rtic_macros/codegen/
shared_resources_struct.rs
1use crate::syntax::{ast::App, Context};
2use proc_macro2::TokenStream as TokenStream2;
3use quote::quote;
4
5use crate::codegen::util;
6
7pub fn codegen(ctxt: Context, app: &App) -> (TokenStream2, TokenStream2) {
9 let resources = match ctxt {
10 Context::Init => unreachable!("Tried to generate shared resources struct for init"),
11 Context::Idle => {
12 &app.idle
13 .as_ref()
14 .expect("RTIC-ICE: unable to get idle name")
15 .args
16 .shared_resources
17 }
18 Context::HardwareTask(name) => &app.hardware_tasks[name].args.shared_resources,
19 Context::SoftwareTask(name) => &app.software_tasks[name].args.shared_resources,
20 };
21
22 let mut fields = vec![];
23 let mut values = vec![];
24
25 for (name, access) in resources {
26 let res = app.shared_resources.get(name).expect("UNREACHABLE");
27
28 let cfgs = &res.cfgs;
29
30 let mut_ = if access.is_exclusive() {
32 Some(quote!(mut))
33 } else {
34 None
35 };
36 let ty = &res.ty;
37 let mangled_name = util::static_shared_resource_ident(name);
38 let shared_name = util::need_to_lock_ident(name);
39
40 if res.properties.lock_free {
41 let lt = if ctxt.runs_once() {
43 quote!('static)
44 } else {
45 quote!('a)
46 };
47
48 fields.push(quote!(
49 #(#cfgs)*
50 #[allow(missing_docs)]
51 pub #name: &#lt #mut_ #ty
52 ));
53 } else if access.is_shared() {
54 fields.push(quote!(
55 #(#cfgs)*
56 #[allow(missing_docs)]
57 pub #name: &'a #ty
58 ));
59 } else {
60 fields.push(quote!(
61 #(#cfgs)*
62 #[allow(missing_docs)]
63 pub #name: shared_resources::#shared_name<'a>
64 ));
65
66 values.push(quote!(
67 #(#cfgs)*
68 #name: shared_resources::#shared_name::new()
69
70 ));
71
72 continue;
74 }
75
76 let expr = if access.is_exclusive() {
77 quote!(&mut *(&mut *#mangled_name.get_mut()).as_mut_ptr())
78 } else {
79 quote!(&*(&*#mangled_name.get()).as_ptr())
80 };
81
82 values.push(quote!(
83 #(#cfgs)*
84 #name: #expr
85 ));
86 }
87
88 fields.push(quote!(
89 #[doc(hidden)]
90 pub __rtic_internal_marker: core::marker::PhantomData<&'a ()>
91 ));
92
93 values.push(quote!(__rtic_internal_marker: core::marker::PhantomData));
94
95 let doc = format!("Shared resources `{}` has access to", ctxt.ident(app));
96 let ident = util::shared_resources_ident(ctxt, app);
97 let item = quote!(
98 #[allow(non_snake_case)]
99 #[allow(non_camel_case_types)]
100 #[doc = #doc]
101 pub struct #ident<'a> {
102 #(#fields,)*
103 }
104 );
105
106 let constructor = quote!(
107 impl<'a> #ident<'a> {
108 #[inline(always)]
109 #[allow(missing_docs)]
110 pub unsafe fn new() -> Self {
111 #ident {
112 #(#values,)*
113 }
114 }
115 }
116 );
117
118 (item, constructor)
119}