@@ -518,8 +518,20 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
518518 order : AtomicOrdering ,
519519 _size : Size ,
520520 ) -> & ' ll Value {
521- // 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.
522- self . atomic_rmw ( AtomicRmwBinOp :: AtomicOr , ptr, self . const_int ( ty, 0 ) , order)
521+ // Since for any A, A | 0 = A, and performing atomics on constant memory is UB in Rust, we
522+ // can abuse bitwise-or to perform atomic reads.
523+ //
524+ // njn: is `ty` the type of the loaded value, or the type of the
525+ // pointer to the loaded-from address? i.e. `T` or `*const T`? I'm
526+ // assuming `T`
527+ let ret_ptr = unsafe { llvm:: LLVMRustGetTypeKind ( ty) == llvm:: TypeKind :: Pointer } ;
528+ self . atomic_rmw (
529+ AtomicRmwBinOp :: AtomicOr ,
530+ ptr,
531+ self . const_int ( ty, 0 ) ,
532+ order,
533+ ret_ptr,
534+ )
523535 }
524536
525537 fn load_operand ( & mut self , place : PlaceRef < ' tcx , & ' ll Value > ) -> OperandRef < ' tcx , & ' ll Value > {
@@ -752,7 +764,9 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
752764 _size : Size ,
753765 ) {
754766 // We can exchange *ptr with val, and then discard the result.
755- self . atomic_rmw ( AtomicRmwBinOp :: AtomicXchg , ptr, val, order) ;
767+ let ret_ptr =
768+ unsafe { llvm:: LLVMRustGetTypeKind ( llvm:: LLVMTypeOf ( val) ) == llvm:: TypeKind :: Pointer } ;
769+ self . atomic_rmw ( AtomicRmwBinOp :: AtomicXchg , ptr, val, order, ret_ptr) ;
756770 }
757771
758772 fn gep ( & mut self , ty : & ' ll Type , ptr : & ' ll Value , indices : & [ & ' ll Value ] ) -> & ' ll Value {
@@ -1209,17 +1223,19 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
12091223 let success = self . extract_value ( res, 1 ) ;
12101224 ( val, success)
12111225 }
1226+
12121227 fn atomic_rmw (
12131228 & mut self ,
12141229 op : AtomicRmwBinOp ,
12151230 dst : & ' ll Value ,
12161231 src : & ' ll Value ,
12171232 order : AtomicOrdering ,
1233+ ret_ptr : bool ,
12181234 ) -> & ' ll Value {
12191235 if matches ! ( op, AtomicRmwBinOp :: AtomicNand ) {
12201236 self . fatal ( "Atomic NAND not supported yet!" )
12211237 }
1222- self . atomic_op (
1238+ let mut res = self . atomic_op (
12231239 dst,
12241240 |builder, dst| {
12251241 // We are in a supported address space - just use ordinary atomics
@@ -1235,8 +1251,8 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
12351251 }
12361252 } ,
12371253 |builder, dst| {
1238- // Local space is only accessible to the current thread.
1239- // So, there are no synchronization issues, and we can emulate it using a simple load / compare / store.
1254+ // Local space is only accessible to the current thread. So, there are no
1255+ // synchronization issues, and we can emulate it using a simple load/ compare/ store.
12401256 let load: & ' ll Value =
12411257 unsafe { llvm:: LLVMBuildLoad ( builder. llbuilder , dst, UNNAMED ) } ;
12421258 let next_val = match op {
@@ -1270,7 +1286,17 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
12701286 unsafe { llvm:: LLVMBuildStore ( builder. llbuilder , next_val, dst) } ;
12711287 load
12721288 } ,
1273- )
1289+ ) ;
1290+
1291+ // njn:
1292+ // - copied from rustc_codegen_llvm
1293+ // - but Fractal said: Here, if ret_ptr is true, we should cast dst to *usize, src to
1294+ // usize, and then cast the return value back to a *T(by checking the original type of
1295+ // src).
1296+ if ret_ptr && self . val_ty ( res) != self . type_ptr ( ) {
1297+ res = self . inttoptr ( res, self . type_ptr ( ) ) ;
1298+ }
1299+ res
12741300 }
12751301
12761302 fn atomic_fence (
0 commit comments