lib.rs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. extern crate proc_macro;
  2. use proc_macro::TokenStream;
  3. use quote::quote;
  4. use syn::{parse, parse_macro_input, spanned::Spanned as _, FnArg, ItemFn};
  5. /// Define the default trap handler. The function should take exactly one argument
  6. /// of type `&mut TrapContext`.
  7. ///
  8. /// # Usage
  9. /// ```no_run
  10. /// #[eonix_hal::default_trap_handler]
  11. /// fn interrupt_handler(ctx: &mut TrapContext) {
  12. /// println!("Trap {} received!", ctx.trap_no());
  13. /// // ...
  14. /// }
  15. /// ```
  16. #[proc_macro_attribute]
  17. pub fn default_trap_handler(attrs: TokenStream, item: TokenStream) -> TokenStream {
  18. let item = parse_macro_input!(item as ItemFn);
  19. if !attrs.is_empty() {
  20. return parse::Error::new(
  21. item.span(),
  22. "`default_trap_handler` attribute does not take any arguments",
  23. )
  24. .into_compile_error()
  25. .into();
  26. }
  27. if item.sig.inputs.len() > 1 {
  28. return parse::Error::new(
  29. item.span(),
  30. "`default_trap_handler` only takes one argument",
  31. )
  32. .into_compile_error()
  33. .into();
  34. }
  35. let attrs = &item.attrs;
  36. let arg = item.sig.inputs.first().unwrap();
  37. let block = &item.block;
  38. quote! {
  39. #(#attrs)*
  40. #[no_mangle]
  41. pub unsafe extern "C" fn _default_trap_handler(#arg) #block
  42. }
  43. .into()
  44. }
  45. /// Define the entry point. The function should have signature like
  46. ///
  47. /// ```ignore
  48. /// [unsafe] fn ident(ident: eonix_hal::bootstrap::BootStrapData) -> !
  49. /// ```
  50. ///
  51. /// # Usage
  52. /// ```no_run
  53. /// #[eonix_hal::main]
  54. /// fn kernel_main(data: eonix_hal::bootstrap::BootStrapData) -> ! {
  55. /// // ...
  56. /// }
  57. /// ```
  58. #[proc_macro_attribute]
  59. pub fn main(attrs: TokenStream, item: TokenStream) -> TokenStream {
  60. let item = parse_macro_input!(item as ItemFn);
  61. if !attrs.is_empty() {
  62. return parse::Error::new(item.span(), "`main` attribute does not take any arguments")
  63. .into_compile_error()
  64. .into();
  65. }
  66. if item.sig.inputs.len() != 1 {
  67. return parse::Error::new(item.span(), "`main` should have exactly one argument.")
  68. .into_compile_error()
  69. .into();
  70. }
  71. let arg_ident = match item.sig.inputs.first().unwrap() {
  72. FnArg::Receiver(_) => {
  73. return parse::Error::new(
  74. item.span(),
  75. "`main` function cannot take `self` as an argument",
  76. )
  77. .into_compile_error()
  78. .into();
  79. }
  80. FnArg::Typed(ty) => &ty.pat,
  81. };
  82. let ident = &item.sig.ident;
  83. let attrs = item.attrs;
  84. let unsafety = item.sig.unsafety;
  85. let block = &item.block;
  86. quote! {
  87. #(#attrs)*
  88. #[export_name = "_eonix_hal_main"]
  89. pub #unsafety fn #ident(
  90. #arg_ident: eonix_hal::bootstrap::BootStrapData,
  91. ) -> ! #block
  92. }
  93. .into()
  94. }
  95. /// Define the AP entry point. The function should have signature like
  96. ///
  97. /// ```ignore
  98. /// [unsafe] fn ident(ident: eonix_mm::address::PRange) -> !
  99. /// ```
  100. ///
  101. /// # Usage
  102. /// ```no_run
  103. /// #[eonix_hal::main]
  104. /// fn ap_main(stack_range: eonix_mm::address::PRange) -> ! {
  105. /// // ...
  106. /// }
  107. /// ```
  108. #[proc_macro_attribute]
  109. pub fn ap_main(attrs: TokenStream, item: TokenStream) -> TokenStream {
  110. let item = parse_macro_input!(item as ItemFn);
  111. if !attrs.is_empty() {
  112. return parse::Error::new(
  113. item.span(),
  114. "`ap_main` attribute does not take any arguments",
  115. )
  116. .into_compile_error()
  117. .into();
  118. }
  119. if item.sig.inputs.len() != 1 {
  120. return parse::Error::new(item.span(), "`ap_main` should have exactly one argument.")
  121. .into_compile_error()
  122. .into();
  123. }
  124. let arg_ident = match item.sig.inputs.first().unwrap() {
  125. FnArg::Receiver(_) => {
  126. return parse::Error::new(
  127. item.span(),
  128. "`ap_main` function cannot take `self` as an argument",
  129. )
  130. .into_compile_error()
  131. .into();
  132. }
  133. FnArg::Typed(ty) => &ty.pat,
  134. };
  135. let ident = &item.sig.ident;
  136. let attrs = item.attrs;
  137. let unsafety = item.sig.unsafety;
  138. let block = &item.block;
  139. quote! {
  140. #(#attrs)*
  141. #[export_name = "_eonix_hal_ap_main"]
  142. pub #unsafety fn #ident(
  143. #arg_ident: eonix_mm::address::PRange,
  144. ) -> ! #block
  145. }
  146. .into()
  147. }