Bootstrapping MVL¶
MVL has two compilers that live in the same repository:
| Compiler | Language | Location | Role |
|---|---|---|---|
| Bootstrap | Rust | src/ |
Stage 0 — compiles MVL from scratch |
| Self-hosted | MVL | compiler/ |
Compiles itself once the bootstrap is ready |
This page walks through building both, from a fresh machine to a working self-hosted binary.
Prerequisites¶
Rust¶
The bootstrap compiler is written in Rust. Install the stable toolchain via rustup:
Verify:
Optional: Z3 for Layer 5 proofs
The refinement solver's Layer 5 uses Z3 for the deepest proofs. It is a Cargo feature — the build works without it.
macOS:
Linux (Debian/Ubuntu): Without Z3, Layers 1–4 still run (trivial, interval, symbolic, Cooper arithmetic). Only the SMT fallback is disabled.Stage 0 — Build the Bootstrap Compiler¶
Clone the repository and build with Cargo:
The binary lands at target/release/mvl. Add it to your PATH:
Or use the Makefile shorthand:
Debug vs release
cargo build (debug) is faster to compile and includes extra assertions. cargo build --release optimises the binary — use this for everyday mvl usage.
Stage 1 — Verify the Self-Hosted Compiler¶
The self-hosted compiler lives in compiler/. Use the Stage 0 binary to check it:
Expected output (scores reflect current proof coverage — not yet 11/11 everywhere):
compiler/backends/llvm/emit_context.mvl: OK (9/11 requirements proven)
compiler/backends/llvm/emit_exprs.mvl: OK (9/11 requirements proven)
compiler/backends/llvm/emit_helpers.mvl: OK (9/11 requirements proven)
compiler/backends/llvm/emit_match.mvl: OK (9/11 requirements proven)
compiler/backends/llvm/emit_program.mvl: OK (9/11 requirements proven)
compiler/backends/llvm/emit_stmts.mvl: OK (9/11 requirements proven)
compiler/backends/llvm/emit_types.mvl: OK (9/11 requirements proven)
compiler/backends/llvm/emitter.mvl: OK (9/11 requirements proven)
compiler/context.mvl: OK (9/11 requirements proven)
compiler/effects.mvl: OK (9/11 requirements proven)
compiler/lexer.mvl: OK (9/11 requirements proven)
compiler/main.mvl: OK (10/11 requirements proven)
compiler/mono.mvl: OK (9/11 requirements proven)
compiler/parser.mvl: OK (9/11 requirements proven)
compiler/resolver.mvl: OK (9/11 requirements proven)
compiler/tir.mvl: OK (8/11 requirements proven)
compiler/tir_lower.mvl: OK (9/11 requirements proven)
compiler/verify_errors.mvl: OK (8/11 requirements proven)
compiler/verify_passes.mvl: OK (9/11 requirements proven)
compiler/verify_types.mvl: OK (9/11 requirements proven)
To see the full assurance report:
To run the MVL-in-MVL test suite:
To run the self-hosted lex+parse pipeline over the full corpus (bootstrap smoke test):
This feeds every tests/corpus/ file through compiler/main.mvl and fails if any produce parse errors.
Stage 2 — Build the Self-Hosted Compiler¶
Not yet available
mvl build compiler/main.mvl currently fails with Rust compilation errors in the
MVL compiler's own source (src/tir.rs), unrelated to the self-hosted code.
The LLVM emitter itself (compiler/backends/llvm/) is fully implemented and usable
today via the TIR pipeline:
Full mvl build support for the self-hosted frontend is tracked in the phase table below.
Bootstrap Phases¶
The full self-hosting plan is split into six phases (ADR-0044):
graph TD
A["Phase 1 ✅<br/>Shared types<br/>compiler/tir.mvl"] --> B
A --> C
B["Phase 2 🔄<br/>Leaf stages<br/>Resolver · Mono · TIR Lower"]
C["Phase A ✅<br/>Backends<br/>MVL-hosted LLVM emitter"]
B --> D
C --> D
D["Phase 3 ✅<br/>Parser<br/>Lexer + recursive descent"]
D --> E["Phase 4 🔄<br/>Checker<br/>Type checker + 11 passes"]
E --> F["Phase 6<br/>Bootstrap<br/>3-stage self-verify"]
Current status¶
| Phase | Scope | Status |
|---|---|---|
| 1 | Shared types (compiler/tir.mvl) |
✅ Done |
| 3 | Parser — Lexer + recursive descent | ✅ Done |
| A | MVL-hosted LLVM emitter (compiler/backends/llvm/) — hello world e2e |
✅ Done |
| 2 | Leaf stages — Resolver, Mono, TIR Lower | 🔄 In progress |
| 4 | Checker — type checker + 11 requirement passes (solver in progress) | 🔄 In progress |
| 6 | Three-stage bootstrap verify | ⬜ Planned |
Three-stage verification (Phase 6)¶
When Phase 6 completes, the build will perform a full trusting trust check:
Stage 0: Rust bootstrap → mvl₀ (trusted base)
Stage 1: mvl₀ compiles compiler/ → mvl₁
Stage 2: mvl₁ compiles compiler/ → mvl₂
assert mvl₁ == mvl₂ # byte-identical output ← bootstrap proven
A divergence between Stage 1 and Stage 2 would indicate a bug in the self-hosted compiler that the bootstrap masked. Byte identity gives confidence that the two compilers are semantically equivalent.
Quick Reference¶
# One-time setup
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
git clone https://github.com/mvl-lang/mvl.git && cd mvl
# Stage 0: build the bootstrap compiler
cargo build --release
export PATH="$PWD/target/release:$PATH"
# Stage 1: verify the self-hosted source
mvl check compiler/
mvl assurance compiler/ --verbose
make test-mvl
make test-bootstrap # lex+parse corpus through the self-hosted frontend
See Also¶
- Install MVL — pre-built binaries and quick install
- Build Assurance — what the assurance report contains
- The 11 Requirements — what the compiler proves about itself