Browse Source

[macros] Remove 'exception' and 'interrupt' attributes

Vadim Kaushan 6 years ago
parent
commit
64fb6ad312
1 changed files with 1 additions and 370 deletions
  1. 1 370
      riscv-rt/macros/src/lib.rs

+ 1 - 370
riscv-rt/macros/src/lib.rs

@@ -15,7 +15,7 @@ use rand::SeedableRng;
 use std::sync::atomic::{AtomicUsize, Ordering};
 use std::time::{SystemTime, UNIX_EPOCH};
 use syn::{
-    parse, spanned::Spanned, FnArg, Ident, ItemFn, ReturnType, Type, Visibility,
+    parse, spanned::Spanned, Ident, ItemFn, ReturnType, Type, Visibility,
 };
 
 static CALL_COUNT: AtomicUsize = AtomicUsize::new(0);
@@ -105,375 +105,6 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
     .into()
 }
 
-/// Attribute to declare an exception handler
-///
-/// **IMPORTANT**: If you are using Rust 1.30 this attribute must be used on reachable items (i.e.
-/// there must be no private modules between the item and the root of the crate); if the item is in
-/// the root of the crate you'll be fine. This reachability restriction doesn't apply to Rust 1.31
-/// and newer releases.
-///
-/// # Syntax
-///
-/// ```
-/// # use riscv_rt_macros::exception;
-/// #[exception]
-/// fn SysTick() {
-///     // ..
-/// }
-///
-/// # fn main() {}
-/// ```
-///
-/// where the name of the function must be one of:
-///
-/// - `DefaultHandler`
-/// - `NonMaskableInt`
-/// - `HardFault`
-/// - `MemoryManagement` (a)
-/// - `BusFault` (a)
-/// - `UsageFault` (a)
-/// - `SecureFault` (b)
-/// - `SVCall`
-/// - `DebugMonitor` (a)
-/// - `PendSV`
-/// - `SysTick`
-///
-/// (a) Not available on Cortex-M0 variants (`thumbv6m-none-eabi`)
-///
-/// (b) Only available on ARMv8-M
-///
-/// # Usage
-///
-/// `#[exception] fn HardFault(..` sets the hard fault handler. The handler must have signature
-/// `[unsafe] fn(&ExceptionFrame) -> !`. This handler is not allowed to return as that can cause
-/// undefined behavior.
-///
-/// `#[exception] fn DefaultHandler(..` sets the *default* handler. All exceptions which have not
-/// been assigned a handler will be serviced by this handler. This handler must have signature
-/// `[unsafe] fn(irqn: i16) [-> !]`. `irqn` is the IRQ number (See CMSIS); `irqn` will be a negative
-/// number when the handler is servicing a core exception; `irqn` will be a positive number when the
-/// handler is servicing a device specific exception (interrupt).
-///
-/// `#[exception] fn Name(..` overrides the default handler for the exception with the given `Name`.
-/// These handlers must have signature `[unsafe] fn() [-> !]`.
-///
-/// # Properties
-///
-/// Exception handlers can only be called by the hardware. Other parts of the program can't refer to
-/// the exception handlers, much less invoke them as if they were functions.
-///
-/// # Examples
-///
-/// - Setting the `HardFault` handler
-///
-/// ```
-/// # extern crate riscv_rt;
-/// # extern crate riscv_rt_macros;
-/// # use riscv_rt_macros::exception;
-/// #[exception]
-/// fn HardFault(ef: &riscv_rt::ExceptionFrame) -> ! {
-///     // prints the exception frame as a panic message
-///     panic!("{:#?}", ef);
-/// }
-///
-/// # fn main() {}
-/// ```
-///
-/// - Setting the default handler
-///
-/// ```
-/// # use riscv_rt_macros::exception;
-/// #[exception]
-/// fn DefaultHandler(irqn: i16) {
-///     println!("IRQn = {}", irqn);
-/// }
-///
-/// # fn main() {}
-/// ```
-#[proc_macro_attribute]
-pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
-    let f = parse_macro_input!(input as ItemFn);
-
-    if !args.is_empty() {
-        return parse::Error::new(Span::call_site(), "This attribute accepts no arguments")
-            .to_compile_error()
-            .into();
-    }
-
-    let fspan = f.span();
-    let ident = f.ident;
-
-    enum Exception {
-        DefaultHandler,
-        HardFault,
-        Other,
-    }
-
-    let ident_s = ident.to_string();
-    let exn = match &*ident_s {
-        "DefaultHandler" => Exception::DefaultHandler,
-        "HardFault" => Exception::HardFault,
-        // NOTE that at this point we don't check if the exception is available on the target (e.g.
-        // MemoryManagement is not available on Cortex-M0)
-        "NonMaskableInt" | "MemoryManagement" | "BusFault" | "UsageFault" | "SecureFault"
-        | "SVCall" | "DebugMonitor" | "PendSV" | "SysTick" => Exception::Other,
-        _ => {
-            return parse::Error::new(ident.span(), "This is not a valid exception name")
-                .to_compile_error()
-                .into();
-        }
-    };
-
-    // XXX should we blacklist other attributes?
-    let attrs = f.attrs;
-    let block = f.block;
-    let stmts = block.stmts;
-    let unsafety = f.unsafety;
-
-    let hash = random_ident();
-    match exn {
-        Exception::DefaultHandler => {
-            let valid_signature = f.constness.is_none()
-                && f.vis == Visibility::Inherited
-                && f.abi.is_none()
-                && f.decl.inputs.len() == 1
-                && f.decl.generics.params.is_empty()
-                && f.decl.generics.where_clause.is_none()
-                && f.decl.variadic.is_none()
-                && match f.decl.output {
-                    ReturnType::Default => true,
-                    ReturnType::Type(_, ref ty) => match **ty {
-                        Type::Tuple(ref tuple) => tuple.elems.is_empty(),
-                        Type::Never(..) => true,
-                        _ => false,
-                    },
-                };
-
-            if !valid_signature {
-                return parse::Error::new(
-                    fspan,
-                    "`DefaultHandler` must have signature `[unsafe] fn(i16) [-> !]`",
-                )
-                .to_compile_error()
-                .into();
-            }
-
-            let arg = match f.decl.inputs[0] {
-                FnArg::Captured(ref arg) => arg,
-                _ => unreachable!(),
-            };
-
-            quote!(
-                #[export_name = #ident_s]
-                #(#attrs)*
-                pub #unsafety extern "C" fn #hash() {
-                    extern crate core;
-
-                    const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32;
-
-                    let #arg = unsafe { core::ptr::read(SCB_ICSR) as u8 as i16 - 16 };
-
-                    #(#stmts)*
-                }
-            )
-            .into()
-        }
-        Exception::HardFault => {
-            let valid_signature = f.constness.is_none()
-                && f.vis == Visibility::Inherited
-                && f.abi.is_none()
-                && f.decl.inputs.len() == 1
-                && match f.decl.inputs[0] {
-                    FnArg::Captured(ref arg) => match arg.ty {
-                        Type::Reference(ref r) => r.lifetime.is_none() && r.mutability.is_none(),
-                        _ => false,
-                    },
-                    _ => false,
-                }
-                && f.decl.generics.params.is_empty()
-                && f.decl.generics.where_clause.is_none()
-                && f.decl.variadic.is_none()
-                && match f.decl.output {
-                    ReturnType::Default => false,
-                    ReturnType::Type(_, ref ty) => match **ty {
-                        Type::Never(_) => true,
-                        _ => false,
-                    },
-                };
-
-            if !valid_signature {
-                return parse::Error::new(
-                    fspan,
-                    "`HardFault` handler must have signature `[unsafe] fn(&ExceptionFrame) -> !`",
-                )
-                .to_compile_error()
-                .into();
-            }
-
-            let arg = match f.decl.inputs[0] {
-                FnArg::Captured(ref arg) => arg,
-                _ => unreachable!(),
-            };
-
-            let pat = &arg.pat;
-
-            quote!(
-                #[export_name = "HardFault"]
-                #[link_section = ".HardFault.user"]
-                #(#attrs)*
-                pub #unsafety extern "C" fn #hash(#arg) -> ! {
-                    extern crate riscv_rt;
-
-                    // further type check of the input argument
-                    let #pat: &riscv_rt::ExceptionFrame = #pat;
-                    #(#stmts)*
-                }
-            )
-            .into()
-        }
-        Exception::Other => {
-            let valid_signature = f.constness.is_none()
-                && f.vis == Visibility::Inherited
-                && f.abi.is_none()
-                && f.decl.inputs.is_empty()
-                && f.decl.generics.params.is_empty()
-                && f.decl.generics.where_clause.is_none()
-                && f.decl.variadic.is_none()
-                && match f.decl.output {
-                    ReturnType::Default => true,
-                    ReturnType::Type(_, ref ty) => match **ty {
-                        Type::Tuple(ref tuple) => tuple.elems.is_empty(),
-                        Type::Never(..) => true,
-                        _ => false,
-                    },
-                };
-
-            if !valid_signature {
-                return parse::Error::new(
-                    fspan,
-                    "`#[exception]` handlers other than `DefaultHandler` and `HardFault` must have \
-                     signature `[unsafe] fn() [-> !]`",
-                )
-                .to_compile_error()
-                .into();
-            }
-
-            quote!(
-                #[export_name = #ident_s]
-                #(#attrs)*
-                pub #unsafety extern "C" fn #hash() {
-                    extern crate riscv_rt;
-
-                    // check that this exception actually exists
-                    riscv_rt::Exception::#ident;
-
-                    #(#stmts)*
-                }
-            )
-            .into()
-        }
-    }
-}
-
-/// Attribute to declare an interrupt (AKA device-specific exception) handler
-///
-/// **IMPORTANT**: If you are using Rust 1.30 this attribute must be used on reachable items (i.e.
-/// there must be no private modules between the item and the root of the crate); if the item is in
-/// the root of the crate you'll be fine. This reachability restriction doesn't apply to Rust 1.31
-/// and newer releases.
-///
-/// **NOTE**: This attribute is exposed by `riscv-rt` only when the `device` feature is enabled.
-/// However, that export is not meant to be used directly -- using it will result in a compilation
-/// error. You should instead use the device crate (usually generated using `svd2rust`) re-export of
-/// that attribute. You need to use the re-export to have the compiler check that the interrupt
-/// exists on the target device.
-///
-/// # Syntax
-///
-/// ``` ignore
-/// extern crate device;
-///
-/// // the attribute comes from the device crate not from riscv-rt
-/// use device::interrupt;
-///
-/// #[interrupt]
-/// fn USART1() {
-///     // ..
-/// }
-/// ```
-///
-/// where the name of the function must be one of the device interrupts.
-///
-/// # Usage
-///
-/// `#[interrupt] fn Name(..` overrides the default handler for the interrupt with the given `Name`.
-/// These handlers must have signature `[unsafe] fn() [-> !]`.
-///
-/// If the interrupt handler has not been overridden it will be dispatched by the default exception
-/// handler (`DefaultHandler`).
-///
-/// # Properties
-///
-/// Interrupts handlers can only be called by the hardware. Other parts of the program can't refer
-/// to the interrupt handlers, much less invoke them as if they were functions.
-#[proc_macro_attribute]
-pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream {
-    let f: ItemFn = syn::parse(input).expect("`#[interrupt]` must be applied to a function");
-
-    if !args.is_empty() {
-        return parse::Error::new(Span::call_site(), "This attribute accepts no arguments")
-            .to_compile_error()
-            .into();
-    }
-
-    let fspan = f.span();
-    let ident = f.ident;
-    let ident_s = ident.to_string();
-
-    // XXX should we blacklist other attributes?
-    let attrs = f.attrs;
-    let block = f.block;
-    let stmts = block.stmts;
-    let unsafety = f.unsafety;
-
-    let valid_signature = f.constness.is_none()
-        && f.vis == Visibility::Inherited
-        && f.abi.is_none()
-        && f.decl.inputs.is_empty()
-        && f.decl.generics.params.is_empty()
-        && f.decl.generics.where_clause.is_none()
-        && f.decl.variadic.is_none()
-        && match f.decl.output {
-            ReturnType::Default => true,
-            ReturnType::Type(_, ref ty) => match **ty {
-                Type::Tuple(ref tuple) => tuple.elems.is_empty(),
-                Type::Never(..) => true,
-                _ => false,
-            },
-        };
-
-    if !valid_signature {
-        return parse::Error::new(
-            fspan,
-            "`#[interrupt]` handlers must have signature `[unsafe] fn() [-> !]`",
-        )
-        .to_compile_error()
-        .into();
-    }
-
-    let hash = random_ident();
-    quote!(
-        #[export_name = #ident_s]
-        #(#attrs)*
-        pub #unsafety extern "C" fn #hash() {
-            interrupt::#ident;
-
-            #(#stmts)*
-        }
-    )
-    .into()
-}
-
 /// Attribute to mark which function will be called at the beginning of the reset handler.
 ///
 /// **IMPORTANT**: This attribute can appear at most *once* in the dependency graph. Also, if you