aboutsummaryrefslogtreecommitdiff
path: root/rtic/macros/src/codegen/shared_resources_struct.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rtic/macros/src/codegen/shared_resources_struct.rs')
-rw-r--r--rtic/macros/src/codegen/shared_resources_struct.rs119
1 files changed, 119 insertions, 0 deletions
diff --git a/rtic/macros/src/codegen/shared_resources_struct.rs b/rtic/macros/src/codegen/shared_resources_struct.rs
new file mode 100644
index 00000000..fa6f0fcb
--- /dev/null
+++ b/rtic/macros/src/codegen/shared_resources_struct.rs
@@ -0,0 +1,119 @@
+use crate::syntax::{ast::App, Context};
+use proc_macro2::TokenStream as TokenStream2;
+use quote::quote;
+
+use crate::codegen::util;
+
+/// Generate shared resources structs
+pub fn codegen(ctxt: Context, app: &App) -> (TokenStream2, TokenStream2) {
+ let resources = match ctxt {
+ Context::Init => unreachable!("Tried to generate shared resources struct for init"),
+ Context::Idle => {
+ &app.idle
+ .as_ref()
+ .expect("RTIC-ICE: unable to get idle name")
+ .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![];
+
+ for (name, access) in resources {
+ let res = app.shared_resources.get(name).expect("UNREACHABLE");
+
+ let cfgs = &res.cfgs;
+
+ // 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::static_shared_resource_ident(name);
+ let shared_name = util::need_to_lock_ident(name);
+
+ if res.properties.lock_free {
+ // Lock free resources of `idle` and `init` get 'static lifetime
+ let lt = if ctxt.runs_once() {
+ quote!('static)
+ } else {
+ quote!('a)
+ };
+
+ fields.push(quote!(
+ #(#cfgs)*
+ #[allow(missing_docs)]
+ pub #name: &#lt #mut_ #ty
+ ));
+ } else if access.is_shared() {
+ fields.push(quote!(
+ #(#cfgs)*
+ #[allow(missing_docs)]
+ pub #name: &'a #ty
+ ));
+ } else {
+ fields.push(quote!(
+ #(#cfgs)*
+ #[allow(missing_docs)]
+ pub #name: shared_resources::#shared_name<'a>
+ ));
+
+ values.push(quote!(
+ #(#cfgs)*
+ #name: shared_resources::#shared_name::new()
+
+ ));
+
+ // continue as the value has been filled,
+ continue;
+ }
+
+ let expr = if access.is_exclusive() {
+ quote!(&mut *(&mut *#mangled_name.get_mut()).as_mut_ptr())
+ } else {
+ quote!(&*(&*#mangled_name.get()).as_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!("Shared resources `{}` has access to", ctxt.ident(app));
+ let ident = util::shared_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)
+}