1
1
#![ deny( warnings) ]
2
2
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 ;
11
4
use proc_macro2:: { Span , TokenStream as TokenStream2 } ;
12
5
use quote:: quote;
13
6
use syn:: {
@@ -18,8 +11,6 @@ use syn::{
18
11
FnArg , ItemFn , LitInt , LitStr , PatType , Path , ReturnType , Token , Type , Visibility ,
19
12
} ;
20
13
21
- use proc_macro:: TokenStream ;
22
-
23
14
/// Attribute to declare the entry point of the program
24
15
///
25
16
/// **IMPORTANT**: This attribute must appear exactly *once* in the dependency graph. Also, if you
@@ -367,7 +358,7 @@ enum RiscvArch {
367
358
Rv64E ,
368
359
}
369
360
370
- impl syn :: parse :: Parse for RiscvArch {
361
+ impl Parse for RiscvArch {
371
362
fn parse ( input : parse:: ParseStream ) -> syn:: Result < Self > {
372
363
let ident: syn:: Ident = input. parse ( ) ?;
373
364
match ident. to_string ( ) . as_str ( ) {
@@ -381,6 +372,17 @@ impl syn::parse::Parse for RiscvArch {
381
372
}
382
373
383
374
impl 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
+
384
386
fn width ( & self ) -> usize {
385
387
match self {
386
388
Self :: Rv32I | Self :: Rv32E => 4 ,
@@ -431,9 +433,9 @@ fn store_trap<T: FnMut(&str) -> bool>(arch: RiscvArch, mut filter: T) -> String
431
433
. iter ( )
432
434
. enumerate ( )
433
435
. 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)" ) )
435
437
. collect :: < Vec < _ > > ( )
436
- . join ( "\n " )
438
+ . join ( "\n " )
437
439
}
438
440
439
441
/// Generate the assembly instructions to load the trap frame.
@@ -445,18 +447,18 @@ fn load_trap(arch: RiscvArch) -> String {
445
447
. iter ( )
446
448
. enumerate ( )
447
449
. 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)" ) )
449
451
. collect :: < Vec < _ > > ( )
450
- . join ( "\n " )
452
+ . join ( "\n " )
451
453
}
452
454
453
455
/// Generates weak `_start_trap` function in assembly.
454
456
///
455
457
/// This implementation stores all registers in the trap frame and calls `_start_trap_rust`.
456
458
/// The trap frame is allocated on the stack and deallocated after the call.
457
459
#[ 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 ( ) ;
460
462
461
463
let width = arch. width ( ) ;
462
464
let trap_size = arch. trap_frame ( ) . len ( ) ;
@@ -482,10 +484,10 @@ core::arch::global_asm!(
482
484
.weak _start_trap
483
485
_start_trap:
484
486
addi sp, sp, - {trap_size} * {width}
485
- {store}
487
+ {store}
486
488
add a0, sp, zero
487
489
jal ra, _start_trap_rust
488
- {load}
490
+ {load}
489
491
addi sp, sp, {trap_size} * {width}
490
492
{ret}
491
493
");"#
@@ -500,8 +502,8 @@ _start_trap:
500
502
/// The '_start_DefaultHandler_trap' function stores the trap frame partially (only register a0) and
501
503
/// jumps to the interrupt handler. The '_continue_interrupt_trap' function stores the trap frame
502
504
/// 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 ( ) ;
505
507
let width = arch. width ( ) ;
506
508
let trap_size = arch. trap_frame ( ) . len ( ) ;
507
509
let store_start = store_trap ( arch, |reg| reg == "a0" ) ;
@@ -522,15 +524,15 @@ core::arch::global_asm!(
522
524
.global _start_DefaultHandler_trap
523
525
_start_DefaultHandler_trap:
524
526
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)
526
528
la a0, DefaultHandler // load interrupt handler address into a0
527
529
528
530
.align 4
529
531
.global _continue_interrupt_trap
530
532
_continue_interrupt_trap:
531
- {store_continue} // store trap partially (all registers except a0)
533
+ {store_continue} // store trap partially (all registers except a0)
532
534
jalr ra, a0, 0 // jump to corresponding interrupt handler (address stored in a0)
533
- {load} // restore trap frame
535
+ {load} // restore trap frame
534
536
addi sp, sp, {trap_size} * {width} // deallocate space for trap frame
535
537
{ret} // return from interrupt
536
538
");"#
@@ -643,93 +645,11 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
643
645
/// loop{};
644
646
/// }
645
647
/// ```
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
733
653
} ;
734
654
trap ( args, input, RiscvPacItem :: CoreInterrupt , arch)
735
655
}
@@ -790,7 +710,6 @@ fn trap(
790
710
Some ( arch) => {
791
711
let trap = start_interrupt_trap ( int_ident, arch) ;
792
712
quote ! {
793
- #[ cfg( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ]
794
713
#trap
795
714
}
796
715
}
@@ -828,7 +747,7 @@ core::arch::global_asm!(
828
747
.global _start_{interrupt}_trap
829
748
_start_{interrupt}_trap:
830
749
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)
832
751
la a0, {interrupt} // load interrupt handler address into a0
833
752
j _continue_interrupt_trap // jump to common part of interrupt trap
834
753
");"#
0 commit comments