Mid-level Intermediate Representation is Atoll’s main optimization and lowering boundary. It receives monomorphic HIR and represents a function as a typed control-flow graph with block parameters, explicit suspension points, storage classifications, ownership operations, and backend-neutral ABI plans.
MIR is SSA-oriented, but it is not unconditionally strict SSA. A LocalId
names the unit of value flow and most transformations create fresh locals;
mutable source bindings and selected transformations can give a local more
than one definition. Passes that require strict single assignment must request
or prove the dedicated SSA discipline instead of assuming it from the name.
Function
An IrFunction combines several layers of facts:
| Layer | Contents |
|---|---|
| Semantic identity | symbol, type, effects, source range |
| Control | blocks, entry block, parameters, exits |
| Values | typed locals and operation operands |
| Suspension | continuation form, continuation classes, resume sites |
| Storage | local storage, frame layout, ABI layout |
| Ownership | RC modes, clone/drop/reuse operations, borrowing facts |
| Analysis | liveness, loop headers, scope exits, recursion and pass facts |
| Tooling | local/op origins, HIR provenance, synthetic kinds, debug bindings |
Fields have phase-specific authority. An unset storage classification is acceptable immediately after build but not after layout inference. An empty continuation list is required in whole-function form and invalid as the finished shape of a suspending function handed to code generation.
Two forms
The same function structure has two legal forms:
Whole
IrForm::Whole is one CFG with suspending calls still represented as
terminators. Its continuation list is empty and its final frame is unset.
Whole form lets liveness, ownership, inlining, scalar replacement, folding,
tail-call work, and other optimizations reason across future suspension
boundaries.
Continuations
The split transition produces IrForm::Continuations. Continuations are
populated, cross-suspension state has a finalized frame home, and code
generation can consume each runtime entry shape.
ContinuationKind distinguishes:
Entry, invoked at function entry;Resume, invoked with a runtime-delivered completion;LoopStep, re-enqueued for cooperative loop progress.
Reach is either Confined, allowing compatible siblings to share
switch-on-state dispatch, or Reified, requiring a separately addressable
WebAssembly function. The safe default is reified until analysis proves
confinement.
The split is a one-way form transition. A pass declares which form it accepts; it must not infer readiness from a few populated fields.
Roles and ABI
Function role and calling ABI answer different questions.
FnRole describes completion behavior:
- an entry signals unit completion;
- a helper returns to its caller or schedules a resume;
- a spawn task records its result and signals task completion.
IrFnAbi describes invocation:
Directuses natural value parameters and results and cannot suspend;Suspendinguses an arena-resident frame and runtime continuation ABI.
The default is Suspending, because choosing a frame when uncertain costs
performance while incorrectly choosing direct ABI breaks behavior. Early
FnAbiFacts record whether direct form is possible and why it was rejected;
later ABI layouts attach concrete carriers and locations.
Operation families
Operations are straight-line computations inside a block. The vocabulary includes:
- constants, moves, arithmetic, comparisons, conversions, and symbols;
- direct, frame, closure, host, and intra-unit call forms;
- field, tuple, list, slice, array, and raw memory operations;
- flex allocation and frame-relative addressing;
- closure, cell, and spawn construction;
- clone, retain, drop, shallow drop, in-place drop, and reuse;
- selected runtime primitives for scheduling, I/O, cancellation, and completion.
Earlier forms can use rich operations such as a struct literal or unselected closure call. Canonicalization expands or selects them before the backend boundary. The backend validator rejects any policy-bearing operation that leaks through.
Read Control for CFG and suspension, Memory for values and ownership, and Validation for phase gates.
Boundary
MIR may still refer to Atoll TypeRefs for diagnostics, layout, ownership,
and ABI attachment. It must not contain unresolved generics. It also does not
encode final WebAssembly stack order or structured branch syntax; WasmIR and
its control-flow lowering own those details.
See MIR Pipeline for pass scheduling and WasmIR for the consumer contract.