rtic_macros/codegen/
shared_resources.rs

1use crate::syntax::{analyze::Ownership, ast::App};
2use crate::{analyze::Analysis, codegen::util};
3use proc_macro2::TokenStream as TokenStream2;
4use quote::quote;
5
6use super::bindings::impl_mutex;
7
8/// Generates `static` variables and shared resource proxies
9pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {
10    let mut mod_app = vec![];
11    let mut mod_resources = vec![];
12
13    for (name, res) in &app.shared_resources {
14        let cfgs = &res.cfgs;
15        let ty = &res.ty;
16        let mangled_name = &util::static_shared_resource_ident(name);
17
18        let attrs = &res.attrs;
19
20        // late resources in `util::link_section_uninit`
21        // unless user specifies custom link section
22        let section = if attrs
23            .iter()
24            .any(|attr| attr.path().is_ident("link_section"))
25        {
26            None
27        } else {
28            Some(util::link_section_uninit())
29        };
30
31        // For future use
32        // let doc = format!(" RTIC internal: {}:{}", file!(), line!());
33        mod_app.push(quote!(
34            #[allow(non_camel_case_types)]
35            #[allow(non_upper_case_globals)]
36            // #[doc = #doc]
37            #[doc(hidden)]
38            #(#attrs)*
39            #(#cfgs)*
40            #section
41            static #mangled_name: rtic::RacyCell<core::mem::MaybeUninit<#ty>> = rtic::RacyCell::new(core::mem::MaybeUninit::uninit());
42        ));
43
44        // For future use
45        // let doc = format!(" RTIC internal: {}:{}", file!(), line!());
46
47        let shared_name = util::need_to_lock_ident(name);
48
49        if !res.properties.lock_free {
50            mod_resources.push(quote!(
51                // #[doc = #doc]
52                #[doc(hidden)]
53                #[allow(non_camel_case_types)]
54                #(#cfgs)*
55                pub struct #shared_name<'a> {
56                    __rtic_internal_p: ::core::marker::PhantomData<&'a ()>,
57                }
58
59                #(#cfgs)*
60                impl<'a> #shared_name<'a> {
61                    #[inline(always)]
62                    pub unsafe fn new() -> Self {
63                        #shared_name { __rtic_internal_p: ::core::marker::PhantomData }
64                    }
65                }
66            ));
67
68            let ptr = quote!(
69                #(#cfgs)*
70                #mangled_name.get_mut() as *mut _
71            );
72
73            let ceiling = match analysis.ownerships.get(name) {
74                Some(Ownership::Owned { priority } | Ownership::CoOwned { priority }) => *priority,
75                Some(Ownership::Contended { ceiling }) => *ceiling,
76                None => 0,
77            };
78
79            // For future use
80            // let doc = format!(" RTIC internal ({} resource): {}:{}", doc, file!(), line!());
81
82            mod_app.push(impl_mutex(
83                app,
84                analysis,
85                cfgs,
86                true,
87                &shared_name,
88                &quote!(#ty),
89                ceiling,
90                &ptr,
91            ));
92        }
93    }
94
95    let mod_resources = if mod_resources.is_empty() {
96        quote!()
97    } else {
98        quote!(mod shared_resources {
99            #(#mod_resources)*
100        })
101    };
102
103    quote!(
104        #(#mod_app)*
105
106        #mod_resources
107    )
108}