use proc_macro::TokenStream;
use quote::quote;
use syn::{Ident, ItemFn, parse::Parse, parse_macro_input};
mod entry;
#[proc_macro_attribute]
pub fn start_code(args: TokenStream, input: TokenStream) -> TokenStream {
let parsed_args = parse_macro_input!(args as StartCodeArgs);
let f = parse_macro_input!(input as ItemFn);
let attrs = f.attrs;
let vis = f.vis;
let name = f.sig.ident;
let args = f.sig.inputs;
let stmts = f.block.stmts;
let ret = f.sig.output;
let naked_prefix;
let naked_attr;
if parsed_args.naked {
naked_attr = quote! {
#[unsafe(naked)]
};
naked_prefix = quote! {
unsafe extern "C"
};
} else {
naked_attr = quote! {};
naked_prefix = quote! {};
};
quote!(
#naked_attr
#[unsafe(link_section = ".idmap.text")]
#(#attrs)*
#vis #naked_prefix fn #name(#args) #ret {
#(#stmts)*
}
)
.into()
}
struct StartCodeArgs {
naked: bool,
}
impl Parse for StartCodeArgs {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let mut naked = false;
if !input.is_empty() {
let ident: Ident = input.parse()?;
if ident == "naked" {
naked = true;
} else {
return Err(input.error("unexpected argument, expected `naked`"));
}
}
Ok(StartCodeArgs { naked })
}
}
#[proc_macro_attribute]
pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
entry::entry(args, input, "__pie_boot_main")
}
#[proc_macro_attribute]
pub fn secondary_entry(args: TokenStream, input: TokenStream) -> TokenStream {
entry::entry(args, input, "__pie_boot_secondary")
}
#[proc_macro_attribute]
pub fn irq_handler(_args: TokenStream, input: TokenStream) -> TokenStream {
let func = parse_macro_input!(input as ItemFn);
let block = func.block;
quote! {
#[unsafe(no_mangle)]
extern "Rust" fn __somehal_handle_irq() {
#block
}
}
.into()
}