@@ -526,8 +526,20 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
526526 order : AtomicOrdering ,
527527 _size : Size ,
528528 ) -> & ' ll Value {
529- // Since for any A, A | 0 = A, and performing atomics on constant memory is UB in Rust, we can abuse or to perform atomic reads.
530- self . atomic_rmw ( AtomicRmwBinOp :: AtomicOr , ptr, self . const_int ( ty, 0 ) , order)
529+ // Since for any A, A | 0 = A, and performing atomics on constant memory is UB in Rust, we
530+ // can abuse bitwise-or to perform atomic reads.
531+ //
532+ // njn: is `ty` the type of the loaded value, or the type of the
533+ // pointer to the loaded-from address? i.e. `T` or `*const T`? I'm
534+ // assuming `T`
535+ let ret_ptr = unsafe { llvm:: LLVMRustGetTypeKind ( ty) == llvm:: TypeKind :: Pointer } ;
536+ self . atomic_rmw (
537+ AtomicRmwBinOp :: AtomicOr ,
538+ ptr,
539+ self . const_int ( ty, 0 ) ,
540+ order,
541+ ret_ptr,
542+ )
531543 }
532544
533545 fn load_operand ( & mut self , place : PlaceRef < ' tcx , & ' ll Value > ) -> OperandRef < ' tcx , & ' ll Value > {
@@ -760,7 +772,9 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
760772 _size : Size ,
761773 ) {
762774 // We can exchange *ptr with val, and then discard the result.
763- self . atomic_rmw ( AtomicRmwBinOp :: AtomicXchg , ptr, val, order) ;
775+ let ret_ptr =
776+ unsafe { llvm:: LLVMRustGetTypeKind ( llvm:: LLVMTypeOf ( val) ) == llvm:: TypeKind :: Pointer } ;
777+ self . atomic_rmw ( AtomicRmwBinOp :: AtomicXchg , ptr, val, order, ret_ptr) ;
764778 }
765779
766780 fn gep ( & mut self , ty : & ' ll Type , ptr : & ' ll Value , indices : & [ & ' ll Value ] ) -> & ' ll Value {
@@ -1217,17 +1231,19 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
12171231 let success = self . extract_value ( res, 1 ) ;
12181232 ( val, success)
12191233 }
1234+
12201235 fn atomic_rmw (
12211236 & mut self ,
12221237 op : AtomicRmwBinOp ,
12231238 dst : & ' ll Value ,
12241239 src : & ' ll Value ,
12251240 order : AtomicOrdering ,
1241+ ret_ptr : bool ,
12261242 ) -> & ' ll Value {
12271243 if matches ! ( op, AtomicRmwBinOp :: AtomicNand ) {
12281244 self . fatal ( "Atomic NAND not supported yet!" )
12291245 }
1230- self . atomic_op (
1246+ let mut res = self . atomic_op (
12311247 dst,
12321248 |builder, dst| {
12331249 // We are in a supported address space - just use ordinary atomics
@@ -1243,8 +1259,8 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
12431259 }
12441260 } ,
12451261 |builder, dst| {
1246- // Local space is only accessible to the current thread.
1247- // So, there are no synchronization issues, and we can emulate it using a simple load / compare / store.
1262+ // Local space is only accessible to the current thread. So, there are no
1263+ // synchronization issues, and we can emulate it using a simple load/ compare/ store.
12481264 let load: & ' ll Value =
12491265 unsafe { llvm:: LLVMBuildLoad ( builder. llbuilder , dst, UNNAMED ) } ;
12501266 let next_val = match op {
@@ -1278,7 +1294,17 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
12781294 unsafe { llvm:: LLVMBuildStore ( builder. llbuilder , next_val, dst) } ;
12791295 load
12801296 } ,
1281- )
1297+ ) ;
1298+
1299+ // njn:
1300+ // - copied from rustc_codegen_llvm
1301+ // - but Fractal said: Here, if ret_ptr is true, we should cast dst to *usize, src to
1302+ // usize, and then cast the return value back to a *T(by checking the original type of
1303+ // src).
1304+ if ret_ptr && self . val_ty ( res) != self . type_ptr ( ) {
1305+ res = self . inttoptr ( res, self . type_ptr ( ) ) ;
1306+ }
1307+ res
12821308 }
12831309
12841310 fn atomic_fence (
0 commit comments