diff options
author | 2023-03-04 21:10:24 +0000 | |
---|---|---|
committer | 2023-03-04 21:10:24 +0000 | |
commit | 7c7d6558f6d9c50fbb4d2487c98c9a5be15f2f7b (patch) | |
tree | 80a47f0dc40059014e9448c4c2eb34c54dff45fe /rtic-macros/src/codegen/local_resources_struct.rs | |
parent | 1c5db277e4161470136dbd2a11e914ff1d383581 (diff) | |
parent | 98c5490d94950608d31cd5ad9dd260f2f853735c (diff) | |
download | rtic-7c7d6558f6d9c50fbb4d2487c98c9a5be15f2f7b.tar.gz rtic-7c7d6558f6d9c50fbb4d2487c98c9a5be15f2f7b.tar.zst rtic-7c7d6558f6d9c50fbb4d2487c98c9a5be15f2f7b.zip |
Merge #694
694: RTIC 2 r=AfoHT a=korken89
Co-authored-by: Emil Fresk <emil.fresk@gmail.com>
Co-authored-by: Per Lindgren <per.lindgren@ltu.se>
Diffstat (limited to 'rtic-macros/src/codegen/local_resources_struct.rs')
-rw-r--r-- | rtic-macros/src/codegen/local_resources_struct.rs | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/rtic-macros/src/codegen/local_resources_struct.rs b/rtic-macros/src/codegen/local_resources_struct.rs new file mode 100644 index 00000000..100c3eb5 --- /dev/null +++ b/rtic-macros/src/codegen/local_resources_struct.rs @@ -0,0 +1,102 @@ +use crate::syntax::{ + ast::{App, TaskLocal}, + Context, +}; +use proc_macro2::TokenStream as TokenStream2; +use quote::quote; + +use crate::codegen::util; + +/// Generates local resources structs +pub fn codegen(ctxt: Context, app: &App) -> (TokenStream2, TokenStream2) { + let resources = match ctxt { + Context::Init => &app.init.args.local_resources, + Context::Idle => { + &app.idle + .as_ref() + .expect("RTIC-ICE: unable to get idle name") + .args + .local_resources + } + Context::HardwareTask(name) => &app.hardware_tasks[name].args.local_resources, + Context::SoftwareTask(name) => &app.software_tasks[name].args.local_resources, + }; + + let task_name = util::get_task_name(ctxt, app); + + let mut fields = vec![]; + let mut values = vec![]; + + for (name, task_local) in resources { + let (cfgs, ty, is_declared) = match task_local { + TaskLocal::External => { + let r = app.local_resources.get(name).expect("UNREACHABLE"); + (&r.cfgs, &r.ty, false) + } + TaskLocal::Declared(r) => (&r.cfgs, &r.ty, true), + }; + + let lt = if ctxt.runs_once() { + quote!('static) + } else { + quote!('a) + }; + + let mangled_name = if matches!(task_local, TaskLocal::External) { + util::static_local_resource_ident(name) + } else { + util::declared_static_local_resource_ident(name, &task_name) + }; + + fields.push(quote!( + #(#cfgs)* + #[allow(missing_docs)] + pub #name: &#lt mut #ty + )); + + let expr = if is_declared { + // If the local resources is already initialized, we only need to access its value and + // not go through an `MaybeUninit` + quote!(&mut *#mangled_name.get_mut()) + } else { + quote!(&mut *(&mut *#mangled_name.get_mut()).as_mut_ptr()) + }; + + values.push(quote!( + #(#cfgs)* + #name: #expr + )); + } + + fields.push(quote!( + #[doc(hidden)] + pub __rtic_internal_marker: ::core::marker::PhantomData<&'a ()> + )); + + values.push(quote!(__rtic_internal_marker: ::core::marker::PhantomData)); + + let doc = format!("Local resources `{}` has access to", ctxt.ident(app)); + let ident = util::local_resources_ident(ctxt, app); + let item = quote!( + #[allow(non_snake_case)] + #[allow(non_camel_case_types)] + #[doc = #doc] + pub struct #ident<'a> { + #(#fields,)* + } + ); + + let constructor = quote!( + impl<'a> #ident<'a> { + #[inline(always)] + #[allow(missing_docs)] + pub unsafe fn new() -> Self { + #ident { + #(#values,)* + } + } + } + ); + + (item, constructor) +} |