From d30209fa372831d819607e6a324b7512f8d1cfaa Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 23 Jan 2018 20:27:06 +0100 Subject: [PATCH 1/3] initialize singletons at runtime --- Cargo.toml | 3 ++- src/lib.rs | 2 ++ src/macros.rs | 5 +++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5885c6b8..82712ee3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ version = "0.4.2" aligned = "0.1.1" bare-metal = "0.1.0" volatile-register = "0.2.0" +untagged-option = "0.1.1" [features] -cm7-r0p1 = [] \ No newline at end of file +cm7-r0p1 = [] diff --git a/src/lib.rs b/src/lib.rs index 694d1b27..6af60d7b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,7 @@ extern crate aligned; extern crate bare_metal; +extern crate untagged_option; extern crate volatile_register; #[macro_use] @@ -31,3 +32,4 @@ pub mod peripheral; pub mod register; pub use peripheral::Peripherals; +pub use untagged_option::UntaggedOption; diff --git a/src/macros.rs b/src/macros.rs index c9a32c23..c5799bf9 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -54,13 +54,14 @@ macro_rules! singleton { (: $ty:ty = $expr:expr) => { $crate::interrupt::free(|_| unsafe { static mut USED: bool = false; - static mut VAR: $ty = $expr; + static mut VAR: $crate::UntaggedOption<$ty> = $crate::UntaggedOption { none: () }; if USED { None } else { USED = true; - let var: &'static mut _ = &mut VAR; + VAR.some = $expr; + let var: &'static mut _ = &mut VAR.some; Some(var) } }) From d3940ec95cca6673c919f37c319170019374da88 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 23 Jan 2018 22:54:12 +0100 Subject: [PATCH 2/3] singleton!: check that calls to unsafe functions require an unsafe block --- src/macros.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index c5799bf9..45c511cb 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -43,6 +43,9 @@ macro_rules! iprintln { /// let y = alias(); /// // BAD this second call to `alias` will definitively `panic!` /// let y_alias = alias(); +/// +/// # // check that the call to `uninitialized` requires unsafe +/// # singleton!(: u8 = unsafe { std::mem::uninitialized() }); /// } /// /// fn alias() -> &'static mut bool { @@ -52,16 +55,17 @@ macro_rules! iprintln { #[macro_export] macro_rules! singleton { (: $ty:ty = $expr:expr) => { - $crate::interrupt::free(|_| unsafe { + $crate::interrupt::free(|_| { static mut USED: bool = false; static mut VAR: $crate::UntaggedOption<$ty> = $crate::UntaggedOption { none: () }; - if USED { + if unsafe { USED } { None } else { - USED = true; - VAR.some = $expr; - let var: &'static mut _ = &mut VAR.some; + unsafe { USED = true } + let expr = $expr; + unsafe { VAR.some = expr } + let var: &'static mut _ = unsafe { &mut VAR.some }; Some(var) } }) From 032af4b2b914f42b5533358cd2f40bbc7a888256 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Thu, 25 Jan 2018 20:41:44 +0100 Subject: [PATCH 3/3] don't trip the unsafe_code lint --- src/macros.rs | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 45c511cb..7d2cf6aa 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -43,9 +43,6 @@ macro_rules! iprintln { /// let y = alias(); /// // BAD this second call to `alias` will definitively `panic!` /// let y_alias = alias(); -/// -/// # // check that the call to `uninitialized` requires unsafe -/// # singleton!(: u8 = unsafe { std::mem::uninitialized() }); /// } /// /// fn alias() -> &'static mut bool { @@ -59,15 +56,55 @@ macro_rules! singleton { static mut USED: bool = false; static mut VAR: $crate::UntaggedOption<$ty> = $crate::UntaggedOption { none: () }; - if unsafe { USED } { + + #[allow(unsafe_code)] + let used = unsafe { USED }; + if used { None } else { + #[allow(unsafe_code)] unsafe { USED = true } + let expr = $expr; + + #[allow(unsafe_code)] unsafe { VAR.some = expr } + + #[allow(unsafe_code)] let var: &'static mut _ = unsafe { &mut VAR.some }; + Some(var) } }) } } + + +/// ``` compile_fail +/// #[macro_use(singleton)] +/// extern crate cortex_m; +/// +/// fn main() {} +/// +/// fn foo() { +/// // check that the call to `uninitialized` requires unsafe +/// singleton!(: u8 = std::mem::uninitialized()); +/// } +/// ``` +#[allow(dead_code)] +const CFAIL: () = (); + +/// ``` +/// #![deny(unsafe_code)] +/// #[macro_use(singleton)] +/// extern crate cortex_m; +/// +/// fn main() {} +/// +/// fn foo() { +/// // check that calls to `singleton!` don't trip the `unsafe_code` lint +/// singleton!(: u8 = 0); +/// } +/// ``` +#[allow(dead_code)] +const CPASS: () = ();