@@ -571,21 +571,6 @@ impl MachineState {
571
571
572
572
state
573
573
}
574
-
575
- /// `*sp = val; sp += size_of::<T>()`
576
- fn push < T > ( & mut self , val : T ) {
577
- let sp = self [ XReg :: sp] . get_ptr :: < T > ( ) ;
578
- unsafe { sp. write_unaligned ( val) }
579
- self [ XReg :: sp] . set_ptr ( sp. wrapping_add ( 1 ) ) ;
580
- }
581
-
582
- /// `ret = *sp; sp -= size_of::<T>()`
583
- fn pop < T > ( & mut self ) -> T {
584
- let sp = self [ XReg :: sp] . get_ptr :: < T > ( ) ;
585
- let val = unsafe { sp. read_unaligned ( ) } ;
586
- self [ XReg :: sp] . set_ptr ( sp. wrapping_sub ( 1 ) ) ;
587
- val
588
- }
589
574
}
590
575
591
576
/// The reason the interpreter loop terminated.
@@ -614,6 +599,76 @@ impl Interpreter<'_> {
614
599
self . pc = unsafe { self . pc . offset ( offset - inst_size) } ;
615
600
ControlFlow :: Continue ( ( ) )
616
601
}
602
+
603
+ /// `sp -= size_of::<T>(); *sp = val;`
604
+ #[ must_use]
605
+ fn push < T > ( & mut self , val : T ) -> ControlFlow < Done > {
606
+ let new_sp = self . state [ XReg :: sp] . get_ptr :: < T > ( ) . wrapping_sub ( 1 ) ;
607
+ self . set_sp ( new_sp) ?;
608
+ unsafe {
609
+ new_sp. write_unaligned ( val) ;
610
+ }
611
+ ControlFlow :: Continue ( ( ) )
612
+ }
613
+
614
+ /// `ret = *sp; sp -= size_of::<T>()`
615
+ fn pop < T > ( & mut self ) -> T {
616
+ let sp = self . state [ XReg :: sp] . get_ptr :: < T > ( ) ;
617
+ let val = unsafe { sp. read_unaligned ( ) } ;
618
+ self . set_sp_unchecked ( sp. wrapping_add ( 1 ) ) ;
619
+ val
620
+ }
621
+
622
+ /// Sets the stack pointer to the `sp` provided.
623
+ ///
624
+ /// Returns a trap if this would result in stack overflow, or if `sp` is
625
+ /// beneath the base pointer of `self.state.stack`.
626
+ #[ must_use]
627
+ fn set_sp < T > ( & mut self , sp : * mut T ) -> ControlFlow < Done > {
628
+ let sp_raw = sp as usize ;
629
+ let base_raw = self . state . stack . as_ptr ( ) as usize ;
630
+ if sp_raw < base_raw {
631
+ return ControlFlow :: Break ( Done :: Trap ( self . pc . as_ptr ( ) ) ) ;
632
+ }
633
+ self . set_sp_unchecked ( sp) ;
634
+ ControlFlow :: Continue ( ( ) )
635
+ }
636
+
637
+ /// Same as `set_sp` but does not check to see if `sp` is in-bounds. Should
638
+ /// only be used with stack increment operations such as `pop`.
639
+ fn set_sp_unchecked < T > ( & mut self , sp : * mut T ) {
640
+ if cfg ! ( debug_assertions) {
641
+ let sp_raw = sp as usize ;
642
+ let base = self . state . stack . as_ptr ( ) as usize ;
643
+ let end = base + self . state . stack . len ( ) ;
644
+ assert ! ( base <= sp_raw && sp_raw <= end) ;
645
+ }
646
+ self . state [ XReg :: sp] . set_ptr ( sp) ;
647
+ }
648
+ }
649
+
650
+ #[ test]
651
+ fn simple_push_pop ( ) {
652
+ let mut state = MachineState :: with_stack ( vec ! [ 0 ; 16 ] ) ;
653
+ unsafe {
654
+ let mut i = Interpreter {
655
+ state : & mut state,
656
+ // this isn't actually read so just manufacture a dummy one
657
+ pc : UnsafeBytecodeStream :: new ( ( & mut 0 ) . into ( ) ) ,
658
+ } ;
659
+ assert ! ( i. push( 0_i32 ) . is_continue( ) ) ;
660
+ assert_eq ! ( i. pop:: <i32 >( ) , 0_i32 ) ;
661
+ assert ! ( i. push( 1_i32 ) . is_continue( ) ) ;
662
+ assert ! ( i. push( 2_i32 ) . is_continue( ) ) ;
663
+ assert ! ( i. push( 3_i32 ) . is_continue( ) ) ;
664
+ assert ! ( i. push( 4_i32 ) . is_continue( ) ) ;
665
+ assert ! ( i. push( 5_i32 ) . is_break( ) ) ;
666
+ assert ! ( i. push( 6_i32 ) . is_break( ) ) ;
667
+ assert_eq ! ( i. pop:: <i32 >( ) , 4_i32 ) ;
668
+ assert_eq ! ( i. pop:: <i32 >( ) , 3_i32 ) ;
669
+ assert_eq ! ( i. pop:: <i32 >( ) , 2_i32 ) ;
670
+ assert_eq ! ( i. pop:: <i32 >( ) , 1_i32 ) ;
671
+ }
617
672
}
618
673
619
674
impl OpVisitor for Interpreter < ' _ > {
@@ -1083,68 +1138,68 @@ impl OpVisitor for Interpreter<'_> {
1083
1138
}
1084
1139
1085
1140
fn xpush32 ( & mut self , src : XReg ) -> ControlFlow < Done > {
1086
- self . state . push ( self . state [ src] . get_u32 ( ) ) ;
1141
+ self . push ( self . state [ src] . get_u32 ( ) ) ? ;
1087
1142
ControlFlow :: Continue ( ( ) )
1088
1143
}
1089
1144
1090
1145
fn xpush32_many ( & mut self , srcs : RegSet < XReg > ) -> ControlFlow < Done > {
1091
1146
for src in srcs {
1092
- self . state . push ( self . state [ src] . get_u32 ( ) ) ;
1147
+ self . xpush32 ( src) ? ;
1093
1148
}
1094
1149
ControlFlow :: Continue ( ( ) )
1095
1150
}
1096
1151
1097
1152
fn xpush64 ( & mut self , src : XReg ) -> ControlFlow < Done > {
1098
- self . state . push ( self . state [ src] . get_u64 ( ) ) ;
1153
+ self . push ( self . state [ src] . get_u64 ( ) ) ? ;
1099
1154
ControlFlow :: Continue ( ( ) )
1100
1155
}
1101
1156
1102
1157
fn xpush64_many ( & mut self , srcs : RegSet < XReg > ) -> ControlFlow < Done > {
1103
1158
for src in srcs {
1104
- self . state . push ( self . state [ src] . get_u64 ( ) ) ;
1159
+ self . xpush64 ( src) ? ;
1105
1160
}
1106
1161
ControlFlow :: Continue ( ( ) )
1107
1162
}
1108
1163
1109
1164
fn xpop32 ( & mut self , dst : XReg ) -> ControlFlow < Done > {
1110
- let val = self . state . pop ( ) ;
1165
+ let val = self . pop ( ) ;
1111
1166
self . state [ dst] . set_u32 ( val) ;
1112
1167
ControlFlow :: Continue ( ( ) )
1113
1168
}
1114
1169
1115
1170
fn xpop32_many ( & mut self , dsts : RegSet < XReg > ) -> ControlFlow < Done > {
1116
1171
for dst in dsts. into_iter ( ) . rev ( ) {
1117
- let val = self . state . pop ( ) ;
1172
+ let val = self . pop ( ) ;
1118
1173
self . state [ dst] . set_u32 ( val) ;
1119
1174
}
1120
1175
ControlFlow :: Continue ( ( ) )
1121
1176
}
1122
1177
1123
1178
fn xpop64 ( & mut self , dst : XReg ) -> ControlFlow < Done > {
1124
- let val = self . state . pop ( ) ;
1179
+ let val = self . pop ( ) ;
1125
1180
self . state [ dst] . set_u64 ( val) ;
1126
1181
ControlFlow :: Continue ( ( ) )
1127
1182
}
1128
1183
1129
1184
fn xpop64_many ( & mut self , dsts : RegSet < XReg > ) -> ControlFlow < Done > {
1130
1185
for dst in dsts. into_iter ( ) . rev ( ) {
1131
- let val = self . state . pop ( ) ;
1186
+ let val = self . pop ( ) ;
1132
1187
self . state [ dst] . set_u64 ( val) ;
1133
1188
}
1134
1189
ControlFlow :: Continue ( ( ) )
1135
1190
}
1136
1191
1137
1192
fn push_frame ( & mut self ) -> ControlFlow < Done > {
1138
- self . state . push ( self . state [ XReg :: lr] . get_ptr :: < u8 > ( ) ) ;
1139
- self . state . push ( self . state [ XReg :: fp] . get_ptr :: < u8 > ( ) ) ;
1193
+ self . push ( self . state [ XReg :: lr] . get_ptr :: < u8 > ( ) ) ? ;
1194
+ self . push ( self . state [ XReg :: fp] . get_ptr :: < u8 > ( ) ) ? ;
1140
1195
self . state [ XReg :: fp] = self . state [ XReg :: sp] ;
1141
1196
ControlFlow :: Continue ( ( ) )
1142
1197
}
1143
1198
1144
1199
fn pop_frame ( & mut self ) -> ControlFlow < Done > {
1145
- self . state [ XReg :: sp ] = self . state [ XReg :: fp] ;
1146
- let fp = self . state . pop ( ) ;
1147
- let lr = self . state . pop ( ) ;
1200
+ self . set_sp_unchecked ( self . state [ XReg :: fp] . get_ptr :: < u8 > ( ) ) ;
1201
+ let fp = self . pop ( ) ;
1202
+ let lr = self . pop ( ) ;
1148
1203
self . state [ XReg :: fp] . set_ptr :: < u8 > ( fp) ;
1149
1204
self . state [ XReg :: lr] . set_ptr :: < u8 > ( lr) ;
1150
1205
ControlFlow :: Continue ( ( ) )
0 commit comments