aboutsummaryrefslogtreecommitdiff
path: root/macros/src/codegen/resources_struct.rs
blob: 6fe4678a625e74608332aa6a7f420f30f837b32d (plain) (blame)
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
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use rtic_syntax::{ast::App, Context};

use crate::codegen::util;

pub fn codegen(ctxt: Context, needs_lt: &mut bool, app: &App) -> (TokenStream2, TokenStream2) {
    let mut lt = None;

    let resources = match ctxt {
        Context::Init => &app.inits.first().unwrap().args.resources,
        Context::Idle => &app.idles.first().unwrap().args.resources,
        Context::HardwareTask(name) => &app.hardware_tasks[name].args.resources,
        Context::SoftwareTask(name) => &app.software_tasks[name].args.resources,
    };

    let mut fields = vec![];
    let mut values = vec![];
    let mut has_cfgs = false;

    for (name, access) in resources {
        let (res, expr) = app.resource(name).expect("UNREACHABLE");

        let cfgs = &res.cfgs;
        has_cfgs |= !cfgs.is_empty();

        // access hold if the resource is [x] (exclusive) or [&x] (shared)
        let mut_ = if access.is_exclusive() {
            Some(quote!(mut))
        } else {
            None
        };
        let ty = &res.ty;
        let mangled_name = util::mark_internal_ident(&name);

        // let ownership = &analysis.ownerships[name];
        let r_prop = &res.properties;

        if !r_prop.task_local && !r_prop.lock_free {
            if access.is_shared() {
                lt = Some(quote!('a));

                fields.push(quote!(
                    #(#cfgs)*
                    pub #name: &'a #ty
                ));
            } else {
                // Resource proxy
                lt = Some(quote!('a));

                fields.push(quote!(
                    #(#cfgs)*
                    pub #name: resources::#name<'a>
                ));

                values.push(quote!(
                    #(#cfgs)*
                    #name: resources::#name::new(priority)

                ));

                // continue as the value has been filled,
                continue;
            }
        } else {
            let lt = if ctxt.runs_once() {
                quote!('static)
            } else {
                lt = Some(quote!('a));
                quote!('a)
            };

            fields.push(quote!(
                #(#cfgs)*
                pub #name: &#lt #mut_ #ty
            ));
        }

        let is_late = expr.is_none();
        if is_late {
            let expr = if access.is_exclusive() {
                quote!(&mut *#mangled_name.get_mut_unchecked().as_mut_ptr())
            } else {
                quote!(&*#mangled_name.get_unchecked().as_ptr())
            };

            values.push(quote!(
                #(#cfgs)*
                #name: #expr
            ));
        } else {
            values.push(quote!(
                #(#cfgs)*
                #name: #mangled_name.get_mut_unchecked()
            ));
        }
    }

    if lt.is_some() {
        *needs_lt = true;

        // The struct could end up empty due to `cfg`s leading to an error due to `'a` being unused
        if has_cfgs {
            fields.push(quote!(
                #[doc(hidden)]
                pub __marker__: core::marker::PhantomData<&'a ()>
            ));

            values.push(quote!(__marker__: core::marker::PhantomData))
        }
    }

    let doc = format!("Resources `{}` has access to", ctxt.ident(app));
    let ident = util::resources_ident(ctxt, app);
    let ident = util::mark_internal_ident(&ident);
    let item = quote!(
        #[allow(non_snake_case)]
        #[doc = #doc]
        pub struct #ident<#lt> {
            #(#fields,)*
        }
    );

    let arg = if ctxt.is_init() {
        None
    } else {
        Some(quote!(priority: &#lt rtic::export::Priority))
    };
    let constructor = quote!(
        impl<#lt> #ident<#lt> {
            #[inline(always)]
            pub unsafe fn new(#arg) -> Self {
                #ident {
                    #(#values,)*
                }
            }
        }
    );

    (item, constructor)
}
05:06:42 -0700'>2022-03-16bun.lockbGravatar Jarred Sumner 3-0/+0 2022-03-16Update feature_flags.zigGravatar Jarred Sumner 1-0/+1 2022-03-16[bun.js] Bun.unsafe test should check the gcGravatar Jarred Sumner 1-4/+14 2022-03-16Update work_pool.zigGravatar Jarred Sumner 1-21/+28 2022-03-16Add a way to run serial tasks on a different threadGravatar Jarred Sumner 1-3/+65 2022-03-16fix crash when SyntaxError is thrown and we did not receive an ErrorInstance?Gravatar Jarred Sumner 1-18/+25 2022-03-16[bun.js] Fix release-mode test failures in HeadersGravatar Jarred Sumner 1-47/+42 2022-03-16Update ref_count.zigGravatar Jarred Sumner 1-2/+0 2022-03-15file is too bigjarred/replGravatar Jarred Sumner 1-113827/+0 2022-03-15Update Dockerfile.baseGravatar Jarred Sumner 1-1/+1 2022-03-15Add rust and lolhtml to dockerfileGravatar Jarred Sumner 2-0/+20 2022-03-15bump webkitGravatar Jarred Sumner 1-1/+1 2022-03-15Update WebKitGravatar Jarred Sumner 1-0/+0 2022-03-15:camera:Gravatar Jarred Sumner 60-799/+859 2022-03-15Fix test failureGravatar Jarred Sumner 1-15/+17 2022-03-15[bun:error] handle errors without a name or messageGravatar Jarred Sumner 1-6/+11 2022-03-15Update pool.zigGravatar Jarred Sumner 1-0/+1 2022-03-15Load .env by defaultGravatar Jarred Sumner 2-0/+8 2022-03-15mimalloc interpose is buggyGravatar Jarred Sumner 1-2/+25 2022-03-15higher max http requests for bun.jsGravatar Jarred Sumner 1-0/+29 2022-03-15zero copyGravatar Jarred Sumner 1-21/+15 2022-03-15Update javascript.zigGravatar Jarred Sumner 1-2/+0 2022-03-15[bun.js] utf8 console.{time, count, timeEnd, profile, profileEnd, count, ↵Gravatar Jarred Sumner 1-16/+16 countReset}