WasmIR is the small canonical SSA representation between canonical MIR and
wasm-encoder. It is WebAssembly-oriented but is not WebAssembly text, a
module format, or a second semantic IR.
Its governing rule is:
The encoder emits an instruction from the instruction’s fields, the read-only frame layout, and read-only module indices. It does not make a language, layout, continuation, or calling-convention decision.
Function
A WasmIRFn contains:
- a function kind and explicit WebAssembly parameter/result types;
- dense virtual-register type, definition, and origin tables;
- basic blocks, block parameters, and an entry block;
- a shared reference to the finalized MIR frame layout;
- optional human-readable debug names;
- instruction-to-MIR provenance;
- a flag selecting the relocation-safe arena-base discipline.
Every virtual register has one natural WasmTy and exactly one definition.
Every block ends in one Term. The entry block is reachable and has no block
parameters.
Function kinds
FnKind fixes the encoded signature:
| Kind | Parameters | Purpose |
|---|---|---|
Continuation |
five i32 values: arena base, frame offset, handle, tag, value |
Entry, resume, or loop-step runtime target |
BlockFn |
arena base, frame offset, then typed live-ins | Hoisted CFG region |
Direct |
natural typed parameters and results | Non-suspending value-ABI function |
The kind is descriptive at this layer, not permission for the encoder to recreate a prologue policy. MIR canonicalization and WasmIR lowering have already materialized required frame writes, value conversions, scheduler operations, and branches.
Three invariants
Self-contained instructions
An instruction’s fields determine its emitted byte behavior. Frame loads/stores name a frame slot; flex accesses name a base, offset, and width; calls name their selected index, arguments, results, and call kind.
Natural values
Every VReg has one of I32, I64, F32, F64, or V128. There are no
virtual i8, i16, aggregate, optional, string, or semantic enum values.
Those values have already been mapped to natural carriers.
Explicit boundaries
Width conversions are explicit Convert instructions except at typed storage
boundaries, where width and signedness select the exact load/store behavior.
This exception exists because WebAssembly has no first-class i8, i16, or
i128 value type.
Pipeline
canonical primitive MIR
↓ mechanical lowering
WasmIR
↓ forwarding, folding, DCE, peepholes, branch simplification, CSE
optimized WasmIR
↓ liveness, register allocation, stack residency, control structuring
encodable WasmIR
↓ encoding
WebAssembly function bodyEvery optimization consumes the effect classification rather than maintaining its own incomplete opcode list. Verifiers run after construction and, in debug builds, after transformations.
Exclusions
WasmIR deliberately excludes:
- unresolved Atoll types or type registry queries;
- trait, method, or overload selection;
- generic specialization;
- continuation-kind dispatch policy;
- enum layout discovery or aggregate field placement;
- implicit calling-convention selection;
- unit discovery, section merging, and final module linking.
Module assembly is documented in WebAssembly and Linking. This section defines only function-level IR and its direct encoding obligations.
Read Values for representation, Control for CFG shape, and Effects for optimization and verification.