@@ -35,6 +35,7 @@ impl DefaultRuntime {
3535 match exec_one ( & mut cf, instr, instrs, stack, store, & module) ? {
3636 // Continue execution at the new top of the call stack
3737 ExecResult :: Call => {
38+ cf = stack. call_stack . pop ( ) ?;
3839 func = store. get_func ( cf. func_ptr ) ?. clone ( ) ;
3940 instrs = func. instructions ( ) ;
4041 continue ;
@@ -76,18 +77,17 @@ enum ExecResult {
7677
7778// Break to a block at the given index (relative to the current frame)
7879// If there is no block at the given index, return or call the parent function
80+ //
81+ // This is a bit hard to see from the spec, but it's vaild to use breaks to return
82+ // from a function, so we need to check if the label stack is empty
7983macro_rules! break_to {
8084 ( $cf: ident, $stack: ident, $break_to_relative: ident) => { {
81- let res = $cf. break_to( * $break_to_relative, & mut $stack. values) ;
82- match res {
83- Some ( ( ) ) => { }
84- None => match $stack. call_stack. is_empty( ) {
85- true => return Ok ( ExecResult :: Return ) ,
86- false => {
87- * $cf = $stack. call_stack. pop( ) ?;
88- return Ok ( ExecResult :: Call ) ;
89- }
90- } ,
85+ if $cf. break_to( * $break_to_relative, & mut $stack. values) . is_none( ) {
86+ if $stack. call_stack. is_empty( ) {
87+ return Ok ( ExecResult :: Return ) ;
88+ } else {
89+ return Ok ( ExecResult :: Call ) ;
90+ }
9191 }
9292 } } ;
9393}
@@ -143,8 +143,6 @@ fn exec_one(
143143 stack. call_stack . push ( call_frame) ;
144144
145145 // call the function
146- * cf = stack. call_stack . pop ( ) ?;
147- debug ! ( "calling: {:?}" , func) ;
148146 return Ok ( ExecResult :: Call ) ;
149147 }
150148
@@ -221,6 +219,7 @@ fn exec_one(
221219 if instr. len ( ) != * len {
222220 panic ! ( "Expected {} BrLabel instructions, got {}" , len, instr. len( ) ) ;
223221 }
222+ cf. instr_ptr += * len;
224223
225224 todo ! ( "br_table" ) ;
226225 }
@@ -234,27 +233,22 @@ fn exec_one(
234233
235234 Return => match stack. call_stack . is_empty ( ) {
236235 true => return Ok ( ExecResult :: Return ) ,
237- false => {
238- * cf = stack. call_stack . pop ( ) ?;
239- return Ok ( ExecResult :: Call ) ;
240- }
236+ false => return Ok ( ExecResult :: Call ) ,
241237 } ,
242238
243239 EndFunc => {
244- if cf. labels . len ( ) > 0 {
245- panic ! ( "endfunc: block frames not empty, this should have been validated by the parser" ) ;
246- }
240+ debug_assert ! (
241+ cf. labels. len( ) > 0 ,
242+ "endfunc: block frames not empty, this should have been validated by the parser"
243+ ) ;
247244
248245 match stack. call_stack . is_empty ( ) {
249246 true => return Ok ( ExecResult :: Return ) ,
250- false => {
251- * cf = stack. call_stack . pop ( ) ?;
252- return Ok ( ExecResult :: Call ) ;
253- }
247+ false => return Ok ( ExecResult :: Call ) ,
254248 }
255249 }
256250
257- // We're essentially using else as a EndBlockFrame instruction
251+ // We're essentially using else as a EndBlockFrame instruction for if blocks
258252 Else ( end_offset) => {
259253 let Some ( block) = cf. labels . pop ( ) else {
260254 panic ! ( "else: no label to end, this should have been validated by the parser" ) ;
0 commit comments