eskiuv0.12.0
Compiler internals · Self-hosting

Self-Hosting

Eskiu has two implementations of its compiler. The released eskiuc is written in C++17 and links LLVM. The second, under selfhost/, is written in Eskiu: it covers the same pipeline and command line, writes LLVM IR as text, and calls clang to assemble and link it. CMake builds it as eskiuc-esk. See selfhost/README.md for its layout.

preprocessor → lexer → parser → sema → async lowering → codegen (LLVM IR text) → clang

The C++ compiler is the reference. Every change to the language lands in both compilers in the same commit, and CI checks that they agree.

How agreement is checked

The ground truth differs by pass, so the check does too:

Pass Check
Preprocessor, lexer, parser Byte-exact comparison with eskiuc --test-lexer and --test-parser
Type checker Same accept or reject verdict as --test-typechecker, with the same message and line:col
Code generator Behavioral: build the program with each compiler, run both, compare exit code and output. LLVM renumbers values and folds constants, so the IR itself is not compared
C ABI The C signatures each compiler lowers for extern structs and callbacks, per target

The scripts are in tests/selfhost/ and all run in CI. The code-generator check covers every runnable program in tests/. The fuzzers in tests/fuzz/ also run generated programs through both compilers.

The bootstrap fixpoint

The self-hosted compiler is also checked against itself. cg_bootstrap.sh builds it in three stages: the C++ eskiuc builds cc0, cc0 builds cc1, and cc1 builds cc2. The check passes when cc1 and cc2 produce identical IR for the compiler's own source. The binaries themselves are not compared, since a Mach-O file embeds a UUID and signature that change between identical builds.

A fixpoint only exercises the parts of the language the compiler's own source uses. It does not show that the rest works, which is why the behavioral check runs over the whole test corpus as well.

Running the checks

tests/selfhost/lex_parity.sh   --full   # lexer
tests/selfhost/pp_parity.sh    --full   # preprocessor
tests/selfhost/parse_parity.sh --full   # parser
tests/selfhost/tc_parity.sh             # type checker, valid and invalid programs
tests/selfhost/cg_parity.sh             # code generator
tests/selfhost/corpus_parity.sh         # every runnable test through eskiuc-esk
tests/selfhost/driver_parity.sh         # building with -o
tests/selfhost/run_parity.sh            # eskiuc-esk run
tests/selfhost/fmt_parity.sh            # eskiuc-esk fmt
tests/selfhost/cabi_parity.sh           # C ABI lowering per target
tests/selfhost/cg_bootstrap.sh          # three-stage fixpoint

They take the C++ compiler from ESKIUC (default build/eskiuc) and clang from CLANG.

Execution backend and distribution model (Roadmap to 1.0)

eskiuc-esk serves as a full self-hosting validation engine and bootstrap compiler: