From 66cb13cb4bf467ea4b6f0efa4c9078c4ea7e665d Mon Sep 17 00:00:00 2001 From: Jan-Justin van Tonder Date: Sat, 25 Feb 2023 15:36:49 +0100 Subject: [PATCH] cranelift: Add atomic_cas to interpreter (#5875) As per issue #5818, atomic_cas was implemented without specific regard for thread safety. --- .../filetests/runtests/atomic-cas-little.clif | 1 + cranelift/interpreter/src/step.rs | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/cranelift/filetests/filetests/runtests/atomic-cas-little.clif b/cranelift/filetests/filetests/runtests/atomic-cas-little.clif index c910befb2b..3bc0f59fa8 100644 --- a/cranelift/filetests/filetests/runtests/atomic-cas-little.clif +++ b/cranelift/filetests/filetests/runtests/atomic-cas-little.clif @@ -1,3 +1,4 @@ +test interpret test run target s390x diff --git a/cranelift/interpreter/src/step.rs b/cranelift/interpreter/src/step.rs index 4f230072a4..e64d90838a 100644 --- a/cranelift/interpreter/src/step.rs +++ b/cranelift/interpreter/src/step.rs @@ -1269,7 +1269,24 @@ where Address::try_from(addr).and_then(|addr| state.checked_store(addr, replace)); assign_or_memtrap(stored.map(|_| prev_val_to_assign)) } - Opcode::AtomicCas => unimplemented!("AtomicCas"), + Opcode::AtomicCas => { + let addr = arg(0)?.into_int()? as u64; + let loaded = Address::try_from(addr).and_then(|addr| state.checked_load(addr, ctrl_ty)); + let loaded_val = match loaded { + Ok(v) => v, + Err(e) => return Ok(ControlFlow::Trap(CraneliftTrap::User(memerror_to_trap(e)))), + }; + let expected_val = arg(1)?; + let val_to_assign = if Value::eq(&loaded_val, &expected_val)? { + let val_to_store = arg(2)?; + Address::try_from(addr) + .and_then(|addr| state.checked_store(addr, val_to_store)) + .map(|_| loaded_val) + } else { + Ok(loaded_val) + }; + assign_or_memtrap(val_to_assign) + } Opcode::AtomicLoad => { let load_ty = inst_context.controlling_type().unwrap(); let addr = arg(0)?.into_int()? as u64;