1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{Ident, ItemFn, parse::Parse, parse_macro_input};
4
5mod entry;
6
7#[proc_macro_attribute]
8pub fn start_code(args: TokenStream, input: TokenStream) -> TokenStream {
9 let parsed_args = parse_macro_input!(args as StartCodeArgs);
11
12 let f = parse_macro_input!(input as ItemFn);
13 let attrs = f.attrs;
14 let vis = f.vis;
15 let name = f.sig.ident;
16 let args = f.sig.inputs;
17 let stmts = f.block.stmts;
18 let ret = f.sig.output;
19
20 let naked_prefix;
21 let naked_attr;
22 if parsed_args.naked {
23 naked_attr = quote! {
24 #[unsafe(naked)]
25 };
26 naked_prefix = quote! {
27 unsafe extern "C"
28 };
29 } else {
30 naked_attr = quote! {};
31 naked_prefix = quote! {};
32 };
33
34 quote!(
35 #naked_attr
36 #[unsafe(link_section = ".idmap.text")]
37 #(#attrs)*
38 #vis #naked_prefix fn #name(#args) #ret {
39 #(#stmts)*
40 }
41 )
42 .into()
43}
44
45struct StartCodeArgs {
46 naked: bool,
47}
48
49impl Parse for StartCodeArgs {
50 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
51 let mut naked = false;
52
53 if !input.is_empty() {
54 let ident: Ident = input.parse()?;
55 if ident == "naked" {
56 naked = true;
57 } else {
58 return Err(input.error("unexpected argument, expected `naked`"));
59 }
60 }
61
62 Ok(StartCodeArgs { naked })
63 }
64}
65
66#[proc_macro_attribute]
98pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
99 entry::entry(args, input, "__pie_boot_main")
100}
101
102#[proc_macro_attribute]
119pub fn secondary_entry(args: TokenStream, input: TokenStream) -> TokenStream {
120 entry::entry(args, input, "__pie_boot_secondary")
121}
122
123#[proc_macro_attribute]
124pub fn irq_handler(_args: TokenStream, input: TokenStream) -> TokenStream {
125 let func = parse_macro_input!(input as ItemFn);
126 let block = func.block;
127 quote! {
128 #[unsafe(no_mangle)]
129 extern "Rust" fn __somehal_handle_irq() {
130 #block
131 }
132 }
133 .into()
134}