aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Rahix <rahix@rahix.de> 2022-01-03 11:43:50 +0100
committerGravatar Rahix <rahix@rahix.de> 2022-01-04 17:40:04 +0100
commit68d7f83096379b18bc7610cd064eaf7b8e03608a (patch)
treebee4c38b6e11a88a5daef84908677a21108ef260 /src
parent19125ac052fcba1d67de39be3292e34bd6c6d0f4 (diff)
downloadcortex-m-68d7f83096379b18bc7610cd064eaf7b8e03608a.tar.gz
cortex-m-68d7f83096379b18bc7610cd064eaf7b8e03608a.tar.zst
cortex-m-68d7f83096379b18bc7610cd064eaf7b8e03608a.zip
macros: Don't use Option in singleton!()
As detailed in rust-embedded/cortex-m#364, niche optimization of the `Option` used in the `singleton!()` macro can lead to the initial value of the static to contain non-zero bits. This in turn leads to the whole static being moved from `.bss` to `.data` which means it eats up flash space for no reason. Especially if the singleton stores a particularly large type, this can be quite problematic. Prevent this by using an explicit boolean flag instead of the `Option` type. This is not quite as nice but at least there is no chance for the `singleton!()` to end up in `.data`...
Diffstat (limited to 'src')
-rw-r--r--src/macros.rs17
1 files changed, 9 insertions, 8 deletions
diff --git a/src/macros.rs b/src/macros.rs
index a1ce322..512c932 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -63,10 +63,14 @@ macro_rules! iprintln {
macro_rules! singleton {
($name:ident: $ty:ty = $expr:expr) => {
$crate::interrupt::free(|_| {
- static mut $name: Option<$ty> = None;
+ // this is a tuple of a MaybeUninit and a bool because using an Option here is
+ // problematic: Due to niche-optimization, an Option could end up producing a non-zero
+ // initializer value which would move the entire static from `.bss` into `.data`...
+ static mut $name: (::core::mem::MaybeUninit<$ty>, bool) =
+ (::core::mem::MaybeUninit::uninit(), false);
#[allow(unsafe_code)]
- let used = unsafe { $name.is_some() };
+ let used = unsafe { $name.1 };
if used {
None
} else {
@@ -74,12 +78,9 @@ macro_rules! singleton {
#[allow(unsafe_code)]
unsafe {
- $name = Some(expr)
- }
-
- #[allow(unsafe_code)]
- unsafe {
- $name.as_mut()
+ $name.1 = true;
+ $name.0 = ::core::mem::MaybeUninit::new(expr);
+ Some(&mut *$name.0.as_mut_ptr())
}
}
})