Skip to content

Commit ca93c3e

Browse files
authored
Rollup merge of rust-lang#76965 - fusion-engineering-forks:fix-atomic-from-mut, r=Amanieu
Add cfg(target_has_atomic_equal_alignment) and use it for Atomic::from_mut. Fixes some platform-specific problems with rust-lang#74532 by using the actual alignment of the types instead of hardcoding a few `target_arch`s. r? @RalfJung
2 parents 1f8002d + bcc1d56 commit ca93c3e

File tree

8 files changed

+272
-5
lines changed

8 files changed

+272
-5
lines changed

compiler/rustc_feature/src/builtin_attrs.rs

+5
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ const GATED_CFGS: &[GatedCfg] = &[
2626
(sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)),
2727
(sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
2828
(sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
29+
(
30+
sym::target_has_atomic_equal_alignment,
31+
sym::cfg_target_has_atomic,
32+
cfg_fn!(cfg_target_has_atomic),
33+
),
2934
(sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)),
3035
(sym::version, sym::cfg_version, cfg_fn!(cfg_version)),
3136
];

compiler/rustc_session/src/config.rs

+17-4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_data_structures::fx::FxHashSet;
1212
use rustc_data_structures::impl_stable_hash_via_hash;
1313
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
1414

15+
use rustc_target::abi::{Align, TargetDataLayout};
1516
use rustc_target::spec::{Target, TargetTriple};
1617

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

752756
let mut ret = FxHashSet::default();
753757
ret.reserve(6); // the minimum number of insertions
@@ -769,18 +773,27 @@ pub fn default_configuration(sess: &Session) -> CrateConfig {
769773
if sess.target.target.options.has_elf_tls {
770774
ret.insert((sym::target_thread_local, None));
771775
}
772-
for &i in &[8, 16, 32, 64, 128] {
776+
for &(i, align) in &[
777+
(8, layout.i8_align.abi),
778+
(16, layout.i16_align.abi),
779+
(32, layout.i32_align.abi),
780+
(64, layout.i64_align.abi),
781+
(128, layout.i128_align.abi),
782+
] {
773783
if i >= min_atomic_width && i <= max_atomic_width {
774-
let mut insert_atomic = |s| {
784+
let mut insert_atomic = |s, align: Align| {
775785
ret.insert((sym::target_has_atomic_load_store, Some(Symbol::intern(s))));
776786
if atomic_cas {
777787
ret.insert((sym::target_has_atomic, Some(Symbol::intern(s))));
778788
}
789+
if align.bits() == i {
790+
ret.insert((sym::target_has_atomic_equal_alignment, Some(Symbol::intern(s))));
791+
}
779792
};
780793
let s = i.to_string();
781-
insert_atomic(&s);
794+
insert_atomic(&s, align);
782795
if &s == wordsz {
783-
insert_atomic("ptr");
796+
insert_atomic("ptr", layout.pointer_align.abi);
784797
}
785798
}
786799
}

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,7 @@ symbols! {
10711071
target_feature,
10721072
target_feature_11,
10731073
target_has_atomic,
1074+
target_has_atomic_equal_alignment,
10741075
target_has_atomic_load_store,
10751076
target_os,
10761077
target_pointer_width,

library/core/src/sync/atomic.rs

+100
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,28 @@ impl AtomicBool {
327327
unsafe { &mut *(self.v.get() as *mut bool) }
328328
}
329329

330+
/// Get atomic access to a `&mut bool`.
331+
///
332+
/// # Examples
333+
///
334+
/// ```
335+
/// #![feature(atomic_from_mut)]
336+
/// use std::sync::atomic::{AtomicBool, Ordering};
337+
///
338+
/// let mut some_bool = true;
339+
/// let a = AtomicBool::from_mut(&mut some_bool);
340+
/// a.store(false, Ordering::Relaxed);
341+
/// assert_eq!(some_bool, false);
342+
/// ```
343+
#[inline]
344+
#[cfg(target_has_atomic_equal_alignment = "8")]
345+
#[unstable(feature = "atomic_from_mut", issue = "76314")]
346+
pub fn from_mut(v: &mut bool) -> &Self {
347+
// SAFETY: the mutable reference guarantees unique ownership, and
348+
// alignment of both `bool` and `Self` is 1.
349+
unsafe { &*(v as *mut bool as *mut Self) }
350+
}
351+
330352
/// Consumes the atomic and returns the contained value.
331353
///
332354
/// This is safe because passing `self` by value guarantees that no other threads are
@@ -819,6 +841,32 @@ impl<T> AtomicPtr<T> {
819841
self.p.get_mut()
820842
}
821843

844+
/// Get atomic access to a pointer.
845+
///
846+
/// # Examples
847+
///
848+
/// ```
849+
/// #![feature(atomic_from_mut)]
850+
/// use std::sync::atomic::{AtomicPtr, Ordering};
851+
///
852+
/// let mut some_ptr = &mut 123 as *mut i32;
853+
/// let a = AtomicPtr::from_mut(&mut some_ptr);
854+
/// a.store(&mut 456, Ordering::Relaxed);
855+
/// assert_eq!(unsafe { *some_ptr }, 456);
856+
/// ```
857+
#[inline]
858+
#[cfg(target_has_atomic_equal_alignment = "ptr")]
859+
#[unstable(feature = "atomic_from_mut", issue = "76314")]
860+
pub fn from_mut(v: &mut *mut T) -> &Self {
861+
use crate::mem::align_of;
862+
let [] = [(); align_of::<AtomicPtr<()>>() - align_of::<*mut ()>()];
863+
// SAFETY:
864+
// - the mutable reference guarantees unique ownership.
865+
// - the alignment of `*mut T` and `Self` is the same on all platforms
866+
// supported by rust, as verified above.
867+
unsafe { &*(v as *mut *mut T as *mut Self) }
868+
}
869+
822870
/// Consumes the atomic and returns the contained value.
823871
///
824872
/// This is safe because passing `self` by value guarantees that no other threads are
@@ -1113,6 +1161,7 @@ macro_rules! if_not_8_bit {
11131161
#[cfg(target_has_atomic_load_store = "8")]
11141162
macro_rules! atomic_int {
11151163
($cfg_cas:meta,
1164+
$cfg_align:meta,
11161165
$stable:meta,
11171166
$stable_cxchg:meta,
11181167
$stable_debug:meta,
@@ -1231,6 +1280,45 @@ assert_eq!(some_var.load(Ordering::SeqCst), 5);
12311280
}
12321281
}
12331282

1283+
doc_comment! {
1284+
concat!("Get atomic access to a `&mut ", stringify!($int_type), "`.
1285+
1286+
",
1287+
if_not_8_bit! {
1288+
$int_type,
1289+
concat!(
1290+
"**Note:** This function is only available on targets where `",
1291+
stringify!($int_type), "` has an alignment of ", $align, " bytes."
1292+
)
1293+
},
1294+
"
1295+
1296+
# Examples
1297+
1298+
```
1299+
#![feature(atomic_from_mut)]
1300+
", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
1301+
1302+
let mut some_int = 123;
1303+
let a = ", stringify!($atomic_type), "::from_mut(&mut some_int);
1304+
a.store(100, Ordering::Relaxed);
1305+
assert_eq!(some_int, 100);
1306+
```
1307+
"),
1308+
#[inline]
1309+
#[$cfg_align]
1310+
#[unstable(feature = "atomic_from_mut", issue = "76314")]
1311+
pub fn from_mut(v: &mut $int_type) -> &Self {
1312+
use crate::mem::align_of;
1313+
let [] = [(); align_of::<Self>() - align_of::<$int_type>()];
1314+
// SAFETY:
1315+
// - the mutable reference guarantees unique ownership.
1316+
// - the alignment of `$int_type` and `Self` is the
1317+
// same, as promised by $cfg_align and verified above.
1318+
unsafe { &*(v as *mut $int_type as *mut Self) }
1319+
}
1320+
}
1321+
12341322
doc_comment! {
12351323
concat!("Consumes the atomic and returns the contained value.
12361324
@@ -1873,6 +1961,7 @@ let mut atomic = ", stringify!($atomic_type), "::new(1);
18731961
#[cfg(target_has_atomic_load_store = "8")]
18741962
atomic_int! {
18751963
cfg(target_has_atomic = "8"),
1964+
cfg(target_has_atomic_equal_alignment = "8"),
18761965
stable(feature = "integer_atomics_stable", since = "1.34.0"),
18771966
stable(feature = "integer_atomics_stable", since = "1.34.0"),
18781967
stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1891,6 +1980,7 @@ atomic_int! {
18911980
#[cfg(target_has_atomic_load_store = "8")]
18921981
atomic_int! {
18931982
cfg(target_has_atomic = "8"),
1983+
cfg(target_has_atomic_equal_alignment = "8"),
18941984
stable(feature = "integer_atomics_stable", since = "1.34.0"),
18951985
stable(feature = "integer_atomics_stable", since = "1.34.0"),
18961986
stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1909,6 +1999,7 @@ atomic_int! {
19091999
#[cfg(target_has_atomic_load_store = "16")]
19102000
atomic_int! {
19112001
cfg(target_has_atomic = "16"),
2002+
cfg(target_has_atomic_equal_alignment = "16"),
19122003
stable(feature = "integer_atomics_stable", since = "1.34.0"),
19132004
stable(feature = "integer_atomics_stable", since = "1.34.0"),
19142005
stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1927,6 +2018,7 @@ atomic_int! {
19272018
#[cfg(target_has_atomic_load_store = "16")]
19282019
atomic_int! {
19292020
cfg(target_has_atomic = "16"),
2021+
cfg(target_has_atomic_equal_alignment = "16"),
19302022
stable(feature = "integer_atomics_stable", since = "1.34.0"),
19312023
stable(feature = "integer_atomics_stable", since = "1.34.0"),
19322024
stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1945,6 +2037,7 @@ atomic_int! {
19452037
#[cfg(target_has_atomic_load_store = "32")]
19462038
atomic_int! {
19472039
cfg(target_has_atomic = "32"),
2040+
cfg(target_has_atomic_equal_alignment = "32"),
19482041
stable(feature = "integer_atomics_stable", since = "1.34.0"),
19492042
stable(feature = "integer_atomics_stable", since = "1.34.0"),
19502043
stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1963,6 +2056,7 @@ atomic_int! {
19632056
#[cfg(target_has_atomic_load_store = "32")]
19642057
atomic_int! {
19652058
cfg(target_has_atomic = "32"),
2059+
cfg(target_has_atomic_equal_alignment = "32"),
19662060
stable(feature = "integer_atomics_stable", since = "1.34.0"),
19672061
stable(feature = "integer_atomics_stable", since = "1.34.0"),
19682062
stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1981,6 +2075,7 @@ atomic_int! {
19812075
#[cfg(target_has_atomic_load_store = "64")]
19822076
atomic_int! {
19832077
cfg(target_has_atomic = "64"),
2078+
cfg(target_has_atomic_equal_alignment = "64"),
19842079
stable(feature = "integer_atomics_stable", since = "1.34.0"),
19852080
stable(feature = "integer_atomics_stable", since = "1.34.0"),
19862081
stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1999,6 +2094,7 @@ atomic_int! {
19992094
#[cfg(target_has_atomic_load_store = "64")]
20002095
atomic_int! {
20012096
cfg(target_has_atomic = "64"),
2097+
cfg(target_has_atomic_equal_alignment = "64"),
20022098
stable(feature = "integer_atomics_stable", since = "1.34.0"),
20032099
stable(feature = "integer_atomics_stable", since = "1.34.0"),
20042100
stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -2017,6 +2113,7 @@ atomic_int! {
20172113
#[cfg(target_has_atomic_load_store = "128")]
20182114
atomic_int! {
20192115
cfg(target_has_atomic = "128"),
2116+
cfg(target_has_atomic_equal_alignment = "128"),
20202117
unstable(feature = "integer_atomics", issue = "32976"),
20212118
unstable(feature = "integer_atomics", issue = "32976"),
20222119
unstable(feature = "integer_atomics", issue = "32976"),
@@ -2035,6 +2132,7 @@ atomic_int! {
20352132
#[cfg(target_has_atomic_load_store = "128")]
20362133
atomic_int! {
20372134
cfg(target_has_atomic = "128"),
2135+
cfg(target_has_atomic_equal_alignment = "128"),
20382136
unstable(feature = "integer_atomics", issue = "32976"),
20392137
unstable(feature = "integer_atomics", issue = "32976"),
20402138
unstable(feature = "integer_atomics", issue = "32976"),
@@ -2074,6 +2172,7 @@ macro_rules! ptr_width {
20742172
#[cfg(target_has_atomic_load_store = "ptr")]
20752173
atomic_int! {
20762174
cfg(target_has_atomic = "ptr"),
2175+
cfg(target_has_atomic_equal_alignment = "ptr"),
20772176
stable(feature = "rust1", since = "1.0.0"),
20782177
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
20792178
stable(feature = "atomic_debug", since = "1.3.0"),
@@ -2092,6 +2191,7 @@ atomic_int! {
20922191
#[cfg(target_has_atomic_load_store = "ptr")]
20932192
atomic_int! {
20942193
cfg(target_has_atomic = "ptr"),
2194+
cfg(target_has_atomic_equal_alignment = "ptr"),
20952195
stable(feature = "rust1", since = "1.0.0"),
20962196
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
20972197
stable(feature = "atomic_debug", since = "1.3.0"),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// only-x86
2+
// only-linux
3+
4+
fn main() {
5+
core::sync::atomic::AtomicU64::from_mut(&mut 0u64);
6+
//~^ ERROR: no function or associated item named `from_mut` found for struct `AtomicU64`
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0599]: no function or associated item named `from_mut` found for struct `AtomicU64` in the current scope
2+
--> $DIR/atomic-from-mut-not-available.rs:5:36
3+
|
4+
LL | core::sync::atomic::AtomicU64::from_mut(&mut 0u64);
5+
| ^^^^^^^^ function or associated item not found in `AtomicU64`
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0599`.

src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs

+24
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,30 @@ fn main() {
8787
//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
8888
cfg!(target_has_atomic = "ptr");
8989
//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
90+
cfg!(target_has_atomic_load_store = "8");
91+
//~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
92+
cfg!(target_has_atomic_load_store = "16");
93+
//~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
94+
cfg!(target_has_atomic_load_store = "32");
95+
//~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
96+
cfg!(target_has_atomic_load_store = "64");
97+
//~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
98+
cfg!(target_has_atomic_load_store = "128");
99+
//~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
100+
cfg!(target_has_atomic_load_store = "ptr");
101+
//~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
102+
cfg!(target_has_atomic_equal_alignment = "8");
103+
//~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
104+
cfg!(target_has_atomic_equal_alignment = "16");
105+
//~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
106+
cfg!(target_has_atomic_equal_alignment = "32");
107+
//~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
108+
cfg!(target_has_atomic_equal_alignment = "64");
109+
//~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
110+
cfg!(target_has_atomic_equal_alignment = "128");
111+
//~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
112+
cfg!(target_has_atomic_equal_alignment = "ptr");
113+
//~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
90114
}
91115

92116
#[macro_export]

0 commit comments

Comments
 (0)