Calls and Recursion
Functions in WebAssembly call each other with the call instruction. Arguments are pushed onto the stack before the call; the return value (if any) is left on the stack when the callee returns. Wasm fully supports direct recursion — a function may call itself — and mutual recursion between functions defined in the same module.
The call instruction
Section titled “The call instruction”call $funcname invokes the named function. You can also call by index (call 0) but named references are far easier to read. Before executing call, push all arguments in left-to-right order:
(module (func $double (param $n i32) (result i32) local.get $n i32.const 2 i32.mul) (func (export "quadruple") (param $x i32) (result i32) local.get $x call $double ;; passes $x; result replaces it on stack call $double)) ;; doubles againquadruple(3) calls $double twice, producing 3 → 6 → 12.
Recursive functions
Section titled “Recursive functions”WAT allows a function to call itself. The pattern mirrors every other language: push arguments, call self, combine results. The base case uses if to return directly without a recursive call.
(module (func $factorial (export "factorial") (param $n i32) (result i32) local.get $n i32.const 1 i32.le_s ;; n <= 1? if (result i32) i32.const 1 ;; base case: 0! = 1! = 1 else local.get $n local.get $n i32.const 1 i32.sub call $factorial ;; factorial(n-1) i32.mul ;; n * factorial(n-1) end))The function is given both an internal name ($factorial) so it can call itself and an export name so JavaScript can invoke it.
Fibonacci example
Section titled “Fibonacci example”Two recursive calls in the else arm work the same way — push arguments, call, then add the two results:
(module (func $fib (export "fib") (param $n i32) (result i32) local.get $n i32.const 1 i32.le_s ;; n <= 1? if (result i32) local.get $n ;; fib(0)=0, fib(1)=1 else local.get $n i32.const 1 i32.sub call $fib ;; fib(n-1) local.get $n i32.const 2 i32.sub call $fib ;; fib(n-2) i32.add end))