Compiler design / 17. Backend lowering

Lowerers translate validated HIR into target code without reopening source or rewriting language meaning.

Turning HIR into JavaScript and Wasm

One HIR operation may become a JavaScript expression in one partition and a Wasm instruction sequence in another. The meaning stays Moth. The spelling becomes target-native. Same source meaning, different host climates.

Lowerers translate validated inputs. They are not second language frontends.

Lowerer inputs

A lowerer receives explicit records:

A lowerer does not:

If a lowerer needs a fact, an earlier owner should have recorded it.

For the walkthrough, target-labelled start, greet and template work arrive ready. The JavaScript path might own page orchestration. Neutral string work may sit in either partition depending on assignment.

Diagram placeholder: Selected target sends one HIR input to two target paths

Caption: exact frontend boundary simplified. Question: what stays shared?

JavaScript lowering

The JS backend speaks host values and functions. It leans on the host GC for reachability. Runtime helpers implement language operations the surface syntax made look primitive: checked numerics, certain casts, template runtime pieces, error plumbing.

greet in JavaScript form is ordinary host code that preserves Moth contracts. A more permissive JS primitive must not silently weaken checked arithmetic, finite-Float rules or error propagation.

Wasm lowering

Accepted Wasm design prefers a structured path:

  1. optionally derive a structured HIR view (not a second semantic authority)
  2. lower into backend-owned structured LIR (a lower IR)
  3. apply ABI, handles, layouts, memory and runtime imports

Beginner picture:

Old dispatcher-loop LIR stories, moth_start bootstrap myths, i64 Int bridges as the final story and per-module memory as the default are removed final-design paths. Teach them only as historical "do not rebuild this" notes, not as the architecture.

Diagram placeholder: A derived backend view feeds structured blocks and ABI operations

Caption: accepted Wasm design, simplified records. Question: where does target structure enter?

Shared runtime and wrappers

Accepted HTML mixed-target design wants page-local shared Wasm runtime and memory rather than a scatter of isolated memories per module as the end state. Page-local shared Wasm runtime/memory applies to Moth-linked variants only. Imported WIT components use component-private memory and value conversion.

JavaScript companion facades and wrappers call Wasm exports through explicit handles and layout rules. The bridge is data, not guesswork.

Diagram placeholder: JavaScript companion calls a Wasm export through explicit handles and layout rules

Caption: teaching boundary. Question: how do targets communicate?

External bindings and ownership facts

Binding-backed calls lower through demand-driven glue. The binder's semantic interface already existed upstream. The lowerer maps stable external ids to imports, helpers or native operations.

Borrow facts may guide optional ownership-aware Wasm lowering: earlier drops, specialised paths, less GC traffic. GC backends may ignore ownership operations. They still required validation upstream. Optimisation must preserve observable behaviour and the same accepted program set.

Diagram placeholder: Ownership side facts guide Wasm operations while GC can ignore them

Caption: semantic invariant. Question: what can optimisation change?

What can fail here

User-facing target failures preferably die in validation, not mid-emission.

Why Moth does it this way

Alternative: give each backend a source interpreter or separate frontend.

Choice: one validated semantic HIR plus target-owned lowering.

Benefit: source behaviour remains shared across JavaScript and Wasm.

Cost: each backend needs a faithful ABI and runtime implementation.

Roadmap and current status

Exit state

You leave with JavaScript, Wasm, wrappers, runtime modules and asset records as data. Next: how the HTML builder assembles and owns those outputs on disk, ending at <p>Hello, Priya!</p>.

Compiler design / Previous / Next