@@ -14,7 +14,6 @@ use super::values::*;
1414use crate :: instance:: ModuleInstanceInner ;
1515use crate :: interpreter:: Value128 ;
1616use crate :: * ;
17-
1817pub ( crate ) struct Executor < ' store > {
1918 cf : CallFrame ,
2019 func : Rc < WasmFunction > ,
@@ -45,37 +44,24 @@ impl<'store> Executor<'store> {
4544 use tinywasm_types:: Instruction :: * ;
4645
4746 macro_rules! stack_op {
48- ( simd_unary $method: ident) => {
49- self . store. stack. values. unary_same:: <Value128 >( |v| Ok ( v. $method( ) ) ) . to_cf( ) ?
50- } ;
51- ( simd_binary $method: ident) => {
52- self . store. stack. values. binary_same:: <Value128 >( |a, b| Ok ( a. $method( b) ) ) . to_cf( ) ?
53- } ;
54- ( unary $ty: ty, |$v: ident| $expr: expr) => {
55- self . store. stack. values. unary_same:: <$ty>( |$v| Ok ( $expr) ) . to_cf( ) ?
56- } ;
57- ( binary $ty: ty, |$a: ident, $b: ident| $expr: expr) => {
58- self . store. stack. values. binary_same:: <$ty>( |$a, $b| Ok ( $expr) ) . to_cf( ) ?
59- } ;
60- ( binary_try $ty: ty, |$a: ident, $b: ident| $expr: expr) => {
61- self . store. stack. values. binary_same:: <$ty>( |$a, $b| $expr) . to_cf( ) ?
62- } ;
63- ( unary $from: ty => $to: ty, |$v: ident| $expr: expr) => {
64- self . store. stack. values. unary:: <$from, $to>( |$v| Ok ( $expr) ) . to_cf( ) ?
65- } ;
66- ( binary $from: ty => $to: ty, |$a: ident, $b: ident| $expr: expr) => {
67- self . store. stack. values. binary:: <$from, $to>( |$a, $b| Ok ( $expr) ) . to_cf( ) ?
68- } ;
69- ( binary $a: ty, $b: ty, |$lhs: ident, $rhs: ident| $expr: expr) => {
70- self . store. stack. values. binary_diff:: <$a, $b, $b>( |$lhs, $rhs| Ok ( $expr) ) . to_cf( ) ?
71- } ;
72- ( binary $a: ty, $b: ty => $res: ty, |$lhs: ident, $rhs: ident| $expr: expr) => {
73- self . store. stack. values. binary_diff:: <$a, $b, $res>( |$lhs, $rhs| Ok ( $expr) ) . to_cf( ) ?
74- } ;
47+ ( simd_unary $method: ident) => { stack_op!( unary Value128 , |v| v. $method( ) ) } ;
48+ ( simd_binary $method: ident) => { stack_op!( binary Value128 , |a, b| a. $method( b) ) } ;
49+ ( unary $ty: ty, |$v: ident| $expr: expr) => { self . store. stack. values. unary:: <$ty>( |$v| Ok ( $expr) ) . to_cf( ) ? } ;
50+ ( binary $ty: ty, |$a: ident, $b: ident| $expr: expr) => { self . store. stack. values. binary:: <$ty>( |$a, $b| Ok ( $expr) ) . to_cf( ) ? } ;
51+ ( binary try $ty: ty, |$a: ident, $b: ident| $expr: expr) => { self . store. stack. values. binary:: <$ty>( |$a, $b| $expr) . to_cf( ) ? } ;
52+ ( unary $from: ty => $to: ty, |$v: ident| $expr: expr) => { self . store. stack. values. unary_into:: <$from, $to>( |$v| Ok ( $expr) ) . to_cf( ) ? } ;
53+ ( binary $from: ty => $to: ty, |$a: ident, $b: ident| $expr: expr) => { self . store. stack. values. binary_into:: <$from, $to>( |$a, $b| Ok ( $expr) ) . to_cf( ) ? } ;
54+ ( binary $a: ty, $b: ty, |$lhs: ident, $rhs: ident| $expr: expr) => { stack_op!( binary $a, $b => $b, |$lhs, $rhs| $expr) } ;
55+ ( binary $a: ty, $b: ty => $res: ty, |$lhs: ident, $rhs: ident| $expr: expr) => { self . store. stack. values. binary_mixed:: <$a, $b, $res>( |$lhs, $rhs| Ok ( $expr) ) . to_cf( ) ? } ;
56+ ( ternary $ty: ty, |$a: ident, $b: ident, $c: ident| $expr: expr) => { self . store. stack. values. ternary:: <$ty>( |$a, $b, $c| Ok ( $expr) ) . to_cf( ) ? } ;
7557 ( local_set_pop $ty: ty, $local_index: expr) => { {
7658 let val = self . store. stack. values. pop:: <$ty>( ) ;
7759 self . store. stack. values. local_set( & self . cf, * $local_index, val) ;
7860 } } ;
61+ ( local_tee $ty: ty, $local_index: expr) => { {
62+ let val = self . store. stack. values. peek:: <$ty>( ) ;
63+ self . store. stack. values. local_set( & self . cf, * $local_index, val) ;
64+ } } ;
7965 }
8066
8167 let next = match self . func . instructions . 0 . get ( self . cf . instr_ptr as usize ) {
@@ -89,7 +75,7 @@ impl<'store> Executor<'store> {
8975
9076 #[ rustfmt:: skip]
9177 match next {
92- Nop | I32ReinterpretF32 | I64ReinterpretF64 | F32ReinterpretI32 | F64ReinterpretI64 | BranchTableTarget { .. } => { }
78+ Nop | I32ReinterpretF32 | I64ReinterpretF64 | F32ReinterpretI32 | F64ReinterpretI64 => { }
9379 Unreachable => return ControlFlow :: Break ( Some ( Trap :: Unreachable . into ( ) ) ) ,
9480 Drop32 => self . store . stack . values . drop :: < Value32 > ( ) ,
9581 Drop64 => self . store . stack . values . drop :: < Value64 > ( ) ,
@@ -106,20 +92,8 @@ impl<'store> Executor<'store> {
10692 ReturnCall ( v) => return self . exec_call_direct :: < true > ( * v) ,
10793 ReturnCallSelf => return self . exec_call_self :: < true > ( ) ,
10894 ReturnCallIndirect ( ty, table) => return self . exec_call_indirect :: < true > ( * ty, * table) ,
109- Jump ( ip) => {
110- self . cf . instr_ptr = * ip;
111- return ControlFlow :: Continue ( ( ) ) ;
112- }
113- JumpIfZero ( ip) => {
114- let cond = self . store . stack . values . pop :: < i32 > ( ) ;
115-
116- if cond == 0 {
117- self . cf . instr_ptr = * ip;
118- } else {
119- self . cf . incr_instr_ptr ( ) ;
120- }
121- return ControlFlow :: Continue ( ( ) ) ;
122- }
95+ Jump ( ip) => return self . exec_jump ( * ip) ,
96+ JumpIfZero ( ip) => if self . exec_jump_if_zero ( * ip) { return ControlFlow :: Continue ( ( ) ) ; } ,
12397 DropKeepSmall { base32, keep32, base64, keep64, base128, keep128, base_ref, keep_ref } => {
12498 let b32 = self . cf . stack_base ( ) . s32 + * base32 as u32 ;
12599 let k32 = * keep32 as usize ;
@@ -154,21 +128,8 @@ impl<'store> Executor<'store> {
154128 let k = * keep as usize ;
155129 self . store . stack . values . stack_ref . truncate_keep ( b as usize , k) ;
156130 }
157- BranchTable ( default_ip, len) => {
158- let idx = self . store . stack . values . pop :: < i32 > ( ) ;
159- let start = self . cf . instr_ptr + 1 ;
160-
161- let target_ip = if idx >= 0 && ( idx as u32 ) < * len {
162- match self . func . instructions . 0 . get ( ( start + idx as u32 ) as usize ) {
163- Some ( Instruction :: BranchTableTarget ( ip) ) => * ip,
164- _ => * default_ip,
165- }
166- } else {
167- * default_ip
168- } ;
169- self . cf . instr_ptr = target_ip;
170- return ControlFlow :: Continue ( ( ) ) ;
171- }
131+ BranchTable ( default_ip, len) => return self . exec_branch_table ( * default_ip, * len) ,
132+ BranchTableTarget { ..} => { } ,
172133 Return => return self . exec_return ( ) ,
173134 LocalGet32 ( local_index) => self . store . stack . values . push ( self . store . stack . values . local_get :: < Value32 > ( & self . cf , * local_index) ) . to_cf ( ) ?,
174135 LocalGet64 ( local_index) => self . store . stack . values . push ( self . store . stack . values . local_get :: < Value64 > ( & self . cf , * local_index) ) . to_cf ( ) ?,
@@ -214,14 +175,13 @@ impl<'store> Executor<'store> {
214175 }
215176 I64XorRotlConst ( c) => stack_op ! ( binary i64 , |lhs, rhs| ( lhs ^ rhs) . rotate_left( * c as u32 ) ) ,
216177 I64XorRotlConstTee ( c, local_index) => {
217- self . store . stack . values . binary_same :: < i64 > ( |lhs, rhs| Ok ( ( lhs ^ rhs) . rotate_left ( * c as u32 ) ) ) . to_cf ( ) ?;
218- let val = self . store . stack . values . peek :: < i64 > ( ) ;
219- self . store . stack . values . local_set ( & self . cf , * local_index, val) ;
178+ stack_op ! ( binary i64 , |lhs, rhs| ( lhs ^ rhs) . rotate_left( * c as u32 ) ) ;
179+ stack_op ! ( local_tee i64 , local_index) ;
220180 }
221- LocalTee32 ( local_index) => self . store . stack . values . local_set ( & self . cf , * local_index , self . store . stack . values . peek :: < Value32 > ( ) ) ,
222- LocalTee64 ( local_index) => self . store . stack . values . local_set ( & self . cf , * local_index , self . store . stack . values . peek :: < Value64 > ( ) ) ,
223- LocalTee128 ( local_index) => self . store . stack . values . local_set ( & self . cf , * local_index , self . store . stack . values . peek :: < Value128 > ( ) ) ,
224- LocalTeeRef ( local_index) => self . store . stack . values . local_set ( & self . cf , * local_index , self . store . stack . values . peek :: < ValueRef > ( ) ) ,
181+ LocalTee32 ( local_index) => stack_op ! ( local_tee Value32 , local_index ) ,
182+ LocalTee64 ( local_index) => stack_op ! ( local_tee Value64 , local_index ) ,
183+ LocalTee128 ( local_index) => stack_op ! ( local_tee Value128 , local_index ) ,
184+ LocalTeeRef ( local_index) => stack_op ! ( local_tee ValueRef , local_index ) ,
225185 GlobalGet ( global_index) => self . exec_global_get ( * global_index) . to_cf ( ) ?,
226186 GlobalSet32 ( global_index) => self . exec_global_set :: < Value32 > ( * global_index) ,
227187 GlobalSet64 ( global_index) => self . exec_global_set :: < Value64 > ( * global_index) ,
@@ -279,14 +239,14 @@ impl<'store> Executor<'store> {
279239 I64Mul => stack_op ! ( binary i64 , |a, b| a. wrapping_mul( b) ) ,
280240 F32Mul => stack_op ! ( binary f32 , |a, b| a * b) ,
281241 F64Mul => stack_op ! ( binary f64 , |a, b| a * b) ,
282- I32DivS => stack_op ! ( binary_try i32 , |a, b| a. wasm_checked_div( b) ) ,
283- I64DivS => stack_op ! ( binary_try i64 , |a, b| a. wasm_checked_div( b) ) ,
284- I32DivU => stack_op ! ( binary_try u32 , |a, b| a. checked_div( b) . ok_or_else( trap_0) ) ,
285- I64DivU => stack_op ! ( binary_try u64 , |a, b| a. checked_div( b) . ok_or_else( trap_0) ) ,
286- I32RemS => stack_op ! ( binary_try i32 , |a, b| a. checked_wrapping_rem( b) ) ,
287- I64RemS => stack_op ! ( binary_try i64 , |a, b| a. checked_wrapping_rem( b) ) ,
288- I32RemU => stack_op ! ( binary_try u32 , |a, b| a. checked_wrapping_rem( b) ) ,
289- I64RemU => stack_op ! ( binary_try u64 , |a, b| a. checked_wrapping_rem( b) ) ,
242+ I32DivS => stack_op ! ( binary try i32 , |a, b| a. wasm_checked_div( b) ) ,
243+ I64DivS => stack_op ! ( binary try i64 , |a, b| a. wasm_checked_div( b) ) ,
244+ I32DivU => stack_op ! ( binary try u32 , |a, b| a. checked_div( b) . ok_or_else( trap_0) ) ,
245+ I64DivU => stack_op ! ( binary try u64 , |a, b| a. checked_div( b) . ok_or_else( trap_0) ) ,
246+ I32RemS => stack_op ! ( binary try i32 , |a, b| a. checked_wrapping_rem( b) ) ,
247+ I64RemS => stack_op ! ( binary try i64 , |a, b| a. checked_wrapping_rem( b) ) ,
248+ I32RemU => stack_op ! ( binary try u32 , |a, b| a. checked_wrapping_rem( b) ) ,
249+ I64RemU => stack_op ! ( binary try u64 , |a, b| a. checked_wrapping_rem( b) ) ,
290250 I32And => stack_op ! ( binary i32 , |a, b| a & b) ,
291251 I64And => stack_op ! ( binary i64 , |a, b| a & b) ,
292252 I32Or => stack_op ! ( binary i32 , |a, b| a | b) ,
@@ -424,7 +384,7 @@ impl<'store> Executor<'store> {
424384 V128AndNot => stack_op ! ( binary Value128 , |a, b| a. v128_andnot( b) ) ,
425385 V128Or => stack_op ! ( binary Value128 , |a, b| a. v128_or( b) ) ,
426386 V128Xor => stack_op ! ( binary Value128 , |a, b| a. v128_xor( b) ) ,
427- V128Bitselect => self . store . stack . values . ternary_same :: < Value128 > ( |v1, v2, c| Ok ( Value128 :: v128_bitselect ( v1, v2, c) ) ) . to_cf ( ) ? ,
387+ V128Bitselect => stack_op ! ( ternary Value128 , |v1, v2, c| Value128 :: v128_bitselect( v1, v2, c) ) ,
428388 V128AnyTrue => stack_op ! ( unary Value128 => i32 , |v| v. v128_any_true( ) as i32 ) ,
429389 I8x16Swizzle => stack_op ! ( binary Value128 , |a, s| a. i8x16_swizzle( s) ) ,
430390 V128Load ( arg) => self . exec_mem_load :: < Value128 , 16 , _ > ( arg. mem_addr ( ) , arg. offset ( ) , |v| v) ?,
@@ -661,6 +621,39 @@ impl<'store> Executor<'store> {
661621 ControlFlow :: Continue ( ( ) )
662622 }
663623
624+ #[ inline( always) ]
625+ fn exec_jump ( & mut self , ip : u32 ) -> ControlFlow < Option < Error > > {
626+ self . cf . instr_ptr = ip;
627+ ControlFlow :: Continue ( ( ) )
628+ }
629+
630+ #[ inline( always) ]
631+ fn exec_jump_if_zero ( & mut self , ip : u32 ) -> bool {
632+ if self . store . stack . values . pop :: < i32 > ( ) == 0 {
633+ self . cf . instr_ptr = ip;
634+ return true ;
635+ }
636+ false
637+ }
638+
639+ #[ inline( always) ]
640+ fn exec_branch_table ( & mut self , default_ip : u32 , len : u32 ) -> ControlFlow < Option < Error > > {
641+ let idx = self . store . stack . values . pop :: < i32 > ( ) ;
642+ let start = self . cf . instr_ptr + 1 ;
643+
644+ let target_ip = if idx >= 0 && ( idx as u32 ) < len {
645+ match self . func . instructions . 0 . get ( ( start + idx as u32 ) as usize ) {
646+ Some ( Instruction :: BranchTableTarget ( ip) ) => * ip,
647+ _ => default_ip,
648+ }
649+ } else {
650+ default_ip
651+ } ;
652+
653+ self . cf . instr_ptr = target_ip;
654+ ControlFlow :: Continue ( ( ) )
655+ }
656+
664657 fn exec_call < const IS_RETURN_CALL : bool > (
665658 & mut self ,
666659 wasm_func : Rc < WasmFunction > ,
@@ -943,6 +936,7 @@ impl<'store> Executor<'store> {
943936 ControlFlow :: Continue ( ( ) )
944937 }
945938
939+ #[ inline( always) ]
946940 fn exec_mem_load < LOAD : MemValue < LOAD_SIZE > , const LOAD_SIZE : usize , TARGET : InternalValue > (
947941 & mut self ,
948942 mem_addr : tinywasm_types:: MemAddr ,
@@ -951,18 +945,28 @@ impl<'store> Executor<'store> {
951945 ) -> ControlFlow < Option < Error > > {
952946 let mem = self . store . state . get_mem ( self . module . resolve_mem_addr ( mem_addr) ) ;
953947
954- let addr = match mem. is_64bit ( ) {
955- true => self . store . stack . values . pop :: < i64 > ( ) as u64 ,
956- false => u64:: from ( self . store . stack . values . pop :: < i32 > ( ) as u32 ) ,
948+ let base: u64 = if mem. is_64bit ( ) {
949+ self . store . stack . values . pop :: < i64 > ( ) as u64
950+ } else {
951+ self . store . stack . values . pop :: < i32 > ( ) as u32 as u64
957952 } ;
958953
959- let Some ( Ok ( addr) ) = offset . checked_add ( addr ) . map ( |a| a . try_into ( ) ) else {
954+ let Some ( addr) = base . checked_add ( offset ) else {
960955 return ControlFlow :: Break ( Some ( Error :: Trap ( Trap :: MemoryOutOfBounds {
961- offset : addr as usize ,
956+ offset : base as usize ,
962957 len : LOAD_SIZE ,
963958 max : 0 ,
964959 } ) ) ) ;
965960 } ;
961+
962+ let Ok ( addr) = usize:: try_from ( addr) else {
963+ return ControlFlow :: Break ( Some ( Error :: Trap ( Trap :: MemoryOutOfBounds {
964+ offset : base as usize ,
965+ len : LOAD_SIZE ,
966+ max : 0 ,
967+ } ) ) ) ;
968+ } ;
969+
966970 let val = mem. load_as :: < LOAD_SIZE , LOAD > ( addr) . to_cf ( ) ?;
967971 self . store . stack . values . push ( cast ( val) ) . to_cf ( ) ?;
968972 ControlFlow :: Continue ( ( ) )
0 commit comments