Skip to content

Commit 392ea29

Browse files
committed
Cast pointers to usize before passing them to atomic operations as some platforms do not support atomic operations on pointers.
1 parent 79fb037 commit 392ea29

File tree

2 files changed

+42
-12
lines changed

2 files changed

+42
-12
lines changed

compiler/rustc_codegen_ssa/src/mir/intrinsic.rs

+38-11
Original file line numberDiff line numberDiff line change
@@ -439,14 +439,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
439439
let ty = substs.type_at(0);
440440
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);
@@ -465,8 +469,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
465469
"load" => {
466470
let ty = substs.type_at(0);
467471
if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() {
468-
let size = bx.layout_of(ty).size;
469-
bx.atomic_load(args[0].immediate(), order, size)
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
}
@@ -476,7 +494,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
476494
let ty = substs.type_at(0);
477495
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

+4-1
Original file line numberDiff line numberDiff line change
@@ -1201,7 +1201,10 @@ impl<T> AtomicPtr<T> {
12011201
}
12021202
}
12031203
#[cfg(not(bootstrap))]
1204-
// SAFETY: data races are prevented by atomic intrinsics.
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.
12051208
unsafe {
12061209
atomic_compare_exchange_weak(self.p.get(), current, new, success, failure)
12071210
}

0 commit comments

Comments
 (0)