1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use rtic_syntax::{analyze::Ownership, ast::App};
use crate::{analyze::Analysis, check::Extra, codegen::util};
/// Generates `local` variables and local resource proxies
pub fn codegen(
app: &App,
analysis: &Analysis,
extra: &Extra,
) -> (
// mod_app -- the `static` variables behind the proxies
Vec<TokenStream2>,
// mod_resources -- the `resources` module
TokenStream2,
) {
let mut mod_app = vec![];
let mut mod_resources = vec![];
for (name, res) in app.local_resources {
// let expr = &res.expr; // TODO: Extract from tasks???...
let cfgs = &res.cfgs;
let ty = &res.ty;
let mangled_name = util::mark_internal_ident(&name);
{
// late resources in `util::link_section_uninit`
let section = if expr.is_none() {
util::link_section_uninit(true)
} else {
None
};
// resource type and assigned value
let (ty, expr) = if let Some(expr) = expr {
// early resource
(
quote!(rtic::RacyCell<#ty>),
quote!(rtic::RacyCell::new(#expr)),
)
} else {
// late resource
(
quote!(rtic::RacyCell<core::mem::MaybeUninit<#ty>>),
quote!(rtic::RacyCell::new(core::mem::MaybeUninit::uninit())),
)
};
let attrs = &res.attrs;
// For future use
// let doc = format!(" RTIC internal: {}:{}", file!(), line!());
mod_app.push(quote!(
#[allow(non_upper_case_globals)]
// #[doc = #doc]
#[doc(hidden)]
#(#attrs)*
#(#cfgs)*
#section
static #mangled_name: #ty = #expr;
));
}
let r_prop = &res.properties;
// For future use
// let doc = format!(" RTIC internal: {}:{}", file!(), line!());
if !r_prop.task_local && !r_prop.lock_free {
mod_resources.push(quote!(
// #[doc = #doc]
#[doc(hidden)]
#[allow(non_camel_case_types)]
#(#cfgs)*
pub struct #name<'a> {
priority: &'a Priority,
}
#(#cfgs)*
impl<'a> #name<'a> {
#[inline(always)]
pub unsafe fn new(priority: &'a Priority) -> Self {
#name { priority }
}
#[inline(always)]
pub unsafe fn priority(&self) -> &Priority {
self.priority
}
}
));
let (ptr, _doc) = if expr.is_none() {
// late resource
(
quote!(
#(#cfgs)*
#mangled_name.get_mut_unchecked().as_mut_ptr()
),
"late",
)
} else {
// early resource
(
quote!(
#(#cfgs)*
#mangled_name.get_mut_unchecked()
),
"early",
)
};
let ceiling = match analysis.ownerships.get(name) {
Some(Ownership::Owned { priority }) => *priority,
Some(Ownership::CoOwned { priority }) => *priority,
Some(Ownership::Contended { ceiling }) => *ceiling,
None => 0,
};
// For future use
// let doc = format!(" RTIC internal ({} resource): {}:{}", doc, file!(), line!());
mod_app.push(util::impl_mutex(
extra,
cfgs,
true,
name,
quote!(#ty),
ceiling,
ptr,
));
}
}
let mod_resources = if mod_resources.is_empty() {
quote!()
} else {
quote!(mod resources {
use rtic::export::Priority;
#(#mod_resources)*
})
};
(mod_app, mod_resources)
}
|