lpc55_rtic_macros/codegen/
resources.rs

1use proc_macro2::TokenStream as TokenStream2;
2use quote::quote;
3use rtic_syntax::{
4    analyze::{Location, Ownership},
5    ast::App,
6};
7
8use crate::{analyze::Analysis, check::Extra, codegen::util};
9
10/// Generates `static [mut]` variables and resource proxies
11pub fn codegen(
12    app: &App,
13    analysis: &Analysis,
14    extra: &Extra,
15) -> (
16    // const_app -- the `static [mut]` variables behind the proxies
17    Vec<TokenStream2>,
18    // mod_resources -- the `resources` module
19    TokenStream2,
20) {
21    let mut const_app = vec![];
22    let mut mod_resources = vec![];
23
24    for (name, res, expr, loc) in app.resources(analysis) {
25        let cfgs = &res.cfgs;
26        let ty = &res.ty;
27
28        {
29            let (loc_attr, section) = match loc {
30                Location::Owned {
31                    core,
32                    cross_initialized: false,
33                } => (
34                    util::cfg_core(*core, app.args.cores),
35                    if expr.is_none() {
36                        util::link_section_uninit(Some(*core))
37                    } else {
38                        util::link_section("data", *core)
39                    },
40                ),
41
42                // shared `static`s and cross-initialized resources need to be in `.shared` memory
43                _ => (
44                    if cfg!(feature = "heterogeneous") {
45                        Some(quote!(#[rtic::export::shared]))
46                    } else {
47                        None
48                    },
49                    if expr.is_none() {
50                        util::link_section_uninit(None)
51                    } else {
52                        None
53                    },
54                ),
55            };
56
57            let (ty, expr) = if let Some(expr) = expr {
58                (quote!(#ty), quote!(#expr))
59            } else {
60                (
61                    quote!(core::mem::MaybeUninit<#ty>),
62                    quote!(core::mem::MaybeUninit::uninit()),
63                )
64            };
65
66            let attrs = &res.attrs;
67            const_app.push(quote!(
68                #[allow(non_upper_case_globals)]
69                #(#attrs)*
70                #(#cfgs)*
71                #loc_attr
72                #section
73                static mut #name: #ty = #expr;
74            ));
75        }
76
77        if let Some(Ownership::Contended { ceiling }) = analysis.ownerships.get(name) {
78            let cfg_core = util::cfg_core(loc.core().expect("UNREACHABLE"), app.args.cores);
79
80            mod_resources.push(quote!(
81                #[allow(non_camel_case_types)]
82                #(#cfgs)*
83                #cfg_core
84                pub struct #name<'a> {
85                    priority: &'a Priority,
86                }
87
88                #(#cfgs)*
89                #cfg_core
90                impl<'a> #name<'a> {
91                    #[inline(always)]
92                    pub unsafe fn new(priority: &'a Priority) -> Self {
93                        #name { priority }
94                    }
95
96                    #[inline(always)]
97                    pub unsafe fn priority(&self) -> &Priority {
98                        self.priority
99                    }
100                }
101            ));
102
103            let ptr = if expr.is_none() {
104                quote!(
105                    #(#cfgs)*
106                    #name.as_mut_ptr()
107                )
108            } else {
109                quote!(
110                    #(#cfgs)*
111                    &mut #name
112                )
113            };
114
115            const_app.push(util::impl_mutex(
116                extra,
117                cfgs,
118                cfg_core.as_ref(),
119                true,
120                name,
121                quote!(#ty),
122                *ceiling,
123                ptr,
124            ));
125        }
126    }
127
128    let mod_resources = if mod_resources.is_empty() {
129        quote!()
130    } else {
131        quote!(mod resources {
132            use rtic::export::Priority;
133
134            #(#mod_resources)*
135        })
136    };
137
138    (const_app, mod_resources)
139}