cortex_m_rtic_macros/codegen/
assertions.rs

1use proc_macro2::TokenStream as TokenStream2;
2use quote::quote;
3
4use crate::{analyze::Analysis, check::Extra, codegen::util};
5use rtic_syntax::ast::App;
6
7/// Generates compile-time assertions that check that types implement the `Send` / `Sync` traits
8pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2> {
9    let mut stmts = vec![];
10
11    for ty in &analysis.send_types {
12        stmts.push(quote!(rtic::export::assert_send::<#ty>();));
13    }
14
15    for ty in &analysis.sync_types {
16        stmts.push(quote!(rtic::export::assert_sync::<#ty>();));
17    }
18
19    for (_, monotonic) in &app.monotonics {
20        let ty = &monotonic.ty;
21        stmts.push(quote!(rtic::export::assert_monotonic::<#ty>();));
22    }
23
24    let device = &extra.device;
25    let chunks_name = util::priority_mask_chunks_ident();
26    let no_basepri_checks: Vec<_> = app
27        .hardware_tasks
28        .iter()
29        .filter_map(|(_, task)| {
30            if !util::is_exception(&task.args.binds) {
31                let interrupt_name = &task.args.binds;
32                let cfgs = &task.cfgs;
33                Some(quote!(
34                    #(#cfgs)*
35                    if (#device::Interrupt::#interrupt_name as usize) >= (#chunks_name * 32) {
36                        ::core::panic!("An interrupt out of range is used while in armv6 or armv8m.base");
37                    }
38                ))
39            } else {
40                None
41            }
42        })
43        .collect();
44
45    let const_check = quote! {
46        const _CONST_CHECK: () = {
47            if !rtic::export::have_basepri() {
48                #(#no_basepri_checks)*
49            } else {
50                // TODO: Add armv7 checks here
51            }
52        };
53
54        let _ = _CONST_CHECK;
55    };
56
57    stmts.push(const_check);
58
59    stmts
60}