riscv_macros/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, DeriveInput};
4
5mod riscv;
6
7/// Attribute-like macro that implements the traits of the `riscv-pac` crate for a given enum.
8///
9/// As these traits are unsafe, the macro must be called with the `unsafe` keyword followed by the trait name.
10/// In this way, we warn callers that they must comply with the requirements of the trait.
11///
12/// The trait name must be one of `ExceptionNumber`, `CoreInterruptNumber`, `ExternalInterruptNumber`,
13/// `PriorityNumber`, or `HartIdNumber`.
14///
15/// # Note
16///
17/// Crates using this macro must depend on the `riscv` crate, as the generated code references it.
18///
19/// If the `rt` feature is enabled, the generated code may also include the necessary runtime support
20/// for interrupt and exception handling. Thus, the calling crate must also depend on the `riscv-rt` crate.
21///
22/// # Safety
23///
24/// The struct to be implemented must comply with the requirements of the specified trait.
25///
26/// # Example
27///
28/// ```rust,ignore,no_run
29/// use riscv::*;
30///
31/// #[repr(usize)]
32/// #[pac_enum(unsafe ExceptionNumber)]
33/// #[derive(Clone, Copy, Debug, Eq, PartialEq)]
34/// enum Exception {
35///     E1 = 1,
36///     E3 = 3,
37/// }
38///
39/// assert_eq!(Exception::E1.number(), 1);
40/// assert_eq!(Exception::E3.number(), 3);
41///
42/// assert_eq!(Exception::from_number(1), Ok(Exception::E1));
43/// assert_eq!(Exception::from_number(2), Err(2));
44/// assert_eq!(Exception::from_number(3), Ok(Exception::E3));
45///
46/// assert_eq!(Exception::MAX_EXCEPTION_NUMBER, 3);
47///```
48#[proc_macro_attribute]
49pub fn pac_enum(attr: TokenStream, item: TokenStream) -> TokenStream {
50    let input = parse_macro_input!(item as DeriveInput);
51    let pac_enum = riscv::PacEnumItem::new(&input);
52
53    let attr = parse_macro_input!(attr as riscv::PacTrait);
54
55    let trait_impl = pac_enum.impl_trait(&attr);
56    quote! {
57        #input
58        #(#trait_impl)*
59    }
60    .into()
61}