diff options
| author | Trevor Gross <t.gross35@gmail.com> | 2025-08-08 14:22:44 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-08 14:22:44 -0500 |
| commit | 6fa6a854cd791e9efa813e9b18cd1a5337ded971 (patch) | |
| tree | 5da733187115c0091cfda5db93500cd086151107 /src | |
| parent | f5dda197758f7ae94538ef6c2beec21c44a18c7b (diff) | |
| parent | de1b999ff6c981475e4491ea2fff1851655587e5 (diff) | |
| download | rust-6fa6a854cd791e9efa813e9b18cd1a5337ded971.tar.gz rust-6fa6a854cd791e9efa813e9b18cd1a5337ded971.zip | |
Rollup merge of #144192 - RalfJung:atomicrmw-ptr, r=nikic
atomicrmw on pointers: move integer-pointer cast hacks into backend Conceptually, we want to have atomic operations on pointers of the form `fn atomic_add(ptr: *mut T, offset: usize, ...)`. However, LLVM does not directly support such operations (https://github.com/llvm/llvm-project/issues/120837), so we have to cast the `offset` to a pointer somewhere. This PR moves that hack into the LLVM backend, so that the standard library, intrinsic, and Miri all work with the conceptual operation we actually want. Hopefully, one day LLVM will gain a way to represent these operations without integer-pointer casts, and then the hack will disappear entirely. Cc ```@nikic``` -- this is the best we can do right now, right? Fixes https://github.com/rust-lang/rust/issues/134617
Diffstat (limited to 'src')
| -rw-r--r-- | src/tools/miri/src/intrinsics/atomic.rs | 19 | ||||
| -rw-r--r-- | src/tools/miri/src/operator.rs | 8 |
2 files changed, 11 insertions, 16 deletions
diff --git a/src/tools/miri/src/intrinsics/atomic.rs b/src/tools/miri/src/intrinsics/atomic.rs index bcc3e9ec885..e6341252927 100644 --- a/src/tools/miri/src/intrinsics/atomic.rs +++ b/src/tools/miri/src/intrinsics/atomic.rs @@ -105,27 +105,27 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "or" => { - let ord = get_ord_at(1); + let ord = get_ord_at(2); this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitOr, false), rw_ord(ord))?; } "xor" => { - let ord = get_ord_at(1); + let ord = get_ord_at(2); this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitXor, false), rw_ord(ord))?; } "and" => { - let ord = get_ord_at(1); + let ord = get_ord_at(2); this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, false), rw_ord(ord))?; } "nand" => { - let ord = get_ord_at(1); + let ord = get_ord_at(2); this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, true), rw_ord(ord))?; } "xadd" => { - let ord = get_ord_at(1); + let ord = get_ord_at(2); this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Add, false), rw_ord(ord))?; } "xsub" => { - let ord = get_ord_at(1); + let ord = get_ord_at(2); this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Sub, false), rw_ord(ord))?; } "min" => { @@ -231,15 +231,14 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> { let place = this.deref_pointer(place)?; let rhs = this.read_immediate(rhs)?; - if !place.layout.ty.is_integral() && !place.layout.ty.is_raw_ptr() { + if !(place.layout.ty.is_integral() || place.layout.ty.is_raw_ptr()) + || !(rhs.layout.ty.is_integral() || rhs.layout.ty.is_raw_ptr()) + { span_bug!( this.cur_span(), "atomic arithmetic operations only work on integer and raw pointer types", ); } - if rhs.layout.ty != place.layout.ty { - span_bug!(this.cur_span(), "atomic arithmetic operation type mismatch"); - } let old = match atomic_op { AtomicOp::Min => diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs index 73d671121f6..3c3f2c28535 100644 --- a/src/tools/miri/src/operator.rs +++ b/src/tools/miri/src/operator.rs @@ -50,17 +50,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Some more operations are possible with atomics. - // The return value always has the provenance of the *left* operand. + // The RHS must be `usize`. Add | Sub | BitOr | BitAnd | BitXor => { assert!(left.layout.ty.is_raw_ptr()); - assert!(right.layout.ty.is_raw_ptr()); + assert_eq!(right.layout.ty, this.tcx.types.usize); let ptr = left.to_scalar().to_pointer(this)?; // We do the actual operation with usize-typed scalars. let left = ImmTy::from_uint(ptr.addr().bytes(), this.machine.layouts.usize); - let right = ImmTy::from_uint( - right.to_scalar().to_target_usize(this)?, - this.machine.layouts.usize, - ); let result = this.binary_op(bin_op, &left, &right)?; // Construct a new pointer with the provenance of `ptr` (the LHS). let result_ptr = Pointer::new( |
