WASM is not quite a stack machine

· ai · Source ↗

TLDR

  • WebAssembly lacks the stack manipulation instructions (dup, swap, over, rot) that define real stack machines, making it closer to a register machine with RPN-encoded compound expressions.

Key Takeaways

  • Real stack machines like JVM provide dup, swap, pop, and over; Wasm ships only drop, which exists solely to discard unwanted function return values.
  • Without dup/swap, Wasm cannot perform common subexpression elimination or rewrite expr^2 as expr * expr without introducing local variables.
  • The moment any non-trivial value reuse is needed, Wasm code falls back to locals, collapsing the “stack machine” abstraction entirely.
  • Binary Wasm encodes expressions in Reverse Polish notation for interpreter simplicity; textual WAT uses S-expressions – both are just encodings of a register model, not evidence of a stack model.
  • Until the multi-value extension, control flow blocks (if, block) could not read values from the outer stack and could only return one value, further breaking the stack-machine model.

Hacker News Comment Review

  • One implementor building a Wasm-to-C compiler confirms the self-contained expression property: because Wasm locals absorb all reuse, each function’s stack never needs external discard or reset logic.
  • The observation that WAT’s S-expression syntax reflects the true register-with-compound-expressions model – not a stack model – is treated as a practical convenience, not a workaround.

Notable Comments

  • @stevefan1999: implementing Wasm-to-C; notes the non-stack behavior means expressions are fully self-contained per function – “I don’t have to discard or reset stack value” – and credits this for WAT’s clean S-expression representation.

Original | Discuss on HN