WASM Syntax

Scope: Learn WAT fundamentals and the host interop model required for production-safe modules.

Syntax

WASM binaries are typically generated by compilers, but understanding text format (WAT) helps you reason about stack operations, memory access, and host contracts.

Module Structure

(module
  (func $add (param $a i32) (param $b i32) (result i32)
    local.get $a
    local.get $b
    i32.add)
  (export "add" (func $add)))
  • module is the root container.
  • func declares typed functions.
  • export exposes symbols to host runtime.

Stack Model

Instruction flow

Instructions push and pop typed values from a virtual stack. Validation guarantees type safety at compile/instantiate time.

local.get $a ;; push i32
local.get $b ;; push i32
i32.add      ;; pop 2, push 1

Types and Locals

  • Numeric types: i32, i64, f32, f64.
  • Use locals for intermediate values; avoid overusing memory for temporary state.
  • Reference types and advanced proposals exist, but start with stable core model first.

Memory

Linear memory

WASM uses contiguous linear memory. Host and module coordinate offsets and lengths explicitly.

(memory (export "memory") 1)
(data (i32.const 0) "Hello")

Safety contracts

  • Always validate pointers and lengths at host boundary.
  • Define ownership conventions for allocated buffers.
  • Document UTF-8/string encoding assumptions.

Imports and Exports

(import "env" "log" (func $log (param i32)))
(func $run
  i32.const 42
  call $log)
(export "run" (func $run))

Treat imports as dependency injection. Keep explicit interface map and versioning policy.

JS Interop

const imports = {
  env: {
    log(value) {
      console.log('wasm:', value);
    }
  }
};

const { instance } = await WebAssembly.instantiateStreaming(fetch('/module.wasm'), imports);
instance.exports.run();

Engineering Notes

Interop code is where most defects occur. Keep thin adapters, typed wrappers, and boundary tests.

Common Mistakes

  • Assuming JS and WASM share automatic memory/object semantics.
  • Hardcoding offsets without documented memory layout.
  • Ignoring module validation or instantiate errors in runtime logging.

Practice Scope

Create one WAT module that exports arithmetic and string-length operations, then consume it from JavaScript with explicit boundary checks.

Back to roadmap: WASM Roadmap