Skip to content

Commit 0521155

Browse files
authored
cranelift: Add atomic_rmw to interpreter (#5817) (#5856)
As per the linked issue, atomic_rmw was implemented without specific regard for thread safety. Additionally, the relevant filetest (atomic-rmw-little.clif) was enabled and altered to fix an inccorrect call to test function `%atomic_rmw_and_i64` after setting up test function `%atomic_rmw_and_i32`.
1 parent f6c6bc2 commit 0521155

File tree

2 files changed

+43
-8
lines changed

2 files changed

+43
-8
lines changed

cranelift/filetests/filetests/runtests/atomic-rmw-little.clif

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
test interpret
12
test run
23
target s390x
34
target s390x has_mie2
@@ -116,11 +117,11 @@ block0(v0: i32, v1: i32):
116117
return v4
117118
}
118119

119-
; run: %atomic_rmw_and_i64(0, 0) == 0
120-
; run: %atomic_rmw_and_i64(1, 0) == 0
121-
; run: %atomic_rmw_and_i64(0, 1) == 0
122-
; run: %atomic_rmw_and_i64(1, 1) == 1
123-
; run: %atomic_rmw_and_i64(0xF1FFFEFE, 0xCEFFEFEF) == 0xC0FFEEEE
120+
; run: %atomic_rmw_and_i32(0, 0) == 0
121+
; run: %atomic_rmw_and_i32(1, 0) == 0
122+
; run: %atomic_rmw_and_i32(0, 1) == 0
123+
; run: %atomic_rmw_and_i32(1, 1) == 1
124+
; run: %atomic_rmw_and_i32(0xF1FFFEFE, 0xCEFFEFEF) == 0xC0FFEEEE
124125

125126

126127

cranelift/interpreter/src/step.rs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use crate::value::{Value, ValueConversionKind, ValueError, ValueResult};
77
use cranelift_codegen::data_value::DataValue;
88
use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
99
use 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
};
1313
use log::trace;
1414
use 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

Comments
 (0)