Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cfg(target_has_atomic_equal_alignment) and use it for Atomic::from_mut. #76965

Merged
merged 8 commits into from
Sep 24, 2020
5 changes: 5 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
@@ -26,6 +26,11 @@ const GATED_CFGS: &[GatedCfg] = &[
(sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)),
(sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
(sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
(
sym::target_has_atomic_equal_alignment,
sym::cfg_target_has_atomic,
cfg_fn!(cfg_target_has_atomic),
),
(sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)),
(sym::version, sym::cfg_version, cfg_fn!(cfg_version)),
];
21 changes: 17 additions & 4 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::impl_stable_hash_via_hash;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};

use rustc_target::abi::{Align, TargetDataLayout};
use rustc_target::spec::{Target, TargetTriple};

use crate::parse::CrateConfig;
@@ -748,6 +749,9 @@ pub fn default_configuration(sess: &Session) -> CrateConfig {
let min_atomic_width = sess.target.target.min_atomic_width();
let max_atomic_width = sess.target.target.max_atomic_width();
let atomic_cas = sess.target.target.options.atomic_cas;
let layout = TargetDataLayout::parse(&sess.target.target).unwrap_or_else(|err| {
sess.fatal(&err);
});

let mut ret = FxHashSet::default();
ret.reserve(6); // the minimum number of insertions
@@ -769,18 +773,27 @@ pub fn default_configuration(sess: &Session) -> CrateConfig {
if sess.target.target.options.has_elf_tls {
ret.insert((sym::target_thread_local, None));
}
for &i in &[8, 16, 32, 64, 128] {
for &(i, align) in &[
(8, layout.i8_align.abi),
(16, layout.i16_align.abi),
(32, layout.i32_align.abi),
(64, layout.i64_align.abi),
(128, layout.i128_align.abi),
] {
if i >= min_atomic_width && i <= max_atomic_width {
let mut insert_atomic = |s| {
let mut insert_atomic = |s, align: Align| {
ret.insert((sym::target_has_atomic_load_store, Some(Symbol::intern(s))));
if atomic_cas {
ret.insert((sym::target_has_atomic, Some(Symbol::intern(s))));
}
if align.bits() == i {
ret.insert((sym::target_has_atomic_equal_alignment, Some(Symbol::intern(s))));
}
};
let s = i.to_string();
insert_atomic(&s);
insert_atomic(&s, align);
if &s == wordsz {
insert_atomic("ptr");
insert_atomic("ptr", layout.pointer_align.abi);
}
}
}
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
@@ -1071,6 +1071,7 @@ symbols! {
target_feature,
target_feature_11,
target_has_atomic,
target_has_atomic_equal_alignment,
target_has_atomic_load_store,
target_os,
target_pointer_width,
100 changes: 100 additions & 0 deletions library/core/src/sync/atomic.rs
Original file line number Diff line number Diff line change
@@ -327,6 +327,28 @@ impl AtomicBool {
unsafe { &mut *(self.v.get() as *mut bool) }
}

/// Get atomic access to a `&mut bool`.
///
/// # Examples
///
/// ```
/// #![feature(atomic_from_mut)]
/// use std::sync::atomic::{AtomicBool, Ordering};
///
/// let mut some_bool = true;
/// let a = AtomicBool::from_mut(&mut some_bool);
/// a.store(false, Ordering::Relaxed);
/// assert_eq!(some_bool, false);
/// ```
#[inline]
#[cfg(target_has_atomic_equal_alignment = "8")]
#[unstable(feature = "atomic_from_mut", issue = "76314")]
pub fn from_mut(v: &mut bool) -> &Self {
// SAFETY: the mutable reference guarantees unique ownership, and
// alignment of both `bool` and `Self` is 1.
unsafe { &*(v as *mut bool as *mut Self) }
}

/// Consumes the atomic and returns the contained value.
///
/// This is safe because passing `self` by value guarantees that no other threads are
@@ -819,6 +841,32 @@ impl<T> AtomicPtr<T> {
self.p.get_mut()
}

/// Get atomic access to a pointer.
///
/// # Examples
///
/// ```
/// #![feature(atomic_from_mut)]
/// use std::sync::atomic::{AtomicPtr, Ordering};
///
/// let mut some_ptr = &mut 123 as *mut i32;
/// let a = AtomicPtr::from_mut(&mut some_ptr);
/// a.store(&mut 456, Ordering::Relaxed);
/// assert_eq!(unsafe { *some_ptr }, 456);
/// ```
#[inline]
#[cfg(target_has_atomic_equal_alignment = "ptr")]
#[unstable(feature = "atomic_from_mut", issue = "76314")]
pub fn from_mut(v: &mut *mut T) -> &Self {
use crate::mem::align_of;
let [] = [(); align_of::<AtomicPtr<()>>() - align_of::<*mut ()>()];
// SAFETY:
// - the mutable reference guarantees unique ownership.
// - the alignment of `*mut T` and `Self` is the same on all platforms
// supported by rust, as verified above.
unsafe { &*(v as *mut *mut T as *mut Self) }
}

/// Consumes the atomic and returns the contained value.
///
/// This is safe because passing `self` by value guarantees that no other threads are
@@ -1113,6 +1161,7 @@ macro_rules! if_not_8_bit {
#[cfg(target_has_atomic_load_store = "8")]
macro_rules! atomic_int {
($cfg_cas:meta,
$cfg_align:meta,
$stable:meta,
$stable_cxchg:meta,
$stable_debug:meta,
@@ -1231,6 +1280,45 @@ assert_eq!(some_var.load(Ordering::SeqCst), 5);
}
}

doc_comment! {
concat!("Get atomic access to a `&mut ", stringify!($int_type), "`.

",
if_not_8_bit! {
$int_type,
concat!(
"**Note:** This function is only available on targets where `",
stringify!($int_type), "` has an alignment of ", $align, " bytes."
)
},
"

# Examples

```
#![feature(atomic_from_mut)]
", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};

let mut some_int = 123;
let a = ", stringify!($atomic_type), "::from_mut(&mut some_int);
a.store(100, Ordering::Relaxed);
assert_eq!(some_int, 100);
```
"),
#[inline]
#[$cfg_align]
#[unstable(feature = "atomic_from_mut", issue = "76314")]
pub fn from_mut(v: &mut $int_type) -> &Self {
use crate::mem::align_of;
let [] = [(); align_of::<Self>() - align_of::<$int_type>()];
// SAFETY:
// - the mutable reference guarantees unique ownership.
// - the alignment of `$int_type` and `Self` is the
// same, as promised by $cfg_align and verified above.
unsafe { &*(v as *mut $int_type as *mut Self) }
}
}

doc_comment! {
concat!("Consumes the atomic and returns the contained value.

@@ -1873,6 +1961,7 @@ let mut atomic = ", stringify!($atomic_type), "::new(1);
#[cfg(target_has_atomic_load_store = "8")]
atomic_int! {
cfg(target_has_atomic = "8"),
cfg(target_has_atomic_equal_alignment = "8"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1891,6 +1980,7 @@ atomic_int! {
#[cfg(target_has_atomic_load_store = "8")]
atomic_int! {
cfg(target_has_atomic = "8"),
cfg(target_has_atomic_equal_alignment = "8"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1909,6 +1999,7 @@ atomic_int! {
#[cfg(target_has_atomic_load_store = "16")]
atomic_int! {
cfg(target_has_atomic = "16"),
cfg(target_has_atomic_equal_alignment = "16"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1927,6 +2018,7 @@ atomic_int! {
#[cfg(target_has_atomic_load_store = "16")]
atomic_int! {
cfg(target_has_atomic = "16"),
cfg(target_has_atomic_equal_alignment = "16"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1945,6 +2037,7 @@ atomic_int! {
#[cfg(target_has_atomic_load_store = "32")]
atomic_int! {
cfg(target_has_atomic = "32"),
cfg(target_has_atomic_equal_alignment = "32"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1963,6 +2056,7 @@ atomic_int! {
#[cfg(target_has_atomic_load_store = "32")]
atomic_int! {
cfg(target_has_atomic = "32"),
cfg(target_has_atomic_equal_alignment = "32"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1981,6 +2075,7 @@ atomic_int! {
#[cfg(target_has_atomic_load_store = "64")]
atomic_int! {
cfg(target_has_atomic = "64"),
cfg(target_has_atomic_equal_alignment = "64"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1999,6 +2094,7 @@ atomic_int! {
#[cfg(target_has_atomic_load_store = "64")]
atomic_int! {
cfg(target_has_atomic = "64"),
cfg(target_has_atomic_equal_alignment = "64"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -2017,6 +2113,7 @@ atomic_int! {
#[cfg(target_has_atomic_load_store = "128")]
atomic_int! {
cfg(target_has_atomic = "128"),
cfg(target_has_atomic_equal_alignment = "128"),
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
@@ -2035,6 +2132,7 @@ atomic_int! {
#[cfg(target_has_atomic_load_store = "128")]
atomic_int! {
cfg(target_has_atomic = "128"),
cfg(target_has_atomic_equal_alignment = "128"),
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
@@ -2074,6 +2172,7 @@ macro_rules! ptr_width {
#[cfg(target_has_atomic_load_store = "ptr")]
atomic_int! {
cfg(target_has_atomic = "ptr"),
cfg(target_has_atomic_equal_alignment = "ptr"),
stable(feature = "rust1", since = "1.0.0"),
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
stable(feature = "atomic_debug", since = "1.3.0"),
@@ -2092,6 +2191,7 @@ atomic_int! {
#[cfg(target_has_atomic_load_store = "ptr")]
atomic_int! {
cfg(target_has_atomic = "ptr"),
cfg(target_has_atomic_equal_alignment = "ptr"),
stable(feature = "rust1", since = "1.0.0"),
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
stable(feature = "atomic_debug", since = "1.3.0"),
7 changes: 7 additions & 0 deletions src/test/ui/atomic-from-mut-not-available.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// only-x86
// only-linux

fn main() {
core::sync::atomic::AtomicU64::from_mut(&mut 0u64);
//~^ ERROR: no function or associated item named `from_mut` found for struct `AtomicU64`
}
9 changes: 9 additions & 0 deletions src/test/ui/atomic-from-mut-not-available.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0599]: no function or associated item named `from_mut` found for struct `AtomicU64` in the current scope
--> $DIR/atomic-from-mut-not-available.rs:5:36
|
LL | core::sync::atomic::AtomicU64::from_mut(&mut 0u64);
| ^^^^^^^^ function or associated item not found in `AtomicU64`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
24 changes: 24 additions & 0 deletions src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs
Original file line number Diff line number Diff line change
@@ -87,6 +87,30 @@ fn main() {
//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
cfg!(target_has_atomic = "ptr");
//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
cfg!(target_has_atomic_load_store = "8");
//~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
cfg!(target_has_atomic_load_store = "16");
//~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
cfg!(target_has_atomic_load_store = "32");
//~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
cfg!(target_has_atomic_load_store = "64");
//~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
cfg!(target_has_atomic_load_store = "128");
//~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
cfg!(target_has_atomic_load_store = "ptr");
//~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
cfg!(target_has_atomic_equal_alignment = "8");
//~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
cfg!(target_has_atomic_equal_alignment = "16");
//~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
cfg!(target_has_atomic_equal_alignment = "32");
//~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
cfg!(target_has_atomic_equal_alignment = "64");
//~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
cfg!(target_has_atomic_equal_alignment = "128");
//~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
cfg!(target_has_atomic_equal_alignment = "ptr");
//~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
}

#[macro_export]
110 changes: 109 additions & 1 deletion src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr
Original file line number Diff line number Diff line change
@@ -160,6 +160,114 @@ LL | cfg!(target_has_atomic = "ptr");
= note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
= help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable

error: aborting due to 18 previous errors
error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-has-atomic.rs:90:10
|
LL | cfg!(target_has_atomic_load_store = "8");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
= help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable

error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-has-atomic.rs:92:10
|
LL | cfg!(target_has_atomic_load_store = "16");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
= help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable

error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-has-atomic.rs:94:10
|
LL | cfg!(target_has_atomic_load_store = "32");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
= help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable

error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-has-atomic.rs:96:10
|
LL | cfg!(target_has_atomic_load_store = "64");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
= help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable

error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-has-atomic.rs:98:10
|
LL | cfg!(target_has_atomic_load_store = "128");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
= help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable

error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-has-atomic.rs:100:10
|
LL | cfg!(target_has_atomic_load_store = "ptr");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
= help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable

error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-has-atomic.rs:102:10
|
LL | cfg!(target_has_atomic_equal_alignment = "8");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
= help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable

error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-has-atomic.rs:104:10
|
LL | cfg!(target_has_atomic_equal_alignment = "16");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
= help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable

error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-has-atomic.rs:106:10
|
LL | cfg!(target_has_atomic_equal_alignment = "32");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
= help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable

error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-has-atomic.rs:108:10
|
LL | cfg!(target_has_atomic_equal_alignment = "64");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
= help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable

error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-has-atomic.rs:110:10
|
LL | cfg!(target_has_atomic_equal_alignment = "128");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
= help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable

error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-has-atomic.rs:112:10
|
LL | cfg!(target_has_atomic_equal_alignment = "ptr");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
= help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable

error: aborting due to 30 previous errors

For more information about this error, try `rustc --explain E0658`.