19 — Targeting wasm

Previous: The CLI as an IDE

日本語版: 19_wasm.vibe.md

The compiler is a wasm program that emits wasm. You do not opt into wasm as a backend — it is the representation. Internal values are tagged i64. Strings are byte strings. Types that can appear on a WIT boundary follow nominal rules so the boundary does not have to invent a mapping.

Two codegen paths

tagged i64 values, a bump/RC heap, Perceus planning for ownership.

VIBE_TEST_BACKEND=gc to opt a test onto this path.

vibe test foo_test.vibe                       # linear
VIBE_TEST_BACKEND=gc vibe test foo_test.vibe  # wasm-gc
vibe build --release app.vibe                 # standalone .wasm

Linear is the default and the lane everything is tested on. The gc lane is the pure-test lane: it gates out host imports as a group, so anything touching HTTP or the filesystem is linear-only. Divergences are tracked one row per builtin in scripts/builtin_parity_classification.tsv and machine-checked at the gate — read that file rather than guessing which of the two a given name is on.

Bench caches key on the backend, so switching linear → gc recompiles.

Feature levels

Generated modules declare the wasm feature level they need (docs/wasm/feature-levels.md). Denied capabilities are folded out, so a program that never reaches Http should not demand a networking-capable runtime.

Two levels are tracked: v8 (Chrome / Node / Deno) and web-baseline (those plus Firefox and Safari). A proposal is safe for a level only when every engine in the set supports it without a flag. The compiler host (viberun) is allowed to enable experimental proposals; generated user code is not.

WIT

Types that can appear on a WIT boundary follow nominal rules (ADR-0089). @vibe/wit_runtime provides the Result that maps to WIT result<T, E> — that is the one blessed two-armed return type. Everywhere else, write T with Exception[E].

What "selfhost" means

bootstrap/seed/ is a pinned compiler wasm. lib/@vibe/compiler/ is source. scripts/generations.sh builds stage1 then stage2. A fixpoint is stage2 compiling the compiler to the same bytes as stage3. You do not need MoonBit, LLVM, or a native vibe compiler.

Next: Pitfalls.