Skip to content

Commit f0f6877

Browse files
committed
Auto merge of rust-lang#77611 - oli-obk:atomic_miri_leakage, r=nagisa
Directly use raw pointers in `AtomicPtr` store/load I was unable to find any reason for this limitation in the latest source of LLVM or in the documentation [here](http://llvm.org/docs/Atomics.html#libcalls-atomic). fixes rust-lang/miri#1574
2 parents c16d52d + 41f988e commit f0f6877

File tree

4 files changed

+73
-30
lines changed

4 files changed

+73
-30
lines changed

compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,12 @@ macro atomic_minmax($fx:expr, $cc:expr, <$T:ident> ($ptr:ident, $src:ident) -> $
146146

147147
macro validate_atomic_type($fx:ident, $intrinsic:ident, $span:ident, $ty:expr) {
148148
match $ty.kind() {
149-
ty::Uint(_) | ty::Int(_) => {}
149+
ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
150150
_ => {
151151
$fx.tcx.sess.span_err(
152152
$span,
153153
&format!(
154-
"`{}` intrinsic: expected basic integer type, found `{:?}`",
154+
"`{}` intrinsic: expected basic integer or raw pointer type, found `{:?}`",
155155
$intrinsic, $ty
156156
),
157157
);

compiler/rustc_codegen_ssa/src/mir/intrinsic.rs

+41-14
Original file line numberDiff line numberDiff line change
@@ -437,16 +437,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
437437
match split[1] {
438438
"cxchg" | "cxchgweak" => {
439439
let ty = substs.type_at(0);
440-
if int_type_width_signed(ty, bx.tcx()).is_some() {
440+
if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() {
441441
let weak = split[1] == "cxchgweak";
442-
let pair = bx.atomic_cmpxchg(
443-
args[0].immediate(),
444-
args[1].immediate(),
445-
args[2].immediate(),
446-
order,
447-
failorder,
448-
weak,
449-
);
442+
let mut dst = args[0].immediate();
443+
let mut cmp = args[1].immediate();
444+
let mut src = args[2].immediate();
445+
if ty.is_unsafe_ptr() {
446+
// Some platforms do not support atomic operations on pointers,
447+
// so we cast to integer first.
448+
let ptr_llty = bx.type_ptr_to(bx.type_isize());
449+
dst = bx.pointercast(dst, ptr_llty);
450+
cmp = bx.ptrtoint(cmp, bx.type_isize());
451+
src = bx.ptrtoint(src, bx.type_isize());
452+
}
453+
let pair = bx.atomic_cmpxchg(dst, cmp, src, order, failorder, weak);
450454
let val = bx.extract_value(pair, 0);
451455
let success = bx.extract_value(pair, 1);
452456
let val = bx.from_immediate(val);
@@ -464,19 +468,42 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
464468

465469
"load" => {
466470
let ty = substs.type_at(0);
467-
if int_type_width_signed(ty, bx.tcx()).is_some() {
468-
let size = bx.layout_of(ty).size;
469-
bx.atomic_load(args[0].immediate(), order, size)
471+
if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() {
472+
let layout = bx.layout_of(ty);
473+
let size = layout.size;
474+
let mut source = args[0].immediate();
475+
if ty.is_unsafe_ptr() {
476+
// Some platforms do not support atomic operations on pointers,
477+
// so we cast to integer first...
478+
let ptr_llty = bx.type_ptr_to(bx.type_isize());
479+
source = bx.pointercast(source, ptr_llty);
480+
}
481+
let result = bx.atomic_load(source, order, size);
482+
if ty.is_unsafe_ptr() {
483+
// ... and then cast the result back to a pointer
484+
bx.inttoptr(result, bx.backend_type(layout))
485+
} else {
486+
result
487+
}
470488
} else {
471489
return invalid_monomorphization(ty);
472490
}
473491
}
474492

475493
"store" => {
476494
let ty = substs.type_at(0);
477-
if int_type_width_signed(ty, bx.tcx()).is_some() {
495+
if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() {
478496
let size = bx.layout_of(ty).size;
479-
bx.atomic_store(args[1].immediate(), args[0].immediate(), order, size);
497+
let mut val = args[1].immediate();
498+
let mut ptr = args[0].immediate();
499+
if ty.is_unsafe_ptr() {
500+
// Some platforms do not support atomic operations on pointers,
501+
// so we cast to integer first.
502+
let ptr_llty = bx.type_ptr_to(bx.type_isize());
503+
ptr = bx.pointercast(ptr, ptr_llty);
504+
val = bx.ptrtoint(val, bx.type_isize());
505+
}
506+
bx.atomic_store(val, ptr, order, size);
480507
return;
481508
} else {
482509
return invalid_monomorphization(ty);

library/core/src/sync/atomic.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -966,8 +966,16 @@ impl<T> AtomicPtr<T> {
966966
#[inline]
967967
#[stable(feature = "rust1", since = "1.0.0")]
968968
pub fn load(&self, order: Ordering) -> *mut T {
969+
#[cfg(not(bootstrap))]
969970
// SAFETY: data races are prevented by atomic intrinsics.
970-
unsafe { atomic_load(self.p.get() as *mut usize, order) as *mut T }
971+
unsafe {
972+
atomic_load(self.p.get(), order)
973+
}
974+
#[cfg(bootstrap)]
975+
// SAFETY: data races are prevented by atomic intrinsics.
976+
unsafe {
977+
atomic_load(self.p.get() as *mut usize, order) as *mut T
978+
}
971979
}
972980

973981
/// Stores a value into the pointer.
@@ -994,6 +1002,12 @@ impl<T> AtomicPtr<T> {
9941002
#[inline]
9951003
#[stable(feature = "rust1", since = "1.0.0")]
9961004
pub fn store(&self, ptr: *mut T, order: Ordering) {
1005+
#[cfg(not(bootstrap))]
1006+
// SAFETY: data races are prevented by atomic intrinsics.
1007+
unsafe {
1008+
atomic_store(self.p.get(), ptr, order);
1009+
}
1010+
#[cfg(bootstrap)]
9971011
// SAFETY: data races are prevented by atomic intrinsics.
9981012
unsafe {
9991013
atomic_store(self.p.get() as *mut usize, ptr as usize, order);
@@ -1105,6 +1119,7 @@ impl<T> AtomicPtr<T> {
11051119
success: Ordering,
11061120
failure: Ordering,
11071121
) -> Result<*mut T, *mut T> {
1122+
#[cfg(bootstrap)]
11081123
// SAFETY: data races are prevented by atomic intrinsics.
11091124
unsafe {
11101125
let res = atomic_compare_exchange(
@@ -1119,6 +1134,11 @@ impl<T> AtomicPtr<T> {
11191134
Err(x) => Err(x as *mut T),
11201135
}
11211136
}
1137+
#[cfg(not(bootstrap))]
1138+
// SAFETY: data races are prevented by atomic intrinsics.
1139+
unsafe {
1140+
atomic_compare_exchange(self.p.get(), current, new, success, failure)
1141+
}
11221142
}
11231143

11241144
/// Stores a value into the pointer if the current value is the same as the `current` value.
@@ -1165,6 +1185,7 @@ impl<T> AtomicPtr<T> {
11651185
success: Ordering,
11661186
failure: Ordering,
11671187
) -> Result<*mut T, *mut T> {
1188+
#[cfg(bootstrap)]
11681189
// SAFETY: data races are prevented by atomic intrinsics.
11691190
unsafe {
11701191
let res = atomic_compare_exchange_weak(
@@ -1179,6 +1200,14 @@ impl<T> AtomicPtr<T> {
11791200
Err(x) => Err(x as *mut T),
11801201
}
11811202
}
1203+
#[cfg(not(bootstrap))]
1204+
// SAFETY: This intrinsic is unsafe because it operates on a raw pointer
1205+
// but we know for sure that the pointer is valid (we just got it from
1206+
// an `UnsafeCell` that we have by reference) and the atomic operation
1207+
// itself allows us to safely mutate the `UnsafeCell` contents.
1208+
unsafe {
1209+
atomic_compare_exchange_weak(self.p.get(), current, new, success, failure)
1210+
}
11821211
}
11831212

11841213
/// Fetches the value, and applies a function to it that returns an optional

library/std/src/sys/windows/thread_local_key.rs

-13
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,6 @@ struct Node {
110110
next: *mut Node,
111111
}
112112

113-
#[cfg(miri)]
114-
extern "Rust" {
115-
/// Miri-provided extern function to mark the block `ptr` points to as a "root"
116-
/// for some static memory. This memory and everything reachable by it is not
117-
/// considered leaking even if it still exists when the program terminates.
118-
///
119-
/// `ptr` has to point to the beginning of an allocated block.
120-
fn miri_static_root(ptr: *const u8);
121-
}
122-
123113
unsafe fn register_dtor(key: Key, dtor: Dtor) {
124114
let mut node = Box::new(Node { key, dtor, next: ptr::null_mut() });
125115

@@ -128,9 +118,6 @@ unsafe fn register_dtor(key: Key, dtor: Dtor) {
128118
node.next = head;
129119
match DTORS.compare_exchange(head, &mut *node, SeqCst, SeqCst) {
130120
Ok(_) => {
131-
#[cfg(miri)]
132-
miri_static_root(&*node as *const _ as *const u8);
133-
134121
mem::forget(node);
135122
return;
136123
}

0 commit comments

Comments
 (0)