Skip to content

Commit 5000d3f

Browse files
authored
Rollup merge of rust-lang#141507 - RalfJung:atomic-intrinsics, r=bjorn3
atomic_load intrinsic: use const generic parameter for ordering We have a gazillion intrinsics for the atomics because we encode the ordering into the intrinsic name rather than making it a parameter. This is particularly bad for those operations that take two orderings. Let's fix that! This PR only converts `load`, to see if there's any feedback that would fundamentally change the strategy we pursue for the const generic intrinsics. The first two commits are preparation and could be a separate PR if you prefer. `@BoxyUwU` -- I hope this is a use of const generics that is unlikely to explode? All we need is a const generic of enum type. We could funnel it through an integer if we had to but an enum is obviously nicer... `@bjorn3` it seems like the cranelift backend entirely ignores the ordering?
2 parents 14c399c + 8e60ea9 commit 5000d3f

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

core/src/intrinsics/mod.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
//!
3131
//! The atomic intrinsics provide common atomic operations on machine
3232
//! words, with multiple possible memory orderings. See the
33-
//! [atomic types][crate::sync::atomic] docs for details.
33+
//! [atomic types][atomic] docs for details.
3434
//!
3535
//! # Unwinding
3636
//!
@@ -50,7 +50,7 @@
5050
)]
5151
#![allow(missing_docs)]
5252

53-
use crate::marker::{DiscriminantKind, Tuple};
53+
use crate::marker::{ConstParamTy, DiscriminantKind, Tuple};
5454
use crate::ptr;
5555

5656
pub mod fallback;
@@ -62,6 +62,20 @@ pub mod simd;
6262
#[cfg(all(target_has_atomic = "8", target_has_atomic = "32", target_has_atomic = "ptr"))]
6363
use crate::sync::atomic::{self, AtomicBool, AtomicI32, AtomicIsize, AtomicU32, Ordering};
6464

65+
/// A type for atomic ordering parameters for intrinsics. This is a separate type from
66+
/// `atomic::Ordering` so that we can make it `ConstParamTy` and fix the values used here without a
67+
/// risk of leaking that to stable code.
68+
#[derive(Debug, ConstParamTy, PartialEq, Eq)]
69+
pub enum AtomicOrdering {
70+
// These values must match the compiler's `AtomicOrdering` defined in
71+
// `rustc_middle/src/ty/consts/int.rs`!
72+
Relaxed = 0,
73+
Release = 1,
74+
Acquire = 2,
75+
AcqRel = 3,
76+
SeqCst = 4,
77+
}
78+
6579
// N.B., these intrinsics take raw pointers because they mutate aliased
6680
// memory, which is not valid for either `&` or `&mut`.
6781

@@ -391,6 +405,15 @@ pub unsafe fn atomic_cxchgweak_seqcst_acquire<T: Copy>(dst: *mut T, old: T, src:
391405
#[rustc_nounwind]
392406
pub unsafe fn atomic_cxchgweak_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
393407

408+
/// Loads the current value of the pointer.
409+
/// `T` must be an integer or pointer type.
410+
///
411+
/// The stabilized version of this intrinsic is available on the
412+
/// [`atomic`] types via the `load` method. For example, [`AtomicBool::load`].
413+
#[rustc_intrinsic]
414+
#[rustc_nounwind]
415+
#[cfg(not(bootstrap))]
416+
pub unsafe fn atomic_load<T: Copy, const ORD: AtomicOrdering>(src: *const T) -> T;
394417
/// Loads the current value of the pointer.
395418
/// `T` must be an integer or pointer type.
396419
///
@@ -399,6 +422,7 @@ pub unsafe fn atomic_cxchgweak_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src:
399422
/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::load`].
400423
#[rustc_intrinsic]
401424
#[rustc_nounwind]
425+
#[cfg(bootstrap)]
402426
pub unsafe fn atomic_load_seqcst<T: Copy>(src: *const T) -> T;
403427
/// Loads the current value of the pointer.
404428
/// `T` must be an integer or pointer type.
@@ -408,6 +432,7 @@ pub unsafe fn atomic_load_seqcst<T: Copy>(src: *const T) -> T;
408432
/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::load`].
409433
#[rustc_intrinsic]
410434
#[rustc_nounwind]
435+
#[cfg(bootstrap)]
411436
pub unsafe fn atomic_load_acquire<T: Copy>(src: *const T) -> T;
412437
/// Loads the current value of the pointer.
413438
/// `T` must be an integer or pointer type.
@@ -417,6 +442,7 @@ pub unsafe fn atomic_load_acquire<T: Copy>(src: *const T) -> T;
417442
/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::load`].
418443
#[rustc_intrinsic]
419444
#[rustc_nounwind]
445+
#[cfg(bootstrap)]
420446
pub unsafe fn atomic_load_relaxed<T: Copy>(src: *const T) -> T;
421447

422448
/// Stores the value at the specified memory location.

core/src/sync/atomic.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3822,6 +3822,7 @@ unsafe fn atomic_store<T: Copy>(dst: *mut T, val: T, order: Ordering) {
38223822

38233823
#[inline]
38243824
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3825+
#[cfg(bootstrap)]
38253826
unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
38263827
// SAFETY: the caller must uphold the safety contract for `atomic_load`.
38273828
unsafe {
@@ -3835,6 +3836,23 @@ unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
38353836
}
38363837
}
38373838

3839+
#[inline]
3840+
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3841+
#[cfg(not(bootstrap))]
3842+
unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
3843+
use intrinsics::AtomicOrdering;
3844+
// SAFETY: the caller must uphold the safety contract for `atomic_load`.
3845+
unsafe {
3846+
match order {
3847+
Relaxed => intrinsics::atomic_load::<T, { AtomicOrdering::Relaxed }>(dst),
3848+
Acquire => intrinsics::atomic_load::<T, { AtomicOrdering::Acquire }>(dst),
3849+
SeqCst => intrinsics::atomic_load::<T, { AtomicOrdering::SeqCst }>(dst),
3850+
Release => panic!("there is no such thing as a release load"),
3851+
AcqRel => panic!("there is no such thing as an acquire-release load"),
3852+
}
3853+
}
3854+
}
3855+
38383856
#[inline]
38393857
#[cfg(target_has_atomic)]
38403858
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces

0 commit comments

Comments
 (0)