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