@@ -6,7 +6,7 @@ use libc::{c_char, c_uint};
6
6
use rustc_abi as abi;
7
7
use rustc_abi:: { AddressSpace , Align , HasDataLayout , Size , TargetDataLayout , WrappingRange } ;
8
8
use rustc_codegen_ssa:: MemFlags ;
9
- use rustc_codegen_ssa:: common:: { IntPredicate , RealPredicate , TypeKind } ;
9
+ use rustc_codegen_ssa:: common:: { IntPredicate , RealPredicate , TypeKind , AtomicRmwBinOp } ;
10
10
use rustc_codegen_ssa:: mir:: operand:: { OperandRef , OperandValue } ;
11
11
use rustc_codegen_ssa:: mir:: place:: PlaceRef ;
12
12
use rustc_codegen_ssa:: traits:: * ;
@@ -1195,13 +1195,65 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1195
1195
}
1196
1196
fn atomic_rmw (
1197
1197
& 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 ,
1202
1202
) -> & ' 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
+ )
1205
1257
}
1206
1258
1207
1259
fn atomic_fence (
0 commit comments