aboutsummaryrefslogtreecommitdiff
path: root/rtic-macros/src/codegen/local_resources_struct.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rtic-macros/src/codegen/local_resources_struct.rs')
-rw-r--r--rtic-macros/src/codegen/local_resources_struct.rs102
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)
+}