cortex_m_rtic_macros/codegen/
local_resources_struct.rs
1use proc_macro2::TokenStream as TokenStream2;
2use quote::quote;
3use rtic_syntax::{
4 ast::{App, TaskLocal},
5 Context,
6};
7
8use crate::codegen::util;
9
10pub fn codegen(ctxt: Context, needs_lt: &mut bool, app: &App) -> (TokenStream2, TokenStream2) {
12 let mut lt = None;
13
14 let resources = match ctxt {
15 Context::Init => &app.init.args.local_resources,
16 Context::Idle => &app.idle.as_ref().unwrap().args.local_resources,
17 Context::HardwareTask(name) => &app.hardware_tasks[name].args.local_resources,
18 Context::SoftwareTask(name) => &app.software_tasks[name].args.local_resources,
19 };
20
21 let task_name = util::get_task_name(ctxt, app);
22
23 let mut fields = vec![];
24 let mut values = vec![];
25 let mut has_cfgs = false;
26
27 for (name, task_local) in resources {
28 let (cfgs, ty, is_declared) = match task_local {
29 TaskLocal::External => {
30 let r = app.local_resources.get(name).expect("UNREACHABLE");
31 (&r.cfgs, &r.ty, false)
32 }
33 TaskLocal::Declared(r) => (&r.cfgs, &r.ty, true),
34 _ => unreachable!(),
35 };
36
37 has_cfgs |= !cfgs.is_empty();
38
39 let lt = if ctxt.runs_once() {
40 quote!('static)
41 } else {
42 lt = Some(quote!('a));
43 quote!('a)
44 };
45
46 let mangled_name = if matches!(task_local, TaskLocal::External) {
47 util::static_local_resource_ident(name)
48 } else {
49 util::declared_static_local_resource_ident(name, &task_name)
50 };
51
52 let local_resource_doc = format!(" Local resource `{name}`");
53 fields.push(quote!(
54 #[doc = #local_resource_doc]
55 #(#cfgs)*
56 pub #name: &#lt mut #ty
57 ));
58
59 let expr = if is_declared {
60 quote!(&mut *#mangled_name.get_mut())
63 } else {
64 quote!(&mut *(&mut *#mangled_name.get_mut()).as_mut_ptr())
65 };
66
67 values.push(quote!(
68 #(#cfgs)*
69 #name: #expr
70 ));
71 }
72
73 if lt.is_some() {
74 *needs_lt = true;
75
76 if has_cfgs {
78 fields.push(quote!(
79 #[doc(hidden)]
80 pub __marker__: core::marker::PhantomData<&'a ()>
81 ));
82
83 values.push(quote!(__marker__: core::marker::PhantomData));
84 }
85 }
86
87 let doc = format!(" Local resources `{}` has access to", ctxt.ident(app));
88 let ident = util::local_resources_ident(ctxt, app);
89 let item = quote!(
90 #[allow(non_snake_case)]
91 #[allow(non_camel_case_types)]
92 #[doc = #doc]
93 pub struct #ident<#lt> {
94 #(#fields,)*
95 }
96 );
97
98 let constructor = quote!(
99 impl<#lt> #ident<#lt> {
100 #[inline(always)]
101 #[doc(hidden)]
102 pub unsafe fn new() -> Self {
103 #ident {
104 #(#values,)*
105 }
106 }
107 }
108 );
109
110 (item, constructor)
111}