11#![ deny( warnings) ]
22
3- extern crate core;
4- extern crate proc_macro;
5- extern crate proc_macro2;
6- extern crate quote;
7- extern crate syn;
8-
9- use std:: vec;
10-
3+ use proc_macro:: TokenStream ;
114use proc_macro2:: { Span , TokenStream as TokenStream2 } ;
125use quote:: quote;
136use syn:: {
@@ -18,8 +11,6 @@ use syn::{
1811 FnArg , ItemFn , LitInt , LitStr , PatType , Path , ReturnType , Token , Type , Visibility ,
1912} ;
2013
21- use proc_macro:: TokenStream ;
22-
2314/// Attribute to declare the entry point of the program
2415///
2516/// **IMPORTANT**: This attribute must appear exactly *once* in the dependency graph. Also, if you
@@ -367,7 +358,7 @@ enum RiscvArch {
367358 Rv64E ,
368359}
369360
370- impl syn :: parse :: Parse for RiscvArch {
361+ impl Parse for RiscvArch {
371362 fn parse ( input : parse:: ParseStream ) -> syn:: Result < Self > {
372363 let ident: syn:: Ident = input. parse ( ) ?;
373364 match ident. to_string ( ) . as_str ( ) {
@@ -381,6 +372,17 @@ impl syn::parse::Parse for RiscvArch {
381372}
382373
383374impl RiscvArch {
375+ fn try_from_env ( ) -> Option < Self > {
376+ let arch = std:: env:: var ( "RISCV_RT_BASE_ISA" ) . ok ( ) ?;
377+ match arch. as_str ( ) {
378+ "rv32i" => Some ( Self :: Rv32I ) ,
379+ "rv32e" => Some ( Self :: Rv32E ) ,
380+ "rv64i" => Some ( Self :: Rv64I ) ,
381+ "rv64e" => Some ( Self :: Rv64E ) ,
382+ _ => None ,
383+ }
384+ }
385+
384386 fn width ( & self ) -> usize {
385387 match self {
386388 Self :: Rv32I | Self :: Rv32E => 4 ,
@@ -431,9 +433,9 @@ fn store_trap<T: FnMut(&str) -> bool>(arch: RiscvArch, mut filter: T) -> String
431433 . iter ( )
432434 . enumerate ( )
433435 . filter ( |( _, & reg) | !reg. starts_with ( '_' ) && filter ( reg) )
434- . map ( |( i, reg) | format ! ( " {store} {reg}, {i}*{width}(sp)" ) )
436+ . map ( |( i, reg) | format ! ( "{store} {reg}, {i}*{width}(sp)" ) )
435437 . collect :: < Vec < _ > > ( )
436- . join ( "\n " )
438+ . join ( "\n " )
437439}
438440
439441/// Generate the assembly instructions to load the trap frame.
@@ -445,18 +447,18 @@ fn load_trap(arch: RiscvArch) -> String {
445447 . iter ( )
446448 . enumerate ( )
447449 . filter ( |( _, & reg) | !reg. starts_with ( '_' ) )
448- . map ( |( i, reg) | format ! ( " {load} {reg}, {i}*{width}(sp)" ) )
450+ . map ( |( i, reg) | format ! ( "{load} {reg}, {i}*{width}(sp)" ) )
449451 . collect :: < Vec < _ > > ( )
450- . join ( "\n " )
452+ . join ( "\n " )
451453}
452454
453455/// Generates weak `_start_trap` function in assembly.
454456///
455457/// This implementation stores all registers in the trap frame and calls `_start_trap_rust`.
456458/// The trap frame is allocated on the stack and deallocated after the call.
457459#[ proc_macro]
458- pub fn weak_start_trap ( input : TokenStream ) -> TokenStream {
459- let arch = parse_macro_input ! ( input as RiscvArch ) ;
460+ pub fn weak_start_trap ( _input : TokenStream ) -> TokenStream {
461+ let arch = RiscvArch :: try_from_env ( ) . unwrap ( ) ;
460462
461463 let width = arch. width ( ) ;
462464 let trap_size = arch. trap_frame ( ) . len ( ) ;
@@ -482,10 +484,10 @@ core::arch::global_asm!(
482484.weak _start_trap
483485_start_trap:
484486 addi sp, sp, - {trap_size} * {width}
485- {store}
487+ {store}
486488 add a0, sp, zero
487489 jal ra, _start_trap_rust
488- {load}
490+ {load}
489491 addi sp, sp, {trap_size} * {width}
490492 {ret}
491493");"#
@@ -500,8 +502,8 @@ _start_trap:
500502/// The '_start_DefaultHandler_trap' function stores the trap frame partially (only register a0) and
501503/// jumps to the interrupt handler. The '_continue_interrupt_trap' function stores the trap frame
502504/// partially (all registers except a0), jumps to the interrupt handler, and restores the trap frame.
503- pub fn vectored_interrupt_trap ( input : TokenStream ) -> TokenStream {
504- let arch = parse_macro_input ! ( input as RiscvArch ) ;
505+ pub fn vectored_interrupt_trap ( _input : TokenStream ) -> TokenStream {
506+ let arch = RiscvArch :: try_from_env ( ) . unwrap ( ) ;
505507 let width = arch. width ( ) ;
506508 let trap_size = arch. trap_frame ( ) . len ( ) ;
507509 let store_start = store_trap ( arch, |reg| reg == "a0" ) ;
@@ -522,15 +524,15 @@ core::arch::global_asm!(
522524.global _start_DefaultHandler_trap
523525_start_DefaultHandler_trap:
524526 addi sp, sp, -{trap_size} * {width} // allocate space for trap frame
525- {store_start} // store trap partially (only register a0)
527+ {store_start} // store trap partially (only register a0)
526528 la a0, DefaultHandler // load interrupt handler address into a0
527529
528530.align 4
529531.global _continue_interrupt_trap
530532_continue_interrupt_trap:
531- {store_continue} // store trap partially (all registers except a0)
533+ {store_continue} // store trap partially (all registers except a0)
532534 jalr ra, a0, 0 // jump to corresponding interrupt handler (address stored in a0)
533- {load} // restore trap frame
535+ {load} // restore trap frame
534536 addi sp, sp, {trap_size} * {width} // deallocate space for trap frame
535537 {ret} // return from interrupt
536538");"#
@@ -643,93 +645,11 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
643645/// loop{};
644646/// }
645647/// ```
646- pub fn core_interrupt_rv32i ( args : TokenStream , input : TokenStream ) -> TokenStream {
647- let arch = match ( ) {
648- #[ cfg( feature = "v-trap" ) ]
649- ( ) => Some ( RiscvArch :: Rv32I ) ,
650- #[ cfg( not( feature = "v-trap" ) ) ]
651- ( ) => None ,
652- } ;
653- trap ( args, input, RiscvPacItem :: CoreInterrupt , arch)
654- }
655-
656- #[ proc_macro_attribute]
657- /// Attribute to declare a core interrupt handler.
658- ///
659- /// The function must have the signature `[unsafe] fn() [-> !]`.
660- ///
661- /// The argument of the macro must be a path to a variant of an enum that implements the `riscv_rt::CoreInterruptNumber` trait.
662- ///
663- /// If the `v-trap` feature is enabled, this macro generates the corresponding interrupt trap handler in assembly.
664- ///
665- /// # Example
666- ///
667- /// ``` ignore,no_run
668- /// #[riscv_rt::core_interrupt(riscv::interrupt::Interrupt::SupervisorSoft)]
669- /// fn supervisor_soft() -> ! {
670- /// loop{};
671- /// }
672- /// ```
673- pub fn core_interrupt_rv32e ( args : TokenStream , input : TokenStream ) -> TokenStream {
674- let arch = match ( ) {
675- #[ cfg( feature = "v-trap" ) ]
676- ( ) => Some ( RiscvArch :: Rv32E ) ,
677- #[ cfg( not( feature = "v-trap" ) ) ]
678- ( ) => None ,
679- } ;
680- trap ( args, input, RiscvPacItem :: CoreInterrupt , arch)
681- }
682-
683- #[ proc_macro_attribute]
684- /// Attribute to declare a core interrupt handler.
685- ///
686- /// The function must have the signature `[unsafe] fn() [-> !]`.
687- ///
688- /// The argument of the macro must be a path to a variant of an enum that implements the `riscv_rt::CoreInterruptNumber` trait.
689- ///
690- /// If the `v-trap` feature is enabled, this macro generates the corresponding interrupt trap handler in assembly.
691- ///
692- /// # Example
693- ///
694- /// ``` ignore,no_run
695- /// #[riscv_rt::core_interrupt(riscv::interrupt::Interrupt::SupervisorSoft)]
696- /// fn supervisor_soft() -> ! {
697- /// loop{};
698- /// }
699- /// ```
700- pub fn core_interrupt_rv64i ( args : TokenStream , input : TokenStream ) -> TokenStream {
701- let arch = match ( ) {
702- #[ cfg( feature = "v-trap" ) ]
703- ( ) => Some ( RiscvArch :: Rv64I ) ,
704- #[ cfg( not( feature = "v-trap" ) ) ]
705- ( ) => None ,
706- } ;
707- trap ( args, input, RiscvPacItem :: CoreInterrupt , arch)
708- }
709-
710- #[ proc_macro_attribute]
711- /// Attribute to declare a core interrupt handler.
712- ///
713- /// The function must have the signature `[unsafe] fn() [-> !]`.
714- ///
715- /// The argument of the macro must be a path to a variant of an enum that implements the `riscv_rt::CoreInterruptNumber` trait.
716- ///
717- /// If the `v-trap` feature is enabled, this macro generates the corresponding interrupt trap handler in assembly.
718- ///
719- /// # Example
720- ///
721- /// ``` ignore,no_run
722- /// #[riscv_rt::core_interrupt(riscv::interrupt::Interrupt::SupervisorSoft)]
723- /// fn supervisor_soft() -> ! {
724- /// loop{};
725- /// }
726- /// ```
727- pub fn core_interrupt_rv64e ( args : TokenStream , input : TokenStream ) -> TokenStream {
728- let arch = match ( ) {
729- #[ cfg( feature = "v-trap" ) ]
730- ( ) => Some ( RiscvArch :: Rv64E ) ,
731- #[ cfg( not( feature = "v-trap" ) ) ]
732- ( ) => None ,
648+ pub fn core_interrupt ( args : TokenStream , input : TokenStream ) -> TokenStream {
649+ let arch = if cfg ! ( feature = "v-trap" ) {
650+ RiscvArch :: try_from_env ( )
651+ } else {
652+ None
733653 } ;
734654 trap ( args, input, RiscvPacItem :: CoreInterrupt , arch)
735655}
@@ -790,7 +710,6 @@ fn trap(
790710 Some ( arch) => {
791711 let trap = start_interrupt_trap ( int_ident, arch) ;
792712 quote ! {
793- #[ cfg( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ]
794713 #trap
795714 }
796715 }
@@ -828,7 +747,7 @@ core::arch::global_asm!(
828747 .global _start_{interrupt}_trap
829748 _start_{interrupt}_trap:
830749 addi sp, sp, -{trap_size} * {width} // allocate space for trap frame
831- {store} // store trap partially (only register a0)
750+ {store} // store trap partially (only register a0)
832751 la a0, {interrupt} // load interrupt handler address into a0
833752 j _continue_interrupt_trap // jump to common part of interrupt trap
834753");"#
0 commit comments