11use alloc:: format;
2+ use alloc:: rc:: Rc ;
23use alloc:: string:: ToString ;
3- use core:: ops:: { BitAnd , BitOr , BitXor , Neg } ;
4- use tinywasm_types:: { BlockArgs , ElementKind , Instruction , ValType } ;
4+ use core:: ops:: { BitAnd , BitOr , BitXor , ControlFlow , Neg } ;
5+ use tinywasm_types:: { BlockArgs , ElementKind , Instruction , ModuleInstanceAddr , ValType , WasmFunction } ;
56
67use super :: stack:: { BlockFrame , BlockType } ;
78use super :: { InterpreterRuntime , RawWasmValue , Stack } ;
@@ -35,11 +36,6 @@ struct Executor<'store, 'stack> {
3536 module : ModuleInstance ,
3637}
3738
38- enum ExecResult {
39- Continue ,
40- Return ,
41- }
42-
4339impl < ' store , ' stack > Executor < ' store , ' stack > {
4440 pub ( crate ) fn new ( store : & ' store mut Store , stack : & ' stack mut Stack ) -> Result < Self > {
4541 let current_frame = stack. call_stack . pop ( ) ?;
@@ -49,19 +45,15 @@ impl<'store, 'stack> Executor<'store, 'stack> {
4945
5046 pub ( crate ) fn run_to_completion ( & mut self ) -> Result < ( ) > {
5147 loop {
52- match self . next ( ) {
53- Ok ( ExecResult :: Return ) => return Ok ( ( ) ) ,
54- Ok ( ExecResult :: Continue ) => continue ,
55- Err ( e) => {
56- cold ( ) ;
57- return Err ( e) ;
58- }
48+ match self . next ( ) ? {
49+ ControlFlow :: Break ( ..) => return Ok ( ( ) ) ,
50+ ControlFlow :: Continue ( ..) => continue ,
5951 } ;
6052 }
6153 }
6254
6355 #[ inline( always) ]
64- pub ( crate ) fn next ( & mut self ) -> Result < ExecResult > {
56+ pub ( crate ) fn next ( & mut self ) -> Result < ControlFlow < ( ) > > {
6557 use tinywasm_types:: Instruction :: * ;
6658 match self . cf . fetch_instr ( ) {
6759 Nop => cold ( ) ,
@@ -70,7 +62,7 @@ impl<'store, 'stack> Executor<'store, 'stack> {
7062 Drop => self . stack . values . pop ( ) . map ( |_| ( ) ) ?,
7163 Select ( _valtype) => self . exec_select ( ) ?,
7264
73- Call ( v) => return self . exec_call ( * v) ,
65+ Call ( v) => return self . exec_call_direct ( * v) ,
7466 CallIndirect ( ty, table) => return self . exec_call_indirect ( * ty, * table) ,
7567
7668 If ( args, el, end) => return self . exec_if ( ( * args) . into ( ) , * el, * end) ,
@@ -310,7 +302,7 @@ impl<'store, 'stack> Executor<'store, 'stack> {
310302 } ;
311303
312304 self . cf . instr_ptr += 1 ;
313- Ok ( ExecResult :: Continue )
305+ Ok ( ControlFlow :: Continue ( ( ) ) )
314306 }
315307
316308 #[ inline( always) ]
@@ -337,18 +329,17 @@ impl<'store, 'stack> Executor<'store, 'stack> {
337329 }
338330
339331 #[ inline( always) ]
340- fn exec_br_if ( & mut self , to : u32 ) -> Result < ExecResult > {
332+ fn exec_br_if ( & mut self , to : u32 ) -> Result < ControlFlow < ( ) > > {
341333 let val: i32 = self . stack . values . pop ( ) ?. into ( ) ;
342334 if val != 0 {
343335 break_to ! ( to, self ) ;
344336 }
345-
346337 self . cf . instr_ptr += 1 ;
347- Ok ( ExecResult :: Continue )
338+ Ok ( ControlFlow :: Continue ( ( ) ) )
348339 }
349340
350341 #[ inline( always) ]
351- fn exec_brtable ( & mut self , default : u32 , len : u32 ) -> Result < ExecResult > {
342+ fn exec_brtable ( & mut self , default : u32 , len : u32 ) -> Result < ControlFlow < ( ) > > {
352343 let start = self . cf . instr_ptr + 1 ;
353344 let end = start + len as usize ;
354345 if end > self . cf . instructions ( ) . len ( ) {
@@ -364,13 +355,14 @@ impl<'store, 'stack> Executor<'store, 'stack> {
364355 }
365356
366357 self . cf . instr_ptr += 1 ;
367- Ok ( ExecResult :: Continue )
358+ Ok ( ControlFlow :: Continue ( ( ) ) )
368359 }
369360
370361 #[ inline( always) ]
371- fn exec_return ( & mut self ) -> Result < ExecResult > {
362+ fn exec_return ( & mut self ) -> Result < ControlFlow < ( ) > > {
363+ // returning from the main function is a break
372364 if self . stack . call_stack . is_empty ( ) {
373- return Ok ( ExecResult :: Return ) ;
365+ return Ok ( ControlFlow :: Break ( ( ) ) ) ;
374366 }
375367
376368 let old = self . cf . block_ptr ;
@@ -384,7 +376,7 @@ impl<'store, 'stack> Executor<'store, 'stack> {
384376 self . module . swap_with ( self . cf . module_addr , self . store ) ;
385377 }
386378
387- Ok ( ExecResult :: Continue )
379+ Ok ( ControlFlow :: Continue ( ( ) ) )
388380 }
389381
390382 #[ inline( always) ]
@@ -645,7 +637,17 @@ impl<'store, 'stack> Executor<'store, 'stack> {
645637 }
646638
647639 #[ inline( always) ]
648- fn exec_call ( & mut self , v : u32 ) -> Result < ExecResult > {
640+ fn exec_call ( & mut self , wasm_func : Rc < WasmFunction > , owner : ModuleInstanceAddr ) -> Result < ControlFlow < ( ) > > {
641+ let params = self . stack . values . pop_n_rev ( wasm_func. ty . params . len ( ) ) ?;
642+ let new_call_frame = CallFrame :: new ( wasm_func, owner, params, self . stack . blocks . len ( ) as u32 ) ;
643+ self . cf . instr_ptr += 1 ; // skip the call instruction
644+ self . stack . call_stack . push ( core:: mem:: replace ( & mut self . cf , new_call_frame) ) ?;
645+ self . module . swap_with ( self . cf . module_addr , self . store ) ;
646+ Ok ( ControlFlow :: Continue ( ( ) ) )
647+ }
648+
649+ #[ inline( always) ]
650+ fn exec_call_direct ( & mut self , v : u32 ) -> Result < ControlFlow < ( ) > > {
649651 let func_inst = self . store . get_func ( self . module . resolve_func_addr ( v) ) ?;
650652 let wasm_func = match & func_inst. func {
651653 crate :: Function :: Wasm ( wasm_func) => wasm_func,
@@ -655,38 +657,27 @@ impl<'store, 'stack> Executor<'store, 'stack> {
655657 let res = ( func. func ) ( FuncContext { store : self . store , module_addr : self . module . id ( ) } , & params) ?;
656658 self . stack . values . extend_from_typed ( & res) ;
657659 self . cf . instr_ptr += 1 ;
658- return Ok ( ExecResult :: Continue ) ;
660+ return Ok ( ControlFlow :: Continue ( ( ) ) ) ;
659661 }
660662 } ;
661-
662- let params = self . stack . values . pop_n_rev ( wasm_func. ty . params . len ( ) ) ?;
663- let new_call_frame = CallFrame :: new ( wasm_func. clone ( ) , func_inst. owner , params, self . stack . blocks . len ( ) as u32 ) ;
664-
665- self . cf . instr_ptr += 1 ; // skip the call instruction
666- self . stack . call_stack . push ( core:: mem:: replace ( & mut self . cf , new_call_frame) ) ?;
667- if self . cf . module_addr != self . module . id ( ) {
668- self . module . swap_with ( self . cf . module_addr , self . store ) ;
669- }
670- Ok ( ExecResult :: Continue )
663+ return self . exec_call ( wasm_func. clone ( ) , func_inst. owner ) ;
671664 }
672665
673666 #[ inline( always) ]
674- fn exec_call_indirect ( & mut self , type_addr : u32 , table_addr : u32 ) -> Result < ExecResult > {
675- let table = self . store . get_table ( self . module . resolve_table_addr ( table_addr) ) ?;
676- let table_idx: u32 = self . stack . values . pop ( ) ?. into ( ) ;
677-
667+ fn exec_call_indirect ( & mut self , type_addr : u32 , table_addr : u32 ) -> Result < ControlFlow < ( ) > > {
678668 // verify that the table is of the right type, this should be validated by the parser already
679669 let func_ref = {
670+ let table = self . store . get_table ( self . module . resolve_table_addr ( table_addr) ) ?;
671+ let table_idx: u32 = self . stack . values . pop ( ) ?. into ( ) ;
680672 let table = table. borrow ( ) ;
681673 assert ! ( table. kind. element_type == ValType :: RefFunc , "table is not of type funcref" ) ;
682674 table. get ( table_idx) ?. addr ( ) . ok_or ( Trap :: UninitializedElement { index : table_idx as usize } ) ?
683675 } ;
684676
685- let func_inst = self . store . get_func ( func_ref) ?. clone ( ) ;
677+ let func_inst = self . store . get_func ( func_ref) ?;
686678 let call_ty = self . module . func_ty ( type_addr) ;
687-
688- let wasm_func = match func_inst. func {
689- crate :: Function :: Wasm ( ref f) => f,
679+ let wasm_func = match & func_inst. func {
680+ crate :: Function :: Wasm ( f) => f,
690681 crate :: Function :: Host ( host_func) => {
691682 if unlikely ( host_func. ty != * call_ty) {
692683 return Err ( Trap :: IndirectCallTypeMismatch {
@@ -701,48 +692,38 @@ impl<'store, 'stack> Executor<'store, 'stack> {
701692 let res = ( host_func. func ) ( FuncContext { store : self . store , module_addr : self . module . id ( ) } , & params) ?;
702693 self . stack . values . extend_from_typed ( & res) ;
703694 self . cf . instr_ptr += 1 ;
704- return Ok ( ExecResult :: Continue ) ;
695+ return Ok ( ControlFlow :: Continue ( ( ) ) ) ;
705696 }
706697 } ;
707698
708- if unlikely ( wasm_func. ty != * call_ty) {
709- return Err (
710- Trap :: IndirectCallTypeMismatch { actual : wasm_func. ty . clone ( ) , expected : call_ty. clone ( ) } . into ( )
711- ) ;
712- }
713-
714- let params = self . stack . values . pop_n_rev ( wasm_func. ty . params . len ( ) ) ?;
715- let new_call_frame = CallFrame :: new ( wasm_func. clone ( ) , func_inst. owner , params, self . stack . blocks . len ( ) as u32 ) ;
716-
717- self . cf . instr_ptr += 1 ; // skip the call instruction
718- self . stack . call_stack . push ( core:: mem:: replace ( & mut self . cf , new_call_frame) ) ?;
719- if self . cf . module_addr != self . module . id ( ) {
720- self . module . swap_with ( self . cf . module_addr , self . store ) ;
699+ if wasm_func. ty == * call_ty {
700+ return self . exec_call ( wasm_func. clone ( ) , func_inst. owner ) ;
721701 }
722702
723- Ok ( ExecResult :: Continue )
703+ cold ( ) ;
704+ return Err ( Trap :: IndirectCallTypeMismatch { actual : wasm_func. ty . clone ( ) , expected : call_ty. clone ( ) } . into ( ) ) ;
724705 }
725706
726707 #[ inline( always) ]
727- fn exec_if ( & mut self , args : BlockArgs , else_offset : u32 , end_offset : u32 ) -> Result < ExecResult > {
708+ fn exec_if ( & mut self , args : BlockArgs , else_offset : u32 , end_offset : u32 ) -> Result < ControlFlow < ( ) > > {
728709 // truthy value is on the top of the stack, so enter the then block
729710 if i32:: from ( self . stack . values . pop ( ) ?) != 0 {
730711 self . enter_block ( self . cf . instr_ptr , end_offset, BlockType :: If , args) ;
731712 self . cf . instr_ptr += 1 ;
732- return Ok ( ExecResult :: Continue ) ;
713+ return Ok ( ControlFlow :: Continue ( ( ) ) ) ;
733714 }
734715
735716 // falsy value is on the top of the stack
736717 if else_offset == 0 {
737718 self . cf . instr_ptr += end_offset as usize + 1 ;
738- return Ok ( ExecResult :: Continue ) ;
719+ return Ok ( ControlFlow :: Continue ( ( ) ) ) ;
739720 }
740721
741722 let old = self . cf . instr_ptr ;
742723 self . cf . instr_ptr += else_offset as usize ;
743724 self . enter_block ( old + else_offset as usize , end_offset - else_offset, BlockType :: Else , args) ;
744725 self . cf . instr_ptr += 1 ;
745- Ok ( ExecResult :: Continue )
726+ Ok ( ControlFlow :: Continue ( ( ) ) )
746727 }
747728
748729 #[ inline( always) ]
@@ -790,7 +771,7 @@ impl<'store, 'stack> Executor<'store, 'stack> {
790771 instr_ptr,
791772 end_instr_offset,
792773 stack_ptr : self . stack . values . len ( ) as u32 - params as u32 ,
793- simd_stack_ptr : self . stack . values . simd_len ( ) as u32 - simd_params as u32 ,
774+ simd_stack_ptr : self . stack . values . simd_len ( ) as u16 - simd_params as u16 ,
794775 results,
795776 simd_params,
796777 simd_results,
0 commit comments