Skip to content

Commit 7cae1f4

Browse files
authored
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 (llvm/llvm-project#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 rust-lang/rust#134617
2 parents 89b33fd + 3062a47 commit 7cae1f4

File tree

2 files changed

+11
-16
lines changed

2 files changed

+11
-16
lines changed

src/intrinsics/atomic.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,27 +105,27 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
105105
}
106106

107107
"or" => {
108-
let ord = get_ord_at(1);
108+
let ord = get_ord_at(2);
109109
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitOr, false), rw_ord(ord))?;
110110
}
111111
"xor" => {
112-
let ord = get_ord_at(1);
112+
let ord = get_ord_at(2);
113113
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitXor, false), rw_ord(ord))?;
114114
}
115115
"and" => {
116-
let ord = get_ord_at(1);
116+
let ord = get_ord_at(2);
117117
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, false), rw_ord(ord))?;
118118
}
119119
"nand" => {
120-
let ord = get_ord_at(1);
120+
let ord = get_ord_at(2);
121121
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, true), rw_ord(ord))?;
122122
}
123123
"xadd" => {
124-
let ord = get_ord_at(1);
124+
let ord = get_ord_at(2);
125125
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Add, false), rw_ord(ord))?;
126126
}
127127
"xsub" => {
128-
let ord = get_ord_at(1);
128+
let ord = get_ord_at(2);
129129
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Sub, false), rw_ord(ord))?;
130130
}
131131
"min" => {
@@ -231,15 +231,14 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
231231
let place = this.deref_pointer(place)?;
232232
let rhs = this.read_immediate(rhs)?;
233233

234-
if !place.layout.ty.is_integral() && !place.layout.ty.is_raw_ptr() {
234+
if !(place.layout.ty.is_integral() || place.layout.ty.is_raw_ptr())
235+
|| !(rhs.layout.ty.is_integral() || rhs.layout.ty.is_raw_ptr())
236+
{
235237
span_bug!(
236238
this.cur_span(),
237239
"atomic arithmetic operations only work on integer and raw pointer types",
238240
);
239241
}
240-
if rhs.layout.ty != place.layout.ty {
241-
span_bug!(this.cur_span(), "atomic arithmetic operation type mismatch");
242-
}
243242

244243
let old = match atomic_op {
245244
AtomicOp::Min =>

src/operator.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
5050
}
5151

5252
// Some more operations are possible with atomics.
53-
// The return value always has the provenance of the *left* operand.
53+
// The RHS must be `usize`.
5454
Add | Sub | BitOr | BitAnd | BitXor => {
5555
assert!(left.layout.ty.is_raw_ptr());
56-
assert!(right.layout.ty.is_raw_ptr());
56+
assert_eq!(right.layout.ty, this.tcx.types.usize);
5757
let ptr = left.to_scalar().to_pointer(this)?;
5858
// We do the actual operation with usize-typed scalars.
5959
let left = ImmTy::from_uint(ptr.addr().bytes(), this.machine.layouts.usize);
60-
let right = ImmTy::from_uint(
61-
right.to_scalar().to_target_usize(this)?,
62-
this.machine.layouts.usize,
63-
);
6460
let result = this.binary_op(bin_op, &left, &right)?;
6561
// Construct a new pointer with the provenance of `ptr` (the LHS).
6662
let result_ptr = Pointer::new(

0 commit comments

Comments
 (0)