@@ -6,7 +6,7 @@ use libc::{c_char, c_uint};
66use rustc_abi as abi;
77use rustc_abi:: { AddressSpace , Align , HasDataLayout , Size , TargetDataLayout , WrappingRange } ;
88use rustc_codegen_ssa:: MemFlags ;
9- use rustc_codegen_ssa:: common:: { IntPredicate , RealPredicate , TypeKind } ;
9+ use rustc_codegen_ssa:: common:: { IntPredicate , RealPredicate , TypeKind , AtomicRmwBinOp } ;
1010use rustc_codegen_ssa:: mir:: operand:: { OperandRef , OperandValue } ;
1111use rustc_codegen_ssa:: mir:: place:: PlaceRef ;
1212use rustc_codegen_ssa:: traits:: * ;
@@ -1195,13 +1195,65 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
11951195 }
11961196 fn atomic_rmw (
11971197 & mut self ,
1198- _op : rustc_codegen_ssa :: common :: AtomicRmwBinOp ,
1199- _dst : & ' ll Value ,
1200- _src : & ' ll Value ,
1201- _order : AtomicOrdering ,
1198+ op : AtomicRmwBinOp ,
1199+ dst : & ' ll Value ,
1200+ src : & ' ll Value ,
1201+ order : AtomicOrdering ,
12021202 ) -> & ' ll Value {
1203- // see cmpxchg comment
1204- self . fatal ( "atomic rmw is not supported" )
1203+ if matches ! ( op, AtomicRmwBinOp :: AtomicNand ) {
1204+ self . fatal ( "Atomic NAND not supported yet!" )
1205+ }
1206+ self . atomic_op (
1207+ dst,
1208+ |builder, dst| {
1209+ // We are in a supported address space - just use ordinary atomics
1210+ unsafe {
1211+ llvm:: LLVMBuildAtomicRMW (
1212+ builder. llbuilder ,
1213+ op,
1214+ dst,
1215+ src,
1216+ crate :: llvm:: AtomicOrdering :: from_generic ( order) ,
1217+ 0 ,
1218+ )
1219+ }
1220+ } ,
1221+ |builder, dst| {
1222+ // Local space is only accessible to the current thread.
1223+ // So, there are no synchronization issues, and we can emulate it using a simple load / compare / store.
1224+ let load: & ' ll Value = unsafe { llvm:: LLVMBuildLoad ( builder. llbuilder , dst, UNNAMED ) } ;
1225+ let next_val = match op{
1226+ AtomicRmwBinOp :: AtomicXchg => src,
1227+ AtomicRmwBinOp :: AtomicAdd => builder. add ( load, src) ,
1228+ AtomicRmwBinOp :: AtomicSub => builder. sub ( load, src) ,
1229+ AtomicRmwBinOp :: AtomicAnd => builder. and ( load, src) ,
1230+ AtomicRmwBinOp :: AtomicNand => {
1231+ let and = builder. and ( load, src) ;
1232+ builder. not ( and)
1233+ } ,
1234+ AtomicRmwBinOp :: AtomicOr => builder. or ( load, src) ,
1235+ AtomicRmwBinOp :: AtomicXor => builder. xor ( load, src) ,
1236+ AtomicRmwBinOp :: AtomicMax => {
1237+ let is_src_bigger = builder. icmp ( IntPredicate :: IntSGT , src, load) ;
1238+ builder. select ( is_src_bigger, src, load)
1239+ }
1240+ AtomicRmwBinOp :: AtomicMin => {
1241+ let is_src_smaller = builder. icmp ( IntPredicate :: IntSLT , src, load) ;
1242+ builder. select ( is_src_smaller, src, load)
1243+ }
1244+ AtomicRmwBinOp :: AtomicUMax => {
1245+ let is_src_bigger = builder. icmp ( IntPredicate :: IntUGT , src, load) ;
1246+ builder. select ( is_src_bigger, src, load)
1247+ } ,
1248+ AtomicRmwBinOp :: AtomicUMin => {
1249+ let is_src_smaller = builder. icmp ( IntPredicate :: IntULT , src, load) ;
1250+ builder. select ( is_src_smaller, src, load)
1251+ }
1252+ } ;
1253+ unsafe { llvm:: LLVMBuildStore ( builder. llbuilder , next_val, dst) } ;
1254+ load
1255+ } ,
1256+ )
12051257 }
12061258
12071259 fn atomic_fence (
0 commit comments