Skip to content

Commit 2b480d3

Browse files
Jules-Bertholetfolkertdev
authored andcommitted
Support #[rustc_align_static] inside thread_local!
1 parent f3b5aae commit 2b480d3

File tree

9 files changed

+119
-36
lines changed

9 files changed

+119
-36
lines changed

library/std/src/sys/thread_local/native/eager.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ enum State {
1010
}
1111

1212
#[allow(missing_debug_implementations)]
13+
#[repr(C)]
1314
pub struct Storage<T> {
14-
state: Cell<State>,
15+
// This field must be first, for correctness of `#[rustc_align_static]`
1516
val: UnsafeCell<T>,
17+
state: Cell<State>,
1618
}
1719

1820
impl<T> Storage<T> {

library/std/src/sys/thread_local/native/lazy.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ enum State<D> {
2727
}
2828

2929
#[allow(missing_debug_implementations)]
30+
#[repr(C)]
3031
pub struct Storage<T, D> {
31-
state: Cell<State<D>>,
32+
// This field must be first, for correctness of `#[rustc_align_static]`
3233
value: UnsafeCell<MaybeUninit<T>>,
34+
state: Cell<State<D>>,
3335
}
3436

3537
impl<T, D> Storage<T, D>

library/std/src/sys/thread_local/native/mod.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,21 +54,23 @@ pub macro thread_local_inner {
5454
// test in `tests/thread.rs` if these types are renamed.
5555

5656
// Used to generate the `LocalKey` value for const-initialized thread locals.
57-
(@key $t:ty, const $init:expr) => {{
57+
(@key $t:ty, $(#[$align_attr:meta])*, const $init:expr) => {{
5858
const __INIT: $t = $init;
5959

6060
unsafe {
6161
$crate::thread::LocalKey::new(const {
6262
if $crate::mem::needs_drop::<$t>() {
6363
|_| {
6464
#[thread_local]
65+
$(#[$align_attr])*
6566
static VAL: $crate::thread::local_impl::EagerStorage<$t>
6667
= $crate::thread::local_impl::EagerStorage::new(__INIT);
6768
VAL.get()
6869
}
6970
} else {
7071
|_| {
7172
#[thread_local]
73+
$(#[$align_attr])*
7274
static VAL: $t = __INIT;
7375
&VAL
7476
}
@@ -78,7 +80,7 @@ pub macro thread_local_inner {
7880
}},
7981

8082
// used to generate the `LocalKey` value for `thread_local!`
81-
(@key $t:ty, $init:expr) => {{
83+
(@key $t:ty, $(#[$align_attr:meta])*, $init:expr) => {{
8284
#[inline]
8385
fn __init() -> $t {
8486
$init
@@ -89,13 +91,15 @@ pub macro thread_local_inner {
8991
if $crate::mem::needs_drop::<$t>() {
9092
|init| {
9193
#[thread_local]
94+
$(#[$align_attr])*
9295
static VAL: $crate::thread::local_impl::LazyStorage<$t, ()>
9396
= $crate::thread::local_impl::LazyStorage::new();
9497
VAL.get_or_init(init, __init)
9598
}
9699
} else {
97100
|init| {
98101
#[thread_local]
102+
$(#[$align_attr])*
99103
static VAL: $crate::thread::local_impl::LazyStorage<$t, !>
100104
= $crate::thread::local_impl::LazyStorage::new();
101105
VAL.get_or_init(init, __init)
@@ -104,9 +108,9 @@ pub macro thread_local_inner {
104108
})
105109
}
106110
}},
107-
($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
111+
($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $(#[$align_attr:meta])*, $($init:tt)*) => {
108112
$(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> =
109-
$crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*);
113+
$crate::thread::local_impl::thread_local_inner!(@key $t, $(#[$align_attr])*, $($init)*);
110114
},
111115
}
112116

library/std/src/sys/thread_local/no_threads.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ use crate::ptr;
1111
#[rustc_macro_transparency = "semitransparent"]
1212
pub macro thread_local_inner {
1313
// used to generate the `LocalKey` value for const-initialized thread locals
14-
(@key $t:ty, const $init:expr) => {{
14+
(@key $t:ty, $(#[$align_attr:meta])*, const $init:expr) => {{
1515
const __INIT: $t = $init;
1616

1717
// NOTE: Please update the shadowing test in `tests/thread.rs` if these types are renamed.
1818
unsafe {
1919
$crate::thread::LocalKey::new(|_| {
20+
$(#[$align_attr])*
2021
static VAL: $crate::thread::local_impl::EagerStorage<$t> =
2122
$crate::thread::local_impl::EagerStorage { value: __INIT };
2223
&VAL.value
@@ -25,7 +26,7 @@ pub macro thread_local_inner {
2526
}},
2627

2728
// used to generate the `LocalKey` value for `thread_local!`
28-
(@key $t:ty, $init:expr) => {{
29+
(@key $t:ty, $(#[$align_attr:meta])*, $init:expr) => {{
2930
#[inline]
3031
fn __init() -> $t { $init }
3132

@@ -34,14 +35,15 @@ pub macro thread_local_inner {
3435
use $crate::thread::local_impl::LazyStorage;
3536

3637
LocalKey::new(|init| {
38+
$(#[$align_attr])*
3739
static VAL: LazyStorage<$t> = LazyStorage::new();
3840
VAL.get(init, __init)
3941
})
4042
}
4143
}},
42-
($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
44+
($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $(#[$align_attr:meta])*, $($init:tt)*) => {
4345
$(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> =
44-
$crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*);
46+
$crate::thread::local_impl::thread_local_inner!(@key $t, $(#[$align_attr])*, $($init)*);
4547
},
4648
}
4749

library/std/src/sys/thread_local/os.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ use crate::ptr;
1111
#[rustc_macro_transparency = "semitransparent"]
1212
pub macro thread_local_inner {
1313
// used to generate the `LocalKey` value for const-initialized thread locals
14-
(@key $t:ty, const $init:expr) => {
15-
$crate::thread::local_impl::thread_local_inner!(@key $t, { const INIT_EXPR: $t = $init; INIT_EXPR })
14+
(@key $t:ty, $(#[$align_attr:meta])*, const $init:expr) => {
15+
$crate::thread::local_impl::thread_local_inner!(@key $t, $(#[$align_attr:meta])*, { const INIT_EXPR: $t = $init; INIT_EXPR })
1616
},
1717

1818
// NOTE: we cannot import `Storage` or `LocalKey` with a `use` because that can shadow user
1919
// provided type or type alias with a matching name. Please update the shadowing test in
2020
// `tests/thread.rs` if these types are renamed.
2121

2222
// used to generate the `LocalKey` value for `thread_local!`.
23-
(@key $t:ty, $init:expr) => {{
23+
(@key $t:ty, $(#[$align_attr:meta])*, $init:expr) => {{
2424
#[inline]
2525
fn __init() -> $t { $init }
2626

@@ -29,15 +29,16 @@ pub macro thread_local_inner {
2929
// in `tests/thread.rs` if these types are renamed.
3030
unsafe {
3131
$crate::thread::LocalKey::new(|init| {
32+
$(#[$align_attr])*
3233
static VAL: $crate::thread::local_impl::Storage<$t>
3334
= $crate::thread::local_impl::Storage::new();
3435
VAL.get(init, __init)
3536
})
3637
}
3738
}},
38-
($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
39+
($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $(#[$align_attr:meta])*, $($init:tt)*) => {
3940
$(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> =
40-
$crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*);
41+
$crate::thread::local_impl::thread_local_inner!(@key $t, $(#[$align_attr])*, $($init)*);
4142
},
4243
}
4344

library/std/src/thread/local.rs

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,44 @@ impl<T: 'static> fmt::Debug for LocalKey<T> {
132132
}
133133
}
134134

135+
#[doc(hidden)]
136+
#[allow_internal_unstable(thread_local_internals)]
137+
#[unstable(feature = "thread_local_internals", issue = "none")]
138+
#[rustc_macro_transparency = "semitransparent"]
139+
pub macro thread_local_process_attrs {
140+
// separate attributes into `rustc_align_static` and everything else
141+
142+
([$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*] #[rustc_align_static $($attr_rest:tt)*] $($tt:tt)*) => (
143+
$crate::thread::local_impl::thread_local_process_attrs!([$($prev_align_attrs)* #[rustc_align_static $($attr_rest)*]] [$($prev_other_attrs)*] $($tt)*);
144+
),
145+
146+
([$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*] #[$attr:meta] $($tt:tt)*) => (
147+
$crate::thread::local_impl::thread_local_process_attrs!([$($prev_align_attrs)*] [$($prev_other_attrs)* #[$attr]] $($tt)*);
148+
),
149+
150+
// delegate to `thread_local_inner` once attributes are categorized
151+
152+
([$($align_attrs:tt)*] [$($other_attrs:tt)*] $vis:vis static $name:ident: $t:ty = const $init:block; $($rest:tt)*) => (
153+
$crate::thread::local_impl::thread_local_inner!($($other_attrs)* $vis $name, $t, $($align_attrs)*, const $init);
154+
$crate::thread_local!($($rest)*);
155+
),
156+
157+
([$($align_attrs:tt)*] [$($other_attrs:tt)*] $vis:vis static $name:ident: $t:ty = const $init:block) => (
158+
$crate::thread::local_impl::thread_local_inner!($($other_attrs)* $vis $name, $t, $($align_attrs)*, const $init);
159+
),
160+
161+
// process multiple declarations
162+
([$($align_attrs:tt)*] [$($other_attrs:tt)*] $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => (
163+
$crate::thread::local_impl::thread_local_inner!($($other_attrs)* $vis $name, $t, $($align_attrs)*, $init);
164+
$crate::thread_local!($($rest)*);
165+
),
166+
167+
// handle a single declaration
168+
([$($align_attrs:tt)*] [$($other_attrs:tt)*] $vis:vis static $name:ident: $t:ty = $init:expr) => (
169+
$crate::thread::local_impl::thread_local_inner!($($other_attrs)* $vis $name, $t, $($align_attrs)*, $init);
170+
),
171+
}
172+
135173
/// Declare a new thread local storage key of type [`std::thread::LocalKey`].
136174
///
137175
/// # Syntax
@@ -185,25 +223,9 @@ macro_rules! thread_local {
185223
// empty (base case for the recursion)
186224
() => {};
187225

188-
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const $init:block; $($rest:tt)*) => (
189-
$crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
190-
$crate::thread_local!($($rest)*);
191-
);
192-
193-
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const $init:block) => (
194-
$crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
195-
);
196-
197-
// process multiple declarations
198-
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => (
199-
$crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, $init);
200-
$crate::thread_local!($($rest)*);
201-
);
202-
203-
// handle a single declaration
204-
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => (
205-
$crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, $init);
206-
);
226+
($($tt:tt)*) => {
227+
$crate::thread::local_impl::thread_local_process_attrs!([] [] $($tt)*);
228+
};
207229
}
208230

209231
/// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with).

library/std/src/thread/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ pub use self::local::{AccessError, LocalKey};
205205
#[doc(hidden)]
206206
#[unstable(feature = "thread_local_internals", issue = "none")]
207207
pub mod local_impl {
208+
pub use super::local::thread_local_process_attrs;
208209
pub use crate::sys::thread_local::*;
209210
}
210211

src/tools/miri/tests/pass/static_align.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,31 @@ static FOO: u64 = 0;
88
#[rustc_align_static(512)]
99
static BAR: u64 = 0;
1010

11+
struct HasDrop;
12+
13+
impl Drop for HasDrop {
14+
fn drop(&mut self) {}
15+
}
16+
17+
thread_local! {
18+
#[rustc_align_static(512)]
19+
static LOCAL: u64 = 0;
20+
21+
#[rustc_align_static(512)]
22+
static CONST_LOCAL: u64 = const { 0 };
23+
24+
#[rustc_align_static(512)]
25+
static HASDROP_LOCAL: HasDrop = HasDrop;
26+
27+
#[rustc_align_static(512)]
28+
static HASDROP_CONST_LOCAL: HasDrop = const { HasDrop };
29+
}
30+
1131
fn main() {
1232
assert!(core::ptr::from_ref(&FOO).addr().is_multiple_of(256));
1333
assert!(core::ptr::from_ref(&BAR).addr().is_multiple_of(512));
34+
LOCAL.with(|local| core::ptr::from_ref(&local).addr().is_multiple_of(512));
35+
CONST_LOCAL.with(|local| core::ptr::from_ref(&local).addr().is_multiple_of(512));
36+
HASDROP_LOCAL.with(|local| core::ptr::from_ref(&local).addr().is_multiple_of(512));
37+
HASDROP_CONST_LOCAL.with(|local| core::ptr::from_ref(&local).addr().is_multiple_of(512));
1438
}

tests/ui/static/static-align.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#[rustc_align_static(64)]
55
static A: u8 = 0;
66

7-
#[rustc_align_static(64)]
7+
#[rustc_align_static(4096)]
88
static B: u8 = 0;
99

1010
#[rustc_align_static(128)]
@@ -17,10 +17,35 @@ unsafe extern "C" {
1717
static C: u64;
1818
}
1919

20+
struct HasDrop;
21+
22+
impl Drop for HasDrop {
23+
fn drop(&mut self) {}
24+
}
25+
26+
thread_local! {
27+
#[rustc_align_static(4096)]
28+
static LOCAL: u64 = 0;
29+
30+
#[rustc_align_static(4096)]
31+
static CONST_LOCAL: u64 = const { 0 };
32+
33+
#[rustc_align_static(4096)]
34+
static HASDROP_LOCAL: HasDrop = HasDrop;
35+
36+
#[rustc_align_static(4096)]
37+
static HASDROP_CONST_LOCAL: HasDrop = const { HasDrop };
38+
}
39+
2040
fn main() {
2141
assert!(core::ptr::from_ref(&A).addr().is_multiple_of(64));
22-
assert!(core::ptr::from_ref(&B).addr().is_multiple_of(64));
42+
assert!(core::ptr::from_ref(&B).addr().is_multiple_of(4096));
2343

2444
assert!(core::ptr::from_ref(&EXPORTED).addr().is_multiple_of(128));
2545
unsafe { assert!(core::ptr::from_ref(&C).addr().is_multiple_of(128)) };
46+
47+
LOCAL.with(|local| core::ptr::from_ref(&local).addr().is_multiple_of(4096));
48+
CONST_LOCAL.with(|local| core::ptr::from_ref(&local).addr().is_multiple_of(4096));
49+
HASDROP_LOCAL.with(|local| core::ptr::from_ref(&local).addr().is_multiple_of(4096));
50+
HASDROP_CONST_LOCAL.with(|local| core::ptr::from_ref(&local).addr().is_multiple_of(4096));
2651
}

0 commit comments

Comments
 (0)