cortex_m_rtic_macros/codegen/
init.rs

1use proc_macro2::TokenStream as TokenStream2;
2use quote::quote;
3use rtic_syntax::{ast::App, Context};
4
5use crate::{
6    analyze::Analysis,
7    check::Extra,
8    codegen::{local_resources_struct, module},
9};
10
11type CodegenResult = (
12    // mod_app_idle -- the `${init}Resources` constructor
13    Option<TokenStream2>,
14    // root_init -- items that must be placed in the root of the crate:
15    // - the `${init}Locals` struct
16    // - the `${init}Resources` struct
17    // - the `${init}LateResources` struct
18    // - the `${init}` module, which contains types like `${init}::Context`
19    Vec<TokenStream2>,
20    // user_init -- the `#[init]` function written by the user
21    TokenStream2,
22    // call_init -- the call to the user `#[init]`
23    TokenStream2,
24);
25
26/// Generates support code for `#[init]` functions
27pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> CodegenResult {
28    let init = &app.init;
29    let mut local_needs_lt = false;
30    let name = &init.name;
31
32    let mut root_init = vec![];
33
34    let context = &init.context;
35    let attrs = &init.attrs;
36    let stmts = &init.stmts;
37    let shared = &init.user_shared_struct;
38    let local = &init.user_local_struct;
39
40    let shared_resources: Vec<_> = app
41        .shared_resources
42        .iter()
43        .map(|(k, v)| {
44            let ty = &v.ty;
45            let cfgs = &v.cfgs;
46            let docs = &v.docs;
47            quote!(
48                #(#cfgs)*
49                #(#docs)*
50                #k: #ty,
51            )
52        })
53        .collect();
54    let local_resources: Vec<_> = app
55        .local_resources
56        .iter()
57        .map(|(k, v)| {
58            let ty = &v.ty;
59            let cfgs = &v.cfgs;
60            let docs = &v.docs;
61            quote!(
62                #(#cfgs)*
63                #(#docs)*
64                #k: #ty,
65            )
66        })
67        .collect();
68
69    let shared_resources_doc = " RTIC shared resource struct".to_string();
70    let local_resources_doc = " RTIC local resource struct".to_string();
71    root_init.push(quote! {
72        #[doc = #shared_resources_doc]
73        struct #shared {
74            #(#shared_resources)*
75        }
76
77        #[doc = #local_resources_doc]
78        struct #local {
79            #(#local_resources)*
80        }
81    });
82
83    let user_init_return = quote! {#shared, #local, #name::Monotonics};
84    let user_init_doc = " User provided init function".to_string();
85
86    let user_init = quote!(
87        #(#attrs)*
88        #[doc = #user_init_doc]
89        #[inline(always)]
90        #[allow(non_snake_case)]
91        fn #name(#context: #name::Context) -> (#user_init_return) {
92            #(#stmts)*
93        }
94    );
95
96    let mut mod_app = None;
97
98    // `${task}Locals`
99    if !init.args.local_resources.is_empty() {
100        let (item, constructor) =
101            local_resources_struct::codegen(Context::Init, &mut local_needs_lt, app);
102
103        root_init.push(item);
104
105        mod_app = Some(constructor);
106    }
107
108    let call_init = quote! {
109        let (shared_resources, local_resources, mut monotonics) = #name(#name::Context::new(core.into()));
110    };
111
112    root_init.push(module::codegen(
113        Context::Init,
114        false,
115        local_needs_lt,
116        app,
117        analysis,
118        extra,
119    ));
120
121    (mod_app, root_init, user_init, call_init)
122}