@@ -7,8 +7,8 @@ use crate::value::{Value, ValueConversionKind, ValueError, ValueResult};
77use cranelift_codegen:: data_value:: DataValue ;
88use cranelift_codegen:: ir:: condcodes:: { FloatCC , IntCC } ;
99use cranelift_codegen:: ir:: {
10- types, AbiParam , Block , BlockCall , ExternalName , FuncRef , Function , InstructionData , Opcode ,
11- TrapCode , Type , Value as ValueRef ,
10+ types, AbiParam , AtomicRmwOp , Block , BlockCall , ExternalName , FuncRef , Function ,
11+ InstructionData , Opcode , TrapCode , Type , Value as ValueRef ,
1212} ;
1313use log:: trace;
1414use smallvec:: { smallvec, SmallVec } ;
@@ -1187,7 +1187,41 @@ where
11871187 Value :: convert ( arg ( 0 ) ?, ValueConversionKind :: ExtractUpper ( types:: I64 ) ) ?,
11881188 ] ) ,
11891189 Opcode :: Iconcat => assign ( Value :: concat ( arg ( 0 ) ?, arg ( 1 ) ?) ?) ,
1190- Opcode :: AtomicRmw => unimplemented ! ( "AtomicRmw" ) ,
1190+ Opcode :: AtomicRmw => {
1191+ let op = inst. atomic_rmw_op ( ) . unwrap ( ) ;
1192+ let val = arg ( 1 ) ?;
1193+ let addr = arg ( 0 ) ?. into_int ( ) ? as u64 ;
1194+ let loaded = Address :: try_from ( addr) . and_then ( |addr| state. checked_load ( addr, ctrl_ty) ) ;
1195+ let prev_val = match loaded {
1196+ Ok ( v) => v,
1197+ Err ( e) => return Ok ( ControlFlow :: Trap ( CraneliftTrap :: User ( memerror_to_trap ( e) ) ) ) ,
1198+ } ;
1199+ let prev_val_to_assign = prev_val. clone ( ) ;
1200+ let replace = match op {
1201+ AtomicRmwOp :: Xchg => Ok ( val) ,
1202+ AtomicRmwOp :: Add => Value :: add ( prev_val, val) ,
1203+ AtomicRmwOp :: Sub => Value :: sub ( prev_val, val) ,
1204+ AtomicRmwOp :: And => Value :: and ( prev_val, val) ,
1205+ AtomicRmwOp :: Or => Value :: or ( prev_val, val) ,
1206+ AtomicRmwOp :: Xor => Value :: xor ( prev_val, val) ,
1207+ AtomicRmwOp :: Nand => Value :: and ( prev_val, val) . and_then ( V :: not) ,
1208+ AtomicRmwOp :: Smax => Value :: max ( prev_val, val) ,
1209+ AtomicRmwOp :: Smin => Value :: min ( prev_val, val) ,
1210+ AtomicRmwOp :: Umax => Value :: max (
1211+ Value :: convert ( val, ValueConversionKind :: ToUnsigned ) ?,
1212+ Value :: convert ( prev_val, ValueConversionKind :: ToUnsigned ) ?,
1213+ )
1214+ . and_then ( |v| Value :: convert ( v, ValueConversionKind :: ToSigned ) ) ,
1215+ AtomicRmwOp :: Umin => Value :: min (
1216+ Value :: convert ( val, ValueConversionKind :: ToUnsigned ) ?,
1217+ Value :: convert ( prev_val, ValueConversionKind :: ToUnsigned ) ?,
1218+ )
1219+ . and_then ( |v| Value :: convert ( v, ValueConversionKind :: ToSigned ) ) ,
1220+ } ?;
1221+ let stored =
1222+ Address :: try_from ( addr) . and_then ( |addr| state. checked_store ( addr, replace) ) ;
1223+ assign_or_memtrap ( stored. map ( |_| prev_val_to_assign) )
1224+ }
11911225 Opcode :: AtomicCas => unimplemented ! ( "AtomicCas" ) ,
11921226 Opcode :: AtomicLoad => {
11931227 let load_ty = inst_context. controlling_type ( ) . unwrap ( ) ;
0 commit comments