Skip to content

Compiler

Architecture, invariants, and engineering guide for the Atoll compiler.

Updated View as Markdown

The Atoll compiler is a staged, diagnostic-first pipeline from source files to per-unit WebAssembly and linked deployment modules. Each stage owns one representation, establishes explicit invariants, and hands a narrower program to the next stage.

This section explains those ownership and handoff contracts. The Language Guide teaches source syntax, the Specification defines language rules, and the IR section is the normative home for HIR, MIR, and WasmIR formats.

Chapter map

Chapter Focus
Pipeline End-to-end stage order, gates, and artifacts
Syntax Lexer, arena AST, recovery, and incremental parsing
Analysis Resolution, types, effects, HIR, and project assembly
Database Salsa inputs, queries, invalidation, and current granularity
Specialization Generic call discovery, canonical keys, and concrete HIR
MIR Pipeline CFG construction, facts, pass scheduling, RC, and validation
WebAssembly Unit discovery, WasmIR, module emission, and ABI selection
Linking Module merging, remapping, metadata, and link groups
Provenance Source identity through IR rewrites, line data, traces, and debugging
Diagnostics Source attribution, layers, recovery, and hard gates
Reproducibility Stable ordering and byte-identical output
Testing Unit, snapshot, parity, determinism, and end-to-end gates

Crate ownership

Crate Owns Must not own
atoll-syntax Tokens, source ranges, interned strings, AST arenas Types or runtime meaning
atoll-sema Symbols, types, effects, layouts, checked HIR WebAssembly encoding
atoll-mono Concrete generic function instances and instantiated layouts Source parsing
atoll-mir Control flow, suspension, frames, ownership operations, optimization Surface syntax
atoll-codegen-wasm WasmIR, unit modules, custom sections, program linking Language-level inference
atoll-db Incremental inputs and memoized composition of compiler stages A second semantic model
atoll-cli Project discovery, user options, stage orchestration, artifact writing Hidden compiler policy

The crates form a dependency direction, not a collection of interchangeable passes. A lower stage may preserve source provenance from an earlier one, but it should not reconstruct semantic decisions that the earlier stage failed to encode.

Design rules

Four rules apply across the compiler:

  1. Reject at the owning layer. Unknown names belong to analysis; invalid suspension lifetimes belong to MIR validation; malformed WasmIR belongs to its verifier.
  2. Never silently lower an unsupported case. A source diagnostic is preferable to a placeholder zero, skipped instruction, panic, or malformed module.
  3. Keep order observable and deterministic. Parallel and incremental work may execute in any order, but IDs, diagnostics, units, sections, and bytes are reduced in canonical order.
  4. Make options explicit. Optimization, debug information, tracing, and diagnostic visibility travel through configuration objects. Environment variables remain development and compatibility controls, not the desired library API.

Every transforming pass also follows a fifth operational rule: preserve or classify provenance. A generated operation either retains the user construct that caused it or carries an explicit synthetic reason; absence is not silently treated as a source range.

Maturity

The compilation path is implemented, but several internal boundaries are actively evolving. In particular, incrementality is finer-grained in parsing, semantic checks, and unit emission than in some whole-project monomorphization and cross-function MIR work. The chapters describe those mixed boundaries explicitly rather than presenting the query graph as uniformly per-function.

For the runtime contract consumed by emitted modules, continue to Architecture and ABI.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close