Compiler Architecture

cppbolt is organized as a single Cargo package that provides a core compiler library (cppbolt), a native CLI (cppbolt-cli), a corpus test runner (cppbolt-testrunner), and a code metrics scanner (cppbolt-census).

The core library is entirely OS-agnostic and dependency-free: it performs no direct filesystem I/O, spawns no child processes, and requires no multi-threading runtime. Host environments supply include files through the IncludeProvider trait.

The release WebAssembly compiler module built for wasm32-unknown-unknown is currently 842,723 bytes raw and 244,401 bytes with gzip -9 -n.


1. High-Level Pipeline

The compiler follows a direct, five-stage pipeline:

 +-----------------------------------------------------------------+
 | C++ Source Text (&str, filename)                                |
 +-----------------------------------------------------------------+
                                  │
                                  ▼
 +-----------------------------------------------------------------+
 | 1. Preprocessor (src/preprocessor/)                             |
 |    - Macro expansion (hide sets, ##, #) & rescan                |
 |    - Conditional evaluation (#if, #elif, #ifdef)                |
 |    - IncludeProvider resolution & cycle detection               |
 |    - Origin line mapping for header diagnostics                 |
 +-----------------------------------------------------------------+
                                  │
                                  ▼ PreprocessedSource
 +-----------------------------------------------------------------+
 | 2. Lexer (src/lexer/)                                           |
 |    - Tokenization into TokenKind variants                       |
 |    - Exact source span tracking (Span: FileId, line, col, len)  |
 +-----------------------------------------------------------------+
                                  │
                                  ▼ Vec<Token>
 +-----------------------------------------------------------------+
 | 3. Parser & AST (src/parser/, src/ast/)                         |
 |    - Feature pre-scan (src/parser/unsupported.rs)               |
 |    - Recursive descent + Pratt expression parser                |
 |    - Nesting depth budgeting (src/depth.rs)                     |
 +-----------------------------------------------------------------+
                                  │
                                  ▼ ast::Program
 +-----------------------------------------------------------------+
 | 4. Semantic Analysis (src/sema/)                                |
 |    - Scopes, symbol registration, using/typedef aliases         |
 |    - Inheritance & vtable slot calculation                      |
 |    - Record layout computation (alignment & padding)            |
 |    - Overload resolution ranking & type checking                |
 |    - C++17 copy elision tagging                                 |
 +-----------------------------------------------------------------+
                                  │
                                  ▼ ast::Program + sema::Sema
 +-----------------------------------------------------------------+
 | 5. WASM Code Generation (src/codegen/, src/wasm/)               |
 |    - Direct AST-to-Wasm instruction lowering (NO IR)            |
 |    - Function context, local frame allocation                   |
 |    - Fixed-width LEB128 frame-size patching                     |
 |    - RAII deterministic scope cleanup emission                  |
 |    - Binary section encoding (src/wasm/)                        |
 +-----------------------------------------------------------------+
                                  │
                                  ▼
 +-----------------------------------------------------------------+
 | Emitted WebAssembly Binary (Vec<u8>)                            |
 +-----------------------------------------------------------------+

2. Direct AST-to-Wasm Lowering (No IR, No Optimizer)

A fundamental architectural decision in cppbolt is the complete absence of an Intermediate Representation (IR) and an optimization pass (see ADR 0002).

  • Traditional Compilers: Typically translate AST -> High-Level IR -> Low-Level IR (SSA / 3-Address Code) -> Machine Instructions, running dozens of optimization passes in between.
  • cppbolt Architecture: Lowers the annotated Abstract Syntax Tree (ast::Program) and semantic state (sema::Sema) directly into WebAssembly instruction bytes.
  • Why No IR?
    • Keeps the compiler's own compiled WebAssembly payload extremely small (~244 KB gzipped).
    • Maximizes compilation throughput in browser Web Workers.
    • Eliminates the memory allocation overhead of building and tearing down intermediate CFG or SSA graphs.
  • Why No Optimizer?
    • Prioritizes compiler correctness, determinism, and transparent mapping to WebAssembly primitives.
    • Generating unoptimized code is an intentional scope boundary for v1 (documented in known-limitations.md).

3. Compiler Pipeline Stages

StagePathPurposeInput TypeOutput TypeKey Data StructuresInvariants
Preprocessorsrc/preprocessor/Macro expansion, include resolution, #if evaluation&str, &dyn IncludeProviderPreprocessedSourceMacroDef, HideSet, LineOriginInclude recursion capped at 128; macro recursion terminates via hide sets; origins accurately track header lines
Lexersrc/lexer/Tokenizes preprocessed text into lexemes&strVec<Token>Token, TokenKind, Span, FileIdEvery token carries an exact non-fabricated source span
Parser & ASTsrc/parser/, src/ast/Parses grammar into typed ASTVec<Token>ast::ProgramProgram, Decl, Stmt, Expr, TypeValidates supported features first; nesting depth bounded per construct via depth.rs
Semantic Analysissrc/sema/Scope analysis, type checking, vtables, layouts, overloads&mut ast::Programsema::SemaSema, StructDef, FunctionSig, RecordLayoutMutates AST with resolved types; rejects multiple/virtual inheritance; catches ambiguous overloads
WASM Codegensrc/codegen/, src/wasm/Lowers AST to WebAssembly binary sections&ast::Program, &sema::SemaVec<u8>Codegen<'a>, FunctionContext, WasmModuleFixed-width LEB128 frame patches; stack allocation traps on guard page entry; RAII cleanups on all exits
Runtimesrc/runtime/, stdlib/In-module allocator, printf runtime, embedded headersN/A (Emitted or included)Wasm opcodesmemory_layout, allocator, formatILP32 32-bit addresses; stack top at 0x810000; heap grows upward; slot 0 traps

4. Binary and Library Targets

The repository contains a single unified Cargo package defined in Cargo.toml:

TargetEntry FileResponsibility
cppbolt (lib)src/lib.rsCore compiler pipeline, public Rust API, and C ABI entry points (src/ffi.rs)
cppbolt-cli (bin)src/main.rsNative command-line interface with filesystem include support and 64 MiB execution thread
cppbolt-testrunner (bin)src/bin/cppbolt-testrunner.rsCorpus test runner, variant verification, native oracle execution, and golden baseline check
cppbolt-census (bin)src/bin/cppbolt-census.rsCode quality scanner enforcing function line count (<80 lines) and parameter limits (<5 params)