Skip to content
PT

Static copy

Copied from docs/en/decisions/adp-013.md in https://github.com/poppy-team/aipo-lang (MIT). Pinned to revision ce47c4e070404fc41722ccd8e2b7b808b99062a8, blob a2ccd3faf7338b7271c5fd62df6771ae5763c916. The source repository remains canonical; this copy is refreshed through a sync pull request, not live.

ADP-013 — WebAssembly Execution Substrate Migration and Self-Hosting Roadmap ​

  • Status: Approved
  • Date: 2026-09-26
  • Deciders: Raillen & Poppy Team
  • Phase: Architectural Evolution / v0.11.0 (Wasm Core & Self-Hosting Foundation)

Context and Technical Diagnosis ​

During the development of the v0.1.0 release of the Aipo programming language, deep bytecode interpreter optimizations were implemented and empirically measured (P1 Value layout compaction, P2 zero-alloc struct method dispatch, P4 superinstructions GetLocal0..7 & Call0..4, and E1 typed structured failures).

Despite significant gains measured in paired benchmarks (up to -13.94% CPU reduction), hardware microarchitectural analysis proved the existence of a physical dispatch floor of ~100ns per opcode in the stack-based interpreter (Stack VM):

  1. Branch Target Buffer (BTB) Pollution: The centralized dispatch loop (match opcode) in safe Rust causes a branch misprediction rate exceeding 60%, costing 15 to 20 clock cycles of pure pipeline flush penalty per executed instruction.
  2. Stack Instruction Multiplication: Stack machines require 3x to 4x more bytecode instructions to perform the same logical computation as register machines or compiled code.
  3. Barrier to Self-Hosting: Enabling Aipo to implement its own compiler (self-hosting) while depending on massive C/Rust libraries (such as LLVM or native Cranelift) would require fragile, heavyweight FFI bindings, creating unwanted ecosystem coupling.

Architectural Decisions ​

1. Freezing the v0.1.0 Edition (Stack VM) ​

  • The current stack virtual machine implementation (aipo-vm), along with the C ABI (aipo-c-abi), test runner (aipo test), and all 506+ green tests, is formally frozen on branch legacy/v0.1.0-stack-vm and tagged as v0.1.0-stack-vm-final.
  • This branch preserves the complete, functional historical reference of the first version of the language.

2. Adopting WebAssembly (Wasm 2.0 + WASI) as the Execution Substrate ​

  • Aipo adopts WebAssembly as its standard binary target and execution substrate.
  • Compiled code becomes a standard .wasm module, executed with near-native performance via Wasmtime's JIT (powered by Cranelift) on desktop/server, and executed natively in browsers and JavaScript engines (Node.js, Deno, Bun, Cloudflare Workers).

3. Preserving the Frontend in its Entirety (100% Reused) ​

  • Frontend layers remain intact and unmodified:
    • aipo-source (source mapping, spans, and locations).
    • aipo-diagnostics (error codes, severity, and reporting).
    • aipo-lexer and aipo-syntax (tokens, parser, and abstract syntax tree).
    • aipo-hir and aipo-sema (type checking, scopes, interface contracts, and semantics).

4. Middle-End Restructuring (aipo-ir) ​

  • aipo-ir is adapted to produce Structured Control Flow (block, loop, if ... else, br, br_if, br_table), eliminating arbitrary jumps in favor of a representation matching WebAssembly's formal model.

5. Creation of the aipo-wasm Backend ​

  • aipo-bytecode (proprietary .aibc format) is succeeded by the aipo-wasm crate.
  • aipo-wasm directly generates standard .wasm binary files using the pure Rust, high-performance wasm-encoder crate.

6. Natural Alignment Between aipo-host and WASI ​

  • Aipo's capability-based security model (CapabilitySet, deny-by-default) maps cleanly to the capability model of WASI (WebAssembly System Interface) and the Wasm Component Model, ensuring strict isolation and execution security.

7. Strategic Three-Phase Self-Hosting Roadmap ​

  1. Phase 1 (Wasm Foundation): Rust compiler generates functional .wasm modules executed via Wasmtime integrated into the CLI.
  2. Phase 2 (Frontend in Aipo): Parser, semantic analyzer, and Wasm emitter rewritten in Aipo itself (aipo-in-aipo), leveraging native data types (Bytes, List, Dict, Struct).
  3. Phase 3 (Closed Bootstrapping): The Rust Aipo compiler compiles the Aipo compiler written in Aipo, producing aipo-compiler.wasm. From this point forward, the compiler is fully self-hosted and verified via bit-for-bit identity checks.

Consequences and Trade-offs ​

Positive ​

  • 30x to 50x Performance Leap: JIT execution via Cranelift brings Aipo's speed close to compiled languages such as Go and C.
  • Universal Portability Without Transpilation: The exact same .wasm binary runs identically in the terminal, on the web, in serverless environments, and in native engines (such as Poppy).
  • Trivial Self-Hosting: Wasm is a pure binary byte specification; emitting .wasm binaries from Aipo requires zero C-ABI bridges or low-level library dependencies.
  • Elimination of Duplicate Code: aipo-js transitions from a complex source transpiler into a native Wasm module loader.

Technical Challenges to Manage ​

  • Structured Control Flow: Requires a structured loop/condition relayout algorithm in aipo-ir (Relooper/Stackifier).
  • Dynamic Memory Management: Linear memory allocation strategy with lightweight embedded allocator and future Wasm GC support.
  • Concurrency & Async: Compiled state machine implementation for cooperative asynchronous tasks.