diff options
author | 2021-07-05 21:40:01 +0200 | |
---|---|---|
committer | 2021-07-05 21:40:01 +0200 | |
commit | 3f85cb5caf1ae930e6551e139978ceec859a2348 (patch) | |
tree | 8c29ac6fa1095f33cf984d2565e2e7bea9504566 /macros/src/codegen/shared_resources_struct.rs | |
parent | 13dc3992e616d817e38c167c4b47db816855f18b (diff) | |
download | rtic-3f85cb5caf1ae930e6551e139978ceec859a2348.tar.gz rtic-3f85cb5caf1ae930e6551e139978ceec859a2348.tar.zst rtic-3f85cb5caf1ae930e6551e139978ceec859a2348.zip |
Started work
Diffstat (limited to 'macros/src/codegen/shared_resources_struct.rs')
-rw-r--r-- | macros/src/codegen/shared_resources_struct.rs | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/macros/src/codegen/shared_resources_struct.rs b/macros/src/codegen/shared_resources_struct.rs new file mode 100644 index 00000000..4bdc8fa1 --- /dev/null +++ b/macros/src/codegen/shared_resources_struct.rs @@ -0,0 +1,131 @@ +use proc_macro2::TokenStream as TokenStream2; +use quote::quote; +use rtic_syntax::{ast::App, Context}; + +use crate::codegen::util; + +/// Generate shared resources structs +pub fn codegen(ctxt: Context, needs_lt: &mut bool, app: &App) -> (TokenStream2, TokenStream2) { + let mut lt = None; + + let resources = match ctxt { + Context::Init => unreachable!("Tried to generate shared resources struct for init"), + Context::Idle => &app.idle.unwrap().args.shared_resources, + Context::HardwareTask(name) => &app.hardware_tasks[name].args.shared_resources, + Context::SoftwareTask(name) => &app.software_tasks[name].args.shared_resources, + }; + + let mut fields = vec![]; + let mut values = vec![]; + let mut has_cfgs = false; + + for (name, access) in resources { + let res = app.shared_resources.get(name).expect("UNREACHABLE"); + + let cfgs = &res.cfgs; + has_cfgs |= !cfgs.is_empty(); + + // access hold if the resource is [x] (exclusive) or [&x] (shared) + let mut_ = if access.is_exclusive() { + Some(quote!(mut)) + } else { + None + }; + let ty = &res.ty; + let mangled_name = util::mark_internal_ident(&name); + + if !res.properties.lock_free { + if access.is_shared() { + lt = Some(quote!('a)); + + fields.push(quote!( + #(#cfgs)* + pub #name: &'a #ty + )); + } else { + // Resource proxy + lt = Some(quote!('a)); + + fields.push(quote!( + #(#cfgs)* + pub #name: resources::#name<'a> + )); + + values.push(quote!( + #(#cfgs)* + #name: resources::#name::new(priority) + + )); + + // continue as the value has been filled, + continue; + } + } else { + let lt = if ctxt.runs_once() { + quote!('static) + } else { + lt = Some(quote!('a)); + quote!('a) + }; + + fields.push(quote!( + #(#cfgs)* + pub #name: &#lt #mut_ #ty + )); + } + + let expr = if access.is_exclusive() { + quote!(&mut *#mangled_name.get_mut_unchecked().as_mut_ptr()) + } else { + quote!(&*#mangled_name.get_unchecked().as_ptr()) + }; + + values.push(quote!( + #(#cfgs)* + #name: #expr + )); + } + + if lt.is_some() { + *needs_lt = true; + + // The struct could end up empty due to `cfg`s leading to an error due to `'a` being unused + if has_cfgs { + fields.push(quote!( + #[doc(hidden)] + pub __marker__: core::marker::PhantomData<&'a ()> + )); + + values.push(quote!(__marker__: core::marker::PhantomData)) + } + } + + let doc = format!("Shared resources `{}` has access to", ctxt.ident(app)); + let ident = util::shared_resources_ident(ctxt, app); + let ident = util::mark_internal_ident(&ident); + let item = quote!( + #[allow(non_snake_case)] + #[doc = #doc] + pub struct #ident<#lt> { + #(#fields,)* + } + ); + + let arg = if ctxt.is_init() { + None + } else { + Some(quote!(priority: &#lt rtic::export::Priority)) + }; + let constructor = quote!( + impl<#lt> #ident<#lt> { + #[inline(always)] + pub unsafe fn new(#arg) -> Self { + #ident { + #(#values,)* + } + } + } + ); + + (item, constructor) +} |