aboutsummaryrefslogtreecommitdiff
path: root/macros/src
diff options
context:
space:
mode:
authorGravatar Hugo van der Wijst <hvanderwijst@tesla.com> 2019-01-16 17:36:55 -0800
committerGravatar Jorge Aparicio <jorge@japaric.io> 2019-02-16 00:23:01 +0100
commitbe8a5e89b8c5763dc691bb748ba1da73a56cb2cc (patch)
tree841cc45a9bdadbcaec19a5cac984aa9696f02f2d /macros/src
parent4f193df0efbd45d5d86eccb472fc2312aec3ca94 (diff)
downloadrtic-be8a5e89b8c5763dc691bb748ba1da73a56cb2cc.tar.gz
rtic-be8a5e89b8c5763dc691bb748ba1da73a56cb2cc.tar.zst
rtic-be8a5e89b8c5763dc691bb748ba1da73a56cb2cc.zip
Make identifiers deterministic.
Diffstat (limited to 'macros/src')
-rw-r--r--macros/src/codegen.rs118
1 files changed, 54 insertions, 64 deletions
diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs
index a96eaef9..9eb875c7 100644
--- a/macros/src/codegen.rs
+++ b/macros/src/codegen.rs
@@ -3,8 +3,6 @@
use proc_macro::TokenStream;
use std::{
collections::{BTreeMap, HashMap},
- sync::atomic::{AtomicUsize, Ordering},
- time::{SystemTime, UNIX_EPOCH},
};
use proc_macro2::Span;
@@ -44,6 +42,8 @@ struct Context {
tasks: BTreeMap<Ident, Task>,
// Alias (`struct` / `static mut`)
timer_queue: Ident,
+ // Generator of Ident names or suffixes
+ ident_gen: IdentGenerator,
}
struct Dispatcher {
@@ -63,19 +63,22 @@ struct Task {
impl Default for Context {
fn default() -> Self {
+ let mut ident_gen = IdentGenerator::new();
+
Context {
#[cfg(feature = "timer-queue")]
- baseline: mk_ident(None),
+ baseline: ident_gen.mk_ident(None),
dispatchers: BTreeMap::new(),
- idle: mk_ident(Some("idle")),
- init: mk_ident(Some("init")),
- priority: mk_ident(None),
+ idle: ident_gen.mk_ident(Some("idle")),
+ init: ident_gen.mk_ident(Some("init")),
+ priority: ident_gen.mk_ident(None),
statics: Aliases::new(),
resources: HashMap::new(),
- schedule_enum: mk_ident(None),
+ schedule_enum: ident_gen.mk_ident(None),
schedule_fn: Aliases::new(),
tasks: BTreeMap::new(),
- timer_queue: mk_ident(None),
+ timer_queue: ident_gen.mk_ident(None),
+ ident_gen,
}
}
}
@@ -164,13 +167,13 @@ pub fn app(app: &App, analysis: &Analysis) -> TokenStream {
() => quote!(),
};
- let timer_queue = timer_queue(&ctxt, app, analysis);
+ let timer_queue = timer_queue(&mut ctxt, app, analysis);
let pre_init = pre_init(&ctxt, &app, analysis);
let assertions = assertions(app, analysis);
- let main = mk_ident(None);
+ let main = ctxt.ident_gen.mk_ident(None);
quote!(
#resources
@@ -236,7 +239,7 @@ fn resources(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2:
pub static #mut_ #name: #ty = #expr;
));
- let alias = mk_ident(None);
+ let alias = ctxt.ident_gen.mk_ident(None);
if let Some(Ownership::Shared { ceiling }) = analysis.ownerships.get(name) {
items.push(mk_resource(
ctxt,
@@ -252,7 +255,7 @@ fn resources(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2:
ctxt.statics.insert(name.clone(), alias);
} else {
- let alias = mk_ident(None);
+ let alias = ctxt.ident_gen.mk_ident(None);
let symbol = format!("{}::{}", name, alias);
items.push(
@@ -826,7 +829,7 @@ fn prelude(
#(#cfgs)*
pub #name: &'a #mut_ #name
));
- let alias = mk_ident(None);
+ let alias = ctxt.ident_gen.mk_ident(None);
items.push(quote!(
#(#cfgs)*
let #mut_ #alias = unsafe {
@@ -843,7 +846,7 @@ fn prelude(
#(#cfgs)*
pub #name: rtfm::Exclusive<'a, #name>
));
- let alias = mk_ident(None);
+ let alias = ctxt.ident_gen.mk_ident(None);
items.push(quote!(
#(#cfgs)*
let #mut_ #alias = unsafe {
@@ -910,7 +913,7 @@ fn prelude(
}
}
- let alias = mk_ident(None);
+ let alias = ctxt.ident_gen.mk_ident(None);
let unsafety = if needs_unsafe {
Some(quote!(unsafe))
} else {
@@ -971,7 +974,7 @@ fn prelude(
continue;
}
- ctxt.schedule_fn.insert(task.clone(), mk_ident(None));
+ ctxt.schedule_fn.insert(task.clone(), ctxt.ident_gen.mk_ident(None));
}
items.push(quote!(
@@ -1100,7 +1103,7 @@ fn exceptions(ctxt: &mut Context, app: &App, analysis: &Analysis) -> Vec<proc_ma
let locals = mk_locals(&exception.statics, false);
let symbol = ident.to_string();
- let alias = mk_ident(None);
+ let alias = ctxt.ident_gen.mk_ident(None);
let unsafety = &exception.unsafety;
quote!(
#module
@@ -1179,7 +1182,7 @@ fn interrupts(
};
let locals = mk_locals(&interrupt.statics, false);
- let alias = mk_ident(None);
+ let alias = ctxt.ident_gen.mk_ident(None);
let symbol = ident.to_string();
let unsafety = &interrupt.unsafety;
scoped.push(quote!(
@@ -1213,10 +1216,10 @@ fn tasks(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::Tok
// first pass to generate buffers (statics and resources) and spawn aliases
for (name, task) in &app.tasks {
#[cfg(feature = "timer-queue")]
- let scheduleds_alias = mk_ident(None);
- let free_alias = mk_ident(None);
- let inputs_alias = mk_ident(None);
- let task_alias = mk_ident(Some(&name.to_string()));
+ let scheduleds_alias = ctxt.ident_gen.mk_ident(None);
+ let free_alias = ctxt.ident_gen.mk_ident(None);
+ let inputs_alias = ctxt.ident_gen.mk_ident(None);
+ let task_alias = ctxt.ident_gen.mk_ident(Some(&name.to_string()));
let inputs = &task.inputs;
@@ -1277,7 +1280,7 @@ fn tasks(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::Tok
alias: task_alias,
free_queue: free_alias,
inputs: inputs_alias,
- spawn_fn: mk_ident(None),
+ spawn_fn: ctxt.ident_gen.mk_ident(None),
#[cfg(feature = "timer-queue")]
scheduleds: scheduleds_alias,
@@ -1362,8 +1365,8 @@ fn dispatchers(
let device = &app.args.device;
for (level, dispatcher) in &analysis.dispatchers {
- let ready_alias = mk_ident(None);
- let enum_alias = mk_ident(None);
+ let ready_alias = ctxt.ident_gen.mk_ident(None);
+ let enum_alias = ctxt.ident_gen.mk_ident(None);
let capacity = mk_typenum_capacity(dispatcher.capacity, true);
let variants = dispatcher
@@ -1452,7 +1455,7 @@ fn dispatchers(
let attrs = &dispatcher.attrs;
let interrupt = &dispatcher.interrupt;
let symbol = interrupt.to_string();
- let alias = mk_ident(None);
+ let alias = ctxt.ident_gen.mk_ident(None);
dispatchers.push(quote!(
#(#attrs)*
#[export_name = #symbol]
@@ -1703,7 +1706,7 @@ fn schedule(ctxt: &Context, app: &App) -> proc_macro2::TokenStream {
quote!(#(#items)*)
}
-fn timer_queue(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::TokenStream {
+fn timer_queue(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::TokenStream {
let tasks = &analysis.timer_queue.tasks;
if tasks.is_empty() {
@@ -1778,7 +1781,7 @@ fn timer_queue(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::T
.collect::<Vec<_>>();
let logical_prio = analysis.timer_queue.priority;
- let alias = mk_ident(None);
+ let alias = ctxt.ident_gen.mk_ident(None);
items.push(quote!(
#[export_name = "SysTick"]
#[doc(hidden)]
@@ -1989,48 +1992,35 @@ fn mk_typenum_capacity(capacity: u8, power_of_two: bool) -> proc_macro2::TokenSt
quote!(rtfm::export::consts::#ident)
}
-fn mk_ident(name: Option<&str>) -> Ident {
- static CALL_COUNT: AtomicUsize = AtomicUsize::new(0);
-
- let elapsed = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
-
- let secs = elapsed.as_secs();
- let nanos = elapsed.subsec_nanos();
-
- let count = CALL_COUNT.fetch_add(1, Ordering::SeqCst) as u32;
- let mut seed: [u8; 16] = [0; 16];
-
- for (i, v) in seed.iter_mut().take(8).enumerate() {
- *v = ((secs >> (i * 8)) & 0xFF) as u8
- }
-
- for (i, v) in seed.iter_mut().skip(8).take(4).enumerate() {
- *v = ((nanos >> (i * 8)) & 0xFF) as u8
- }
+struct IdentGenerator {
+ rng: rand::rngs::SmallRng,
+}
- for (i, v) in seed.iter_mut().skip(12).enumerate() {
- *v = ((count >> (i * 8)) & 0xFF) as u8
+impl IdentGenerator {
+ fn new() -> IdentGenerator {
+ IdentGenerator { rng: rand::rngs::SmallRng::seed_from_u64(0) }
}
- let n;
- let mut s = if let Some(name) = name {
- n = 4;
- format!("{}_", name)
- } else {
- n = 16;
- String::new()
- };
-
- let mut rng = rand::rngs::SmallRng::from_seed(seed);
- for i in 0..n {
- if i == 0 || rng.gen() {
- s.push(('a' as u8 + rng.gen::<u8>() % 25) as char)
+ fn mk_ident(&mut self, name: Option<&str>) -> Ident {
+ let n;
+ let mut s = if let Some(name) = name {
+ n = 4;
+ format!("{}_", name)
} else {
- s.push(('0' as u8 + rng.gen::<u8>() % 10) as char)
+ n = 16;
+ String::new()
+ };
+
+ for i in 0..n {
+ if i == 0 || self.rng.gen() {
+ s.push(('a' as u8 + self.rng.gen::<u8>() % 25) as char)
+ } else {
+ s.push(('0' as u8 + self.rng.gen::<u8>() % 10) as char)
+ }
}
- }
- Ident::new(&s, Span::call_site())
+ Ident::new(&s, Span::call_site())
+ }
}
// `once = true` means that these locals will be called from a function that will run *once*