1use proc_macro::TokenStream;
2use proc_macro2::Span;
3use proc_macro_crate::{crate_name, FoundCrate};
4use quote::{format_ident, quote};
5use syn::{
6 parse_macro_input, spanned::Spanned, Error, Ident, ItemFn, ItemStatic, StaticMutability, Token,
7};
8
9#[proc_macro_attribute]
10pub fn arch_entry(_input: TokenStream, annotated_item: TokenStream) -> TokenStream {
11 let annotated_item = parse_macro_input!(annotated_item as ItemFn);
12 TokenStream::from(quote! {
13 #[export_name = "_main_for_arch"]
14 #annotated_item
15 })
16}
17
18#[proc_macro_attribute]
19pub fn arch_interrupt(_input: TokenStream, annotated_item: TokenStream) -> TokenStream {
20 let annotated_item = parse_macro_input!(annotated_item as ItemFn);
21 TokenStream::from(quote! {
22 #[export_name = "_interrupt_for_arch"]
23 #annotated_item
24 })
25}
26
27#[proc_macro_attribute]
28pub fn percpu(attr: TokenStream, item: TokenStream) -> TokenStream {
29 if !attr.is_empty() {
30 return compiler_error(Error::new(
31 Span::call_site(),
32 "expect an empty attribute: `#[def_percpu]`",
33 ));
34 }
35
36 let found_crate = crate_name("polyhal").expect("polyhal is present in `Cargo.toml`");
37 let mut ast = syn::parse_macro_input!(item as ItemStatic);
38 ast.mutability = StaticMutability::Mut(Token));
39
40 let raw_name = ast.ident.clone();
41 ast.ident = format_ident!("__PERCPU_{}", raw_name);
42 let ast_name = &ast.ident;
43 let vis = &ast.vis;
44
45 let raw_ty = ast.ty.clone();
46
47 let ty_path = match found_crate {
48 FoundCrate::Itself => quote!(crate::utils::percpu::PerCPU),
49 FoundCrate::Name(name) => {
50 let ident = Ident::new(&name, Span::call_site());
51 quote!( #ident::utils::percpu::PerCPU )
52 }
53 };
54
55 quote! {
56 #[unsafe(link_section = "percpu")]
57 #ast
58
59 #vis static #raw_name: #ty_path<#raw_ty> = #ty_path::new(&raw mut #ast_name);
60 }
61 .into()
62}
63
64#[proc_macro]
65pub fn define_arch_mods(_input: TokenStream) -> TokenStream {
66 quote! {
67 #[cfg(target_arch = "riscv64")]
68 mod riscv64;
69 #[cfg(target_arch = "riscv64")]
70 #[allow(unused_imports)]
71 pub use riscv64::*;
72 #[cfg(target_arch = "aarch64")]
73 mod aarch64;
74 #[cfg(target_arch = "aarch64")]
75 #[allow(unused_imports)]
76 pub use aarch64::*;
77 #[cfg(target_arch = "x86_64")]
78 mod x86_64;
79 #[cfg(target_arch = "x86_64")]
80 #[allow(unused_imports)]
81 pub use x86_64::*;
82 #[cfg(target_arch = "loongarch64")]
83 mod loongarch64;
84 #[cfg(target_arch = "loongarch64")]
85 #[allow(unused_imports)]
86 pub use loongarch64::*;
87 }
88 .into()
89}
90
91fn compiler_error(err: Error) -> TokenStream {
92 err.to_compile_error().into()
93}