litmus8.js (1511B)
1 // Tail-call litmus test with multiple results 2 // 3 // Mutually recursive functions implement a multi-entry loop using tail calls, 4 // with exception handling. 5 // 6 // The functions do not have the same signatures, so if all arguments are stack 7 // arguments then these use different amounts of stack space. 8 // 9 // The "even" function will throw when the input is zero, so when an exception 10 // bubbles out of return_call it must not be caught by the exception handler in 11 // "odd", but must instead be delegated to the caller, which is JS code. 12 13 var ins = wasmEvalText(` 14 (module 15 (tag $t) 16 (func $odd (export "odd") (param $n i32) (param $dummy i32) (result i32 i32 i32) 17 try (result i32 i32 i32) 18 (if (result i32 i32 i32) (i32.eqz (local.get $n)) 19 (then (return (i32.const 0) (i32.const 32769) (i32.const -37))) 20 (else (return_call $even (i32.sub (local.get $n) (i32.const 1))))) 21 catch_all 22 unreachable 23 end) 24 25 (func $even (export "even") (param $n i32) (result i32 i32 i32) 26 (if (result i32 i32 i32) (i32.eqz (local.get $n)) 27 (then (throw $t)) 28 (else (return_call $odd (i32.sub (local.get $n) (i32.const 1)) (i32.const 33))))) 29 ) 30 `); 31 32 assertErrorMessage(() => ins.exports.even(TailCallIterations), WebAssembly.Exception, /.*/); 33 assertSame(ins.exports.odd(TailCallIterations, 33), [0, 32769, -37]); 34 35 assertErrorMessage(() => ins.exports.odd(TailCallIterations+1, 33), WebAssembly.Exception, /.*/); 36 assertSame(ins.exports.even(TailCallIterations+1), [0, 32769, -37]);