commit 49b6fb2e582e31592612da787fc1af47163ab9cf
parent 299fe4b9b5bba064049f2eeda3f39573d5a7d45b
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Fri, 17 Jul 2026 15:10:27 -0700
docs: restructure and ship project documentation
Diffstat:
30 files changed, 983 insertions(+), 282 deletions(-)
diff --git a/README.md b/README.md
@@ -1,134 +1,205 @@
-# kit - a compilation multi-tool
-
-Kit Is a Toolchain.
-
-Kit is a compilation multi-tool written in C11, featuring a C11 compiler along
-with many other tools one may need to compile, link, run, and distribute code.
-
-Its inspirations are TCC, MIR, and LLVM.
-
-It features:
-- A C11 preprocessor
-- A single-pass C11 parser and code generator
-- A JIT compiler, linker, and in-process executor
-- An IR interpreter (`run --no-jit`)
-- A lightweight optimizer (`-O1`) with SSA construction, register allocation, and
- local cleanup
-- `-O2` accepted as a v1 compatibility spelling for `-O1` (not a distinct
- optimization level yet)
-- Cross-compiling backends for aarch64, x86-64, and riscv64, plus WebAssembly and
- a portable C-source backend
-- Support for object files and executables (PE/COFF, ELF, Mach-O)
-- Primary tested targets: x86_64-linux, aarch64-linux, x86_64-macos,
- aarch64-macos, x86_64-windows, aarch64-windows, riscv64-linux, plus freestanding
- variants of the same architectures.
-- An assembler, standalone and inline, with basic linker-script support
-- A disassembler and object/image inspection
-- Object and binary utilities: ar, ranlib, nm, size, strip, objcopy, objdump,
- addr2line, strings
-- Standalone gzip and LZ4-frame compression (`compress`), interoperable with
- stock `gzip`/`lz4`
-- Content hashing (`hash`: SHA-256, BLAKE2b-256, CRC-32)
-- A parser/lexer generator (`gram`): EBNF in, C parser / lexer / token-machine
- tables out, with allocation-free push runtimes for the generated code
-- Drop-in standard names for the above: `sha256sum`, `b2sum`, `crc32`, `gzip`,
- `gunzip`, `lz4`, `lz4c`
-- A single multi-call binary, with an `install` command that drops per-tool
- symlinks (hard links on Windows) into a directory for drop-in toolchain use
-- Debug info generation and consumption (DWARF)
-- An interactive JIT debugger on Darwin/Linux aarch64 hosts
-- Header dependency generation
-- Reproducible builds
-- Signed, content-addressed code distribution (`.kpkg`)
-- Bootstrap from hex0-seed
-- A C library providing access to all of the above
-
-kit also provides these headers beyond the freestanding set:
-- stdatomic.h
-- assert.h
-- setjmp.h
-
-And kit-specific extensions:
-- kit/syscall.h
-- kit/baremetal.h
-- kit/coro.h
+# kit
-## Documentation
+Kit is a BusyBox for compilation: one multi-call executable and one C library
+covering the compiler, linker, binary utilities, execution runtimes, package
+distribution, and builds.
-The release distribution is self-documenting through:
+A conventional toolchain is assembled from several layers. `cc` coordinates
+preprocessing, compilation, assembly, and linking; binutils handles archives and
+object inspection; JIT and WebAssembly runtimes are separate again; build and
+package systems sit above and after them. Kit gives those layers a shared target
+registry, object model, linker, content store, and public API.
-- `bin/kit --help` for the tool inventory and general conventions;
-- `bin/kit COMMAND --help` (or `bin/kit help COMMAND`) for each command;
-- this `README.txt`; and
-- the public API comments under `include/kit/`.
+Kit is implemented in freestanding C11. It does not require a C++ compiler to
+bootstrap, has no mutable global state, and makes host services explicit through
+context structs and vtables. The `kit` executable is the reference host for
+`libkit.a`, not a separate implementation wrapped around it.
-The 2026.6.0 release currently requires explicit resource paths when used from
-an extracted distribution. The examples below state those paths instead of
-depending on a source-tree working directory. Keep every path quoted if the
-distribution may be installed below a directory whose name contains spaces.
+For a longer introduction, including representative compile-speed and code-size
+comparisons, see [Introducing kit](doc/INTRODUCING_KIT.md).
-### C developer quick start
+## Quick start
-On macOS, run this from the extracted distribution directory. Kit discovers
-the native SDK with `-print-sysroot`, but this release requires feeding that
-path back with `-isysroot`. The explicit `--support-dir` is likewise required
-when the current working directory is outside the Kit source tree.
+From a source checkout:
```sh
-ROOT="$PWD"
-K="$ROOT/bin/kit"
-SDK="$("$K" cc -print-sysroot)"
+make bin
+K=build/kit
+```
-printf 'int answer(void) { return 42; }\n' > answer.c
-printf 'int answer(void); int main(void) { return answer() != 42; }\n' > main.c
+From an extracted release:
-"$K" cc --support-dir "$ROOT/support" -isysroot "$SDK" -g -c answer.c -o answer.o
-"$K" ar rcs libanswer.a answer.o
-"$K" ranlib libanswer.a
-"$K" cc --support-dir "$ROOT/support" -isysroot "$SDK" main.c libanswer.a -o hello
-./hello
-"$K" nm libanswer.a
+```sh
+K=bin/kit
+```
+
+Compile, inspect, and run a native program:
+
+```sh
+printf 'int main(void) { return 0; }\n' > hello.c
+"$K" cc hello.c -o hello
"$K" objdump -h -t hello
+./hello
+
+"$K" run hello.c
+"$K" run --no-jit hello.c
+```
+
+Native distributions discover their sibling support tree automatically. Native
+macOS builds also discover and apply the SDK. An explicit `--support-dir`,
+`--sysroot`, or `-isysroot` remains an authoritative override.
+
+Inspect the compiled target profiles before cross-compiling:
+
+```sh
+"$K" targets
+"$K" targets aarch64-linux-gnu
+"$K" cc -target aarch64-linux-gnu --sysroot /path/to/sysroot \
+ -c hello.c -o hello.aarch64.o
+```
+
+Hosted cross targets currently require an appropriate SDK or sysroot.
+Freestanding targets use kit's shipped runtime sources and caller-supplied
+startup/linker policy. Signed `.kpkg` SDK distribution is planned; see
+[the sysroot plan](doc/plan/SYSROOTS.md).
+
+Install the multi-call binary under conventional tool names:
+
+```sh
+mkdir -p "$HOME/.local/bin"
+"$K" install "$HOME/.local/bin"
+```
+
+Kit creates symlinks on POSIX and hard links on Windows. `kit cc ...` and an
+installed `cc ...` invoke the same command implementation.
+
+## What is included
+
+| Surface | Commands and APIs |
+|---|---|
+| Compilation | C11 preprocessor/compiler, assembly, `cc`, `check`, `cpp`, `as`, `ld`, `build-exe`, `build-lib`, `build-obj` |
+| Binary tools | `ar`, `ranlib`, `nm`, `size`, `strip`, `objcopy`, `objdump`, `addr2line`, `symbolize`, `strings`, `disas`, `mc`, `image`, `cpio` |
+| Execution | Native JIT with `run`, IR interpreter with `run --no-jit`, interactive `dbg`, Wasm/WAT execution with explicit host-resource policy |
+| Targets | AArch64, x86-64, RISC-V, Arm freestanding, and wasm32 across ELF, Mach-O, COFF/PE, and Wasm profiles |
+| Distribution | Content-addressed `cas`, signed `.kpkg`/portable packages with `pkg`, managed release installation and rollback with `update` |
+| Builds | Content-addressed `build` targets, tests, configuration profiles, declared recipe inputs, dependency traces, external repositories, and output trees |
+| Data tools | SHA-256, BLAKE2b-256, CRC-32, gzip, LZ4 frame, `xxd`, and `cmp`, including conventional command aliases |
+| Generation | `gram` EBNF-to-C parser/lexer generation with allocation-free push runtimes |
+| Library | Public C APIs for compilation, code generation, objects, linking, JIT, debugging, DWARF, archives, hashing, compression, CAS, packages, builds, and targets |
+
+Run `kit --help` for the compiled tool inventory and `kit help COMMAND` for the
+authoritative command-line reference.
+
+## Packages and trust
+
+Kit separates content identity from trust. Blobs and canonical directory trees
+are addressed by BLAKE2b-256 and can come from an untrusted store. A canonical
+package manifest names output trees and artifact roles; a Minisign-compatible
+Ed25519 signature authorizes that claim.
+
+```sh
+kit pkg keygen -o release-key
+kit pkg create --name app --version 1 -s release-key.key \
+ --root out -o app.kpkg
+kit pkg verify -p release-key.pub app.kpkg
+kit pkg unpack --verify -p release-key.pub app.kpkg -C installed
+```
+
+The native `.kpkg` representation may be fat, metadata-rich, or thin. A
+portable `.tar.gz` representation carries the same signed logical package. Kit
+uses this machinery for its own releases and authenticates both the release
+channel and selected package before `kit update` changes the active toolchain.
+
+See [Code distribution](doc/DISTRIBUTE.md) and
+[Releasing and updating kit](doc/RELEASE.md).
+
+## Build system
+
+`kit build` is a build system, not an alias for `cc`. A package-local
+`BUILD.kit` maps target labels to recipe executables. Recipes receive a clean
+environment, write an output directory, and declare configuration, source,
+glob, fetch, and target dependencies through the recipe protocol.
+
+```text
+kit-build 1
+[target app]
+recipe recipes/app.sh
+```
+
+```sh
+kit build //:app
```
-For hosted cross-compilation, replace `-isysroot "$SDK"` with the target's
-canonical `-target TRIPLE --sysroot /path/to/sysroot` pair. For freestanding
-work, use a freestanding triple, provide startup code and a linker script, and
-select the entry with `-T SCRIPT -e SYMBOL`. The complete current target list
-and its required sysroots are not yet exposed by the release binary.
-
-### Language developer quick start
-
-The public library does not provide a hosted context adapter. An embedder owns
-and initializes a `KitHeap`, `KitDiagSink`, and optional `KitFileIO`, then keeps
-them alive through this lifecycle:
-
-1. Initialize `KitContext` with those host callbacks.
-2. Parse a triple with `kit_target_from_triple`, then call `kit_target_new`.
-3. Create a `KitCompiler` with `kit_compiler_new` or `kit_compiler_new_ex`.
-4. Compile source with `KitCompileSession`, or emit a language directly through
- `KitCg` into a `KitObjBuilder`.
-5. Emit the relocatable object, or add it to a `KitLinkSession`, resolve, and
- emit the linked image through a caller-owned `KitWriter`.
-6. Commit a staged compile only after publishing its output; otherwise abort
- it. Free sessions/writers/builders before the compiler, then free the target.
-
-`include/kit/compile.h` contains a concrete source-session/link lifecycle;
-`include/kit/cg.h`, `include/kit/object.h`, and `include/kit/link.h` document the
-lower-level language-frontend path and ownership rules. A hosted out-of-tree
-program using the static library is built with only the distributed toolkit as
-follows on macOS:
+Outputs are canonical content-addressed trees. Deep traces handle unchanged
+transitive inputs; shallow traces can reuse a parent when a changed dependency
+rebuilds to the same output. The current contract relies on recipes declaring
+all cache-visible inputs; filesystem hermeticity enforcement and build-store
+garbage collection remain future work.
+
+See [Content-addressed build coordinator](doc/BUILD_COORDINATOR.md).
+
+## Optimization and scope
+
+`-O0` emits through the direct native backend. `-O1` records IR and runs the
+fast, non-SSA optimization and register-allocation pipeline. `-O2` is currently
+accepted as an alias for `-O1`; the distinct SSA mid-end is maintained but not
+yet enabled as a public optimization level.
+
+Kit is not intended to hide its current boundaries:
+
+- Hosted cross-compilation needs target system files; `kit targets` reports the
+ provisioning model separately from compiler capability.
+- Shared-library creation is currently an ELF feature.
+- Wasm supports same-invocation source builds and partial WASI, not general
+ separate-object/archive linking or complete WASI.
+- Debugger and execution support depends on the host/profile reported by the
+ target registry.
+
+## Embedding and bootstrapping
+
+An embedder owns the host callbacks and the lifetime of its `KitContext`, target,
+compiler, compile/object/link sessions, and writers. The public headers are the
+API contract; the driver and most frontends are built against the same boundary
+without access to internal headers.
+
+See [Embedding libkit](doc/EMBEDDING.md),
+[Design](doc/DESIGN.md), and [Interfaces](doc/INTERFACES.md).
+
+Kit's normal self-host check starts from a host C compiler, builds kit, and then
+uses kit for two more stages. Stage 2 and stage 3 must be byte-identical. Because
+the implementation is C, replacing the initial compiler with a smaller seed
+does not require first constructing a C++ toolchain; a minimal/diverse seed is a
+separate trust project, not a claim of the current build.
+
+See [Build and configuration](doc/BUILD.md).
+
+## Documentation
+
+Start with the [documentation map](doc/README.md). Common routes are:
+
+| Task | Documentation |
+|---|---|
+| Learn the architecture | [DESIGN.md](doc/DESIGN.md) |
+| Use and extend the CLI | [DRIVER.md](doc/DRIVER.md) |
+| Inspect targets and portability lanes | [PORT.md](doc/PORT.md) |
+| Embed the library | [EMBEDDING.md](doc/EMBEDDING.md), [INTERFACES.md](doc/INTERFACES.md) |
+| Package and authenticate artifacts | [DISTRIBUTE.md](doc/DISTRIBUTE.md) |
+| Define builds | [BUILD_COORDINATOR.md](doc/BUILD_COORDINATOR.md) |
+| Work on kit itself | [BUILD.md](doc/BUILD.md), [TESTING.md](doc/TESTING.md) |
+| Measure performance and size | [BENCHMARKING.md](doc/BENCHMARKING.md), [CODE_SIZE.md](doc/CODE_SIZE.md) |
+
+Durable `doc/*.md` files describe implemented behavior. Forward-looking work is
+under [doc/plan](doc/plan/README.md); speculative designs are under
+[doc/ideas](doc/ideas/README.md).
+
+## Building and testing
```sh
-ROOT="/path/to/extracted/kit" # replace with the extraction directory
-K="$ROOT/bin/kit"
-SDK="$("$K" cc -print-sysroot)"
-"$K" cc --support-dir "$ROOT/support" -isysroot "$SDK" \
- -I "$ROOT/include" embed.c "$ROOT/lib/libkit.a" -o embed
-./embed
+make lib # libkit.a
+make bin # kit
+make rt # libkit_rt.a
```
-No extra user-specified library is required when the native sysroot is
-explicit. The embedder's heap callbacks must honor the requested alignment;
-diagnostics are reported through the supplied sink, whose `errors` and
-`warnings` counters are maintained by libkit.
+Prefer the targeted suites listed in [TESTING.md](doc/TESTING.md). Portability
+and self-host testing are separately provisioned and documented in
+[PORT.md](doc/PORT.md).
diff --git a/doc/ARCH.md b/doc/ARCH.md
@@ -7,7 +7,7 @@ while keeping the ISA-specific seams thin. It also covers the ABI / calling
convention layer in `src/abi`, which is the single authority for storage layout
and call classification. The semantic codegen surface a backend sits behind is
in [CODEGEN.md](CODEGEN.md); the IR the optimizer feeds it is in [IR.md](IR.md);
-the SSA/regalloc machinery driving the optimizing path is in [OPT.md](OPT.md);
+the no-SSA O1 and future SSA O2 optimizer paths are in [OPT.md](OPT.md);
the standalone assembler that shares the ISA tables is in [ASM.md](ASM.md). ABI
content is canonical here.
@@ -117,8 +117,11 @@ It is driven from two directions:
```
-O0 path: CG semantic ops ──► NativeDirectTarget ──┐
(src/cg/native_*) ├──► NativeTarget ──► MCEmitter ──► ObjBuilder
- -O1+ path: CG ──► record IR ──► opt passes ──────────┘ (~35 hooks)
- (SSA, machinize, regalloc, pass_native_emit)
+ -O1 path: CG ──► record IR ──► opt passes ──────────┘ (~35 hooks)
+ (CFG/local cleanup, machinize, linear-scan regalloc,
+ pass_native_emit; no SSA)
+
+ future O2: recorded IR ──► SSA mid-end ──► O1 backend tail
```
- At **-O0**, the shared `NativeDirectTarget` (`src/cg/native_direct_target.c`)
@@ -130,11 +133,13 @@ It is driven from two directions:
semantic world. Everything else (frame slots, `class_for_type`, `addr_legal`)
the direct target calls straight through to `NativeTarget`.
-- At **-O1+**, the optimizer records IR, runs SSA/CFG passes, machinizes, and
- allocates registers (see [OPT.md](OPT.md)), then `src/opt/pass_native_emit.c`
- replays the allocated program against the *same* `NativeTarget` hooks. By this
- point every value already has a physical home, so the emit pass hands the
- target hard registers and frame slots and the target just encodes.
+- At **-O1**, the optimizer records IR, builds a CFG, runs the no-SSA local
+ schedule, machinizes, and allocates registers with the linear-scan path (see
+ [OPT.md](OPT.md)); `src/opt/pass_native_emit.c` then replays the allocated
+ program against the *same* `NativeTarget` hooks. By this point every value
+ already has a physical home, so the emit pass hands the target hard registers
+ and frame slots and the target just encodes. `-O2` currently selects this same
+ path; the maintained SSA schedule is not publicly reachable yet.
That a single ~35-hook contract serves both paths is what keeps the two code
generators byte-compatible per arch. The hook families:
diff --git a/doc/BUILD.md b/doc/BUILD.md
@@ -19,10 +19,12 @@ kit the multi-call driver binary
rt/<variant>/libkit_rt.a compiler-rt/libc support, per target variant
```
-The first two are direct make targets (`make lib`, `make bin`); the runtime is
-*not* a standalone user target. Its variants are produced as a dependency of the
-self-host path — the freshly built `kit` compiles each `libkit_rt.a` (`RT_CC =
-$(BIN) cc`) — so building the runtime always goes through a working driver binary.
+All three have direct make targets: `make lib`, `make bin`, and `make rt` for the
+native default runtime variants. `make rt-<variant>` selects one variant and
+`make rt-all-targets` requests the configured set. Runtime variants are also
+produced as dependencies of self-host and release paths. They are compiled by
+the freshly built `kit` (`RT_CC = $(BIN) cc`), so runtime construction always
+goes through a working driver binary.
Layering is enforced by include paths, not convention:
@@ -100,8 +102,10 @@ obj-format ELF MACHO COFF WASM
language ASM CPP C TOY WASM
optimizer OPT (O1+; O0 direct codegen is always present)
subsystems AR DISASM DWARF LINK JIT DBG EMU INTERP
-tools CC CHECK CPP AS LD AR RANLIB STRIP OBJCOPY OBJDUMP
- DBG RUN EMU NM SIZE ADDR2LINE STRINGS CAS PKG
+tools CC CHECK BUILD_EXE BUILD_LIB BUILD_OBJ BUILD INSTALL CPP AS LD
+ AR CPIO RANLIB STRIP OBJCOPY IMAGE OBJDUMP DBG RUN EMU NM SIZE
+ ADDR2LINE SYMBOLIZE STRINGS CAS PKG XXD CMP HASH COMPRESS DISAS
+ MC GRAM UPDATE TARGETS
```
### One source of truth: config.h
diff --git a/doc/BUILD_COORDINATOR.md b/doc/BUILD_COORDINATOR.md
@@ -358,10 +358,12 @@ the exact archive bytes; `url` rows are untrusted fetch hints and are not cache
identity. For `format tar.gz`, the coordinator fetches the archive blob if
needed, verifies the blob id, unpacks it with strict path validation, applies
`strip-prefix` if present, and treats the resulting directory as a read-only
-workspace root. For `format kpkg`, the archive blob is a signed kit package; the
-coordinator verifies the package with the configured trust policy, checks the
-optional `package` id when present, and materializes its default output tree as
-the external workspace root.
+workspace root. For `format kpkg`, the archive blob is a signed kit package. The
+current hosted coordinator verifies it with the package layer's TOFU state,
+checks the optional `package` id when present, and materializes its default
+output tree as the external workspace root. Applications embedding the
+coordinator can impose a different acquisition policy before admitting an
+archive to their CAS.
External workspaces are cached under the build store by content, e.g.
`build/external/<repo-key>/`, where `<repo-key>` is derived from `(format,
@@ -381,7 +383,7 @@ recomputed against the new external workspace. Same-content repins remain cache
no-ops; different content busts through the existing `recipe-id`, source, glob,
and dep-output checks.
-The driver should provide repository-management commands that update
+The driver provides repository-management commands that update
`WORKSPACE.kit` without hand-editing hashes:
```
@@ -390,10 +392,12 @@ kit build repo fetch NAME
kit build repo list
```
-`repo add` downloads `URL` through the host fetch path, stores the bytes in the
-CAS as a blob, records the blob id and URL in `WORKSPACE.kit`, and for `.kpkg`
-also records the verified `package-id`. `repo fetch` materializes the configured
-external workspace into the build-store external cache.
+The current `repo add` command accepts a local path or `file://` URL, hashes the
+archive, and records its blob id and URL in `WORKSPACE.kit`. It does not yet
+download remote URLs or derive the optional `package-id`. `repo fetch` currently
+checks that a configured name exists; actual verified fetching and
+materialization happen lazily when an `@repo//...` label is resolved. `repo
+list` prints the configured name, format, and archive id.
To make a workspace consumable by another workspace, package the source
workspace as a deterministic kit package whose default output tree is the
@@ -1207,18 +1211,18 @@ logged as an ordinary source dependency.
Build execution:
```
-kit build [--store DIR] [--root DIR] [--def-name FILE]
+kit build [--store DIR] [--root DIR] [--def FILE]
[--profile NAME] [--config K=V|env.NAME]... [--env NAME[=V]]...
[--verify] [--stats] [--trace] TARGET [-- ARG...]
-kit build list [--scan-do] [PATTERN]
-kit build repo {add|fetch|list} ...
-kit build workspace package [--format kpkg|tar.gz] [-s SECKEY] -o OUT
+kit build [--root DIR] [--def FILE] list [--scan-do] [//PACKAGE[/...]]
+kit build [--root DIR] repo {add|fetch|list} ...
+kit build [--root DIR] workspace package [--format tar.gz] -o OUT
```
Test execution:
```
-kit build test [--store DIR] [--root DIR] [--def-name FILE]
+kit build test [--store DIR] [--root DIR] [--def FILE]
[--profile NAME] [--config K=V|env.NAME]... [--env NAME[=V]]...
[--verify] [--stats] [--trace] TARGET [-- ARG...]
```
@@ -1230,14 +1234,19 @@ errors also exit nonzero and print diagnostics on stderr. `--stats` prints
cumulative coordinator counters, including `test_runs`, `test_cache_hits`, and
`test_failures`, to stderr. `--trace` prints target-level resolution decisions
to stderr, using the [diagnostic resolution trace](#diagnostic-resolution-trace)
-event names. `--def-name` selects the package build-file basename, overriding
-`WORKSPACE.kit`'s `def-name`; when neither is present it defaults to
-`BUILD.kit`. It must be a single filename, not a path, so package lookup remains
-`<workspace>/<package>/<def-name>`.
+event names. `--def` (also accepted as `--def-name`) selects the package
+build-file basename, overriding `WORKSPACE.kit`'s `def-name`; when neither is
+present it defaults to `BUILD.kit`. It must be a single filename, not a path, so
+package lookup remains `<workspace>/<package>/<def-name>`.
+
+`workspace package` currently emits only `tar.gz` through a hosted system
+`tar`. Use `kit pkg create` when a signed `.kpkg` or portable signed package is
+required.
Recipe-side shell helper commands are available as `kit build <verb> ...` inside
-a running recipe (`$KIT_BUILD_SOCK` set), or explicitly outside a recipe as
-`kit build --client <verb> ...`:
+a running recipe (`$KIT_BUILD_SOCK` set). `kit build --client <verb> ...`
+selects the same mode explicitly, but still requires the coordinator environment
+established for a running recipe:
```
kit build config-get [--default VALUE] KEY
diff --git a/doc/CODEGEN.md b/doc/CODEGEN.md
@@ -190,11 +190,12 @@ then conditionally wraps it:
- **`-O0`, native arch:** the backend's `make` returns a `NativeDirectTarget`
(see below). No IR is recorded; semantic ops emit machine code immediately.
-- **`-O1` (and `-O2`, currently an `-O1` alias) or interpreter:** `session.c` wraps the base target with
- `opt_cgtarget_new` (`src/opt/opt.c`), which returns a `CgIrRecorder`
- (`src/cg/ir_recorder.c`). Recording does not emit; at `kit_cg_finish` the optimizer
- replays optimized IR. The recorder still holds the unwrapped native target so
- the optimizer can drive `NativeTarget` directly after lowering.
+- **`-O1` (and `-O2`, currently an `-O1` alias) or interpreter:** `session.c`
+ wraps the base target with `opt_cgtarget_new` (`src/opt/opt.c`), which returns
+ a `CgIrRecorder` (`src/cg/ir_recorder.c`). Recording does not emit; at
+ `kit_cg_finish` the optimizer replays optimized IR. The recorder still holds
+ the unwrapped native target so the optimizer can drive `NativeTarget`
+ directly after lowering.
- **C-source / wasm:** the registry returns a source-like `CgTarget` that
implements the semantic vtable and writes C text or a wasm module. These are
semantic backends, not `NativeTarget` implementers.
@@ -210,10 +211,12 @@ surface exactly once — there is no separate per-arch semantic `CgTarget`.
one IR instruction in a per-function `CgIrFunc`, preserving operands, sticky
source locations, tail-call policy, and global references. It is purely a sink:
`finalize` triggers the optimizer's cross-function passes and per-function
-lowering. From the recorded clean IR, the optimizer derives its own
-CFG/SSA/MIR/allocated-MIR views and finally calls `opt_emit_native` to drive the
-arch `NativeTarget`. The same recorded IR feeds the interpreter via a sibling
-lowering path (`opt_run_o1_interp`). See [IR.md](IR.md), [OPT.md](OPT.md), and
+lowering. From the recorded clean IR, the current O1 schedule derives its own
+CFG/PReg/MIR/allocated-MIR views without constructing SSA, then calls
+`opt_emit_native` to drive the arch `NativeTarget`. The maintained future O2
+schedule additionally derives SSA/value views before returning to the same
+backend tail. The same recorded IR feeds the interpreter via a sibling lowering
+path (`opt_run_o1_interp`). See [IR.md](IR.md), [OPT.md](OPT.md), and
[INTERPRETER.md](INTERPRETER.md).
## Shared native `-O0`: NativeDirectTarget
diff --git a/doc/CODE_SIZE.md b/doc/CODE_SIZE.md
@@ -50,7 +50,7 @@ The full C compiler ≈ `lang/c` + `lang/cpp`, driving the shared
| Subsystem | Lines |
|---|---:|
-| optimizer (`opt`, -O1 SSA/regalloc) | 16,476 |
+| optimizer (`opt`, no-SSA O1 + maintained SSA O2/regalloc) | 16,476 |
| codegen (`cg`, public CG API + IR) | 11,454 |
| api (composition layer) | 6,935 |
| debug/DWARF (`debug`) | 6,026 |
diff --git a/doc/DBG.md b/doc/DBG.md
@@ -10,18 +10,18 @@ C11, like all of `src/`); the host primitives and the REPL live in the driver.
See [JIT.md](JIT.md) for how the image is produced and [DWARF.md](DWARF.md) for
the line/CFI/variable tables the source-level features consume.
-## V1 support boundary
+## Current support boundary
-The V1 release claim is limited to host/arch pairs where `make test-dbg` runs
-hard-green. Today that scripted lane runs on Darwin and Linux aarch64 hosts
+Supported host/arch pairs are limited to those where `make test-dbg` runs
+hard-green. The current scripted lane runs on Darwin and Linux aarch64 hosts
(`arm64` / `aarch64`) and validates breakpoints, instruction and source-line
stepping, backtraces, registers, variables, memory access, interrupt handling,
and teardown behavior.
Other arch hooks and host adapters may exist in the tree, but they are
implementation work until their debugger lane proves the same behavior. The
-source-level features are claimed for `-O0 -g`; optimized-source debugging is
-not a V1 release claim.
+source-level features are supported for `-O0 -g`; optimized-source debugging is
+not currently claimed.
## Layering
diff --git a/doc/DESIGN.md b/doc/DESIGN.md
@@ -1,33 +1,40 @@
# kit Design
-kit is a freestanding C11 compiler multi-tool, written in C11. This document
-is the front door to the design docs: it states what kit is, the principles
-that shape it, the layered architecture, the primary data flows, and an index of
-every sibling design doc. It is a map, not a manual — API signatures and struct
-layouts live in the headers under `include/kit/`; per-subsystem detail lives in
-the docs indexed at the end.
+kit is a freestanding C11 compiler multi-tool, written in C11. This document is
+the front door to the architecture: it states what kit is, the principles that
+shape it, the layered design, the primary data flows, and an index of the
+subsystem references. The task-oriented reader map is [README.md](README.md).
+API signatures and struct layouts live in the headers under `include/kit/`.
## What kit is
A single multi-call binary (`kit`) that bundles a complete C toolchain plus the
-machinery to JIT and debug what it produces. The v1 public surface is controlled
-by [plan/RELEASE.md](plan/RELEASE.md); subsystems marked internal there, such as
-the Toy frontend and `emu`, may remain documented for maintainers without being
-release claims. Capabilities:
+machinery to JIT and debug what it produces. The compiled tool registry (`kit
+--help`) and shipped public headers are the current surface; forward-looking
+release work lives in [plan/RELEASE.md](plan/RELEASE.md). Development surfaces,
+such as the Toy frontend and unregistered `emu` command, remain documented for
+maintainers. Capabilities:
- C11 preprocessor, single-pass parser/type checker, and code generator.
- A JIT compiler, an in-process runner, and an interactive debugger.
- A linker (objects/archives/DSO inputs -> executable or shared image), with
basic linker-script support and file-based incremental linking.
- A standalone assembler (GAS subset) and inline assembler sharing one emitter.
-- A lightweight optimizer (a recording IR with SSA, register allocation, and
- local cleanup behind `-O1`).
+- A lightweight no-SSA optimizer behind `-O1`: recorded IR, CFG/local cleanup,
+ machinization, and linear-scan register allocation. The maintained SSA
+ mid-end is reserved for a future distinct `-O2`; the accepted `-O2` spelling
+ currently aliases `-O1`.
- Cross-compiling backends for aarch64, x86-64, riscv64, and WebAssembly, plus a
portable C-source backend.
- Object read/write for ELF, Mach-O, and PE/COFF; a Wasm object form.
- DWARF debug-info production and consumption; a disassembler.
- A bytecode interpreter over the optimizer IR (`run --no-jit`).
- Signed, content-addressed code distribution (`.kpkg`).
+- A content-addressed build system (`kit build`) with declared recipe inputs,
+ output-tree identity, deep/shallow dependency traces, workspace packages,
+ and signed trace sharing.
+- A public target-profile registry (`kit targets`) that separates compiler
+ capability from local SDK/sysroot/runner provisioning.
- A parser/lexer generator (`gram`): EBNF in, C parser / lexer / token-machine
tables out, with allocation-free push runtimes for the generated code.
- Object/archive utilities: `ar`, `ranlib`, `nm`, `size`, `strip`, `objcopy`,
@@ -72,8 +79,8 @@ From outside in, each layer depends only on the layer beneath it:
```
driver/ CLI policy + host I/O. Includes ONLY <kit/*.h>.
- lang/ Frontends (c, cpp, toy, wasm). API consumers; ONLY
- <kit/*.h> + their own private headers.
+ lang/ Frontends. C/cpp/toy consume <kit/*.h> + their own private
+ headers; wasm has one documented shared-module edge.
include/kit/ PUBLIC BOUNDARY. The library's entire stable contract.
src/api/ Composition: public handles <-> internal subsystems.
src/... Internal subsystems. Share private headers among their own
@@ -104,10 +111,13 @@ driver/ CLI policy + host I/O. Includes ONLY <kit/*.h>.
`link`, `jit`, `dbg`, `emu`, `interp`, `debug` (DWARF), `wasm`, `os`, and
`dist` (content-addressed store + signed `.kpkg` packaging).
-**The layering invariant:** `driver/` and `lang/` include only `<kit/*.h>` —
-never a `src/` header. Anything a frontend or tool needs is promoted into the
-public headers; reaching into `src/` is a layering violation. Subsystem
-`*_internal.h` headers stay private to their own translation units.
+**The layering invariant:** `driver/` includes only `<kit/*.h>` and the one
+frontend-public C header; C/cpp/toy frontends likewise stay on the public
+surface. The Wasm frontend's single `src/wasm/wasm.h` edge is a documented
+shared-internal module contract with the Wasm object/backend peers, not general
+permission for frontends to include `src/`. Anything else a frontend or tool
+needs is promoted into public headers. Subsystem `*_internal.h` headers stay
+private to their own translation units. See [INTERFACES.md](INTERFACES.md).
## Key abstractions
@@ -118,9 +128,10 @@ public headers; reaching into `src/` is a layering violation. Subsystem
- **Tiered backend.** A `CgTarget` (`src/cg/cgtarget.h`) receives the lowered CG
stream. At `-O0` a shared `NativeDirectTarget` adapts the physical
`NativeTarget` (`src/arch/native_target.h`) directly; at `-O1` the optimizer
- wrapper (`src/opt/`) records IR, runs its passes, then replays into the same
- `NativeTarget`. Physical machine bytes flow through one arch-neutral
- `MCEmitter` (`src/arch/mc.h`).
+ wrapper (`src/opt/`) records IR, runs the no-SSA O1 schedule, and replays into
+ the same `NativeTarget`. The separate SSA schedule is implemented but remains
+ unreachable while `-O2` aliases `-O1`. Physical machine bytes flow through
+ one arch-neutral `MCEmitter` (`src/arch/mc.h`).
- **`ObjBuilder` (`src/obj/obj.h`)** is the canonical in-memory object model
during compilation, assembly, linking, JIT, inspection, and DWARF emission —
one section/symbol/relocation store, with format knowledge behind
@@ -212,7 +223,7 @@ unless an API states otherwise.
| [IR.md](IR.md) | The recording/optimizer IR: instructions, types, and how CG operations become analyzable functions. |
| [ARCH.md](ARCH.md) | Per-arch backends (aarch64/x86-64/riscv64), `ArchImpl` dispatch, `MCEmitter`, register files, and fixups. |
| [ASM.md](ASM.md) | The standalone + inline assembler, GAS-subset syntax, and the shared emitter. |
-| [OPT.md](OPT.md) | The `-O1` optimizer: SSA construction, register allocation, combine/DCE, and replay into the backend. |
+| [OPT.md](OPT.md) | The optimizer: current no-SSA `-O1`, maintained future SSA `-O2`, register allocation, cleanup, and native replay. |
| [INTERPRETER.md](INTERPRETER.md) | The bytecode interpreter over the optimizer IR used by `run --no-jit`. |
| [OBJ.md](OBJ.md) | The format-neutral object model and ELF/Mach-O/COFF/Wasm read/write behind `ObjFormatImpl`. |
| [LINK.md](LINK.md) | Linking: symbol resolution, layout, relocation, linker scripts, and incremental linking. |
@@ -226,6 +237,7 @@ unless an API states otherwise.
| [DISTRIBUTE.md](DISTRIBUTE.md) | Signed `.kpkg` packaging and the content-addressed store (`src/dist/`, `<kit/cas.h>` / `<kit/package.h>`, `cas`/`pkg` tools). |
| [BUILD_COORDINATOR.md](BUILD_COORDINATOR.md) | The content-addressed build coordinator: `<kit/build_coord.h>`, `kit build`, trace/deepset caching, recipe protocol, and shared traces. |
| [RELEASE.md](RELEASE.md) | Releasing and updating kit itself: `VERSION`/`kit --version`, `make dist` + `scripts/release.sh` signed artifacts, the `kit-release` channel index, and `kit update`. |
+| [EMBEDDING.md](EMBEDDING.md) | Linking `libkit.a`, host callbacks, handle lifetimes, compile/link sessions, frontend registration, and ownership rules. |
| [DRIVER.md](DRIVER.md) | The multi-call binary, tool registry, and command-line policy. |
| [RUNTIME.md](RUNTIME.md) | The freestanding headers and compiler-rt/libc-style support in `rt/`. |
| [BUILD.md](BUILD.md) | The build system and `KIT_*_ENABLED` component gating. |
diff --git a/doc/DISTRIBUTE.md b/doc/DISTRIBUTE.md
@@ -16,6 +16,13 @@ Release artifacts use the same package format. See [RELEASE.md](RELEASE.md) for
the `kit update` flow, install-root layout, default tool links, and release
channel index built on top of `kit pkg`.
+Hosted SDK/sysroot distribution is planned to use this same signed `.kpkg` and
+CAS model, but is not part of the current package install surface. Today a
+hosted cross compile takes an explicitly provisioned sysroot. The proposed
+minimal, target-profile-indexed packages and acquisition flow are in
+[plan/SYSROOTS.md](plan/SYSROOTS.md); keeping that work under `plan/` prevents a
+future provisioning design from becoming a current release claim.
+
## Why this shape
Three design decisions drive the whole subsystem:
diff --git a/doc/DRIVER.md b/doc/DRIVER.md
@@ -1,13 +1,15 @@
# DRIVER
-The `kit` multitool is the toolchain's only executable: a single binary that
-dispatches to ~27 named tools (compiler, assembler, linker, archive/object
-utilities, byte utilities, JIT runner, debugger, packager, and an
-`install` command that lays down the per-tool links). It is also the first and
-canonical *consumer* of libkit — it depends only on the public API under
-`include/kit/`, never on `src/`. Everything that the OS provides (heap, file
-I/O, executable memory, threads, signals, time, entropy) enters libkit through
-host vtables that the driver constructs in exactly one place. See
+The `kit` multitool is the toolchain's only executable: a single binary whose
+component-gated registry dispatches the compiler, assembler, linker,
+archive/object utilities, data tools, JIT/interpreter/debugger, grammar and
+image tools, package/build tools, target discovery, installation, and updates.
+The registry and `kit --help` are the authoritative inventory; this document
+groups the tools by role rather than maintaining a brittle count. The driver is
+also the first and canonical *consumer* of libkit — it depends only on the
+public API under `include/kit/`, never on `src/`. Everything that the OS provides
+(heap, file I/O, executable memory, threads, signals, time, entropy) enters
+libkit through host vtables that the driver constructs in exactly one place. See
[DESIGN.md](DESIGN.md) for the library it drives, [INTERFACES.md](INTERFACES.md)
for the public API, [RUNTIME.md](RUNTIME.md) for `libkit_rt.a`, and
[DISTRIBUTE.md](DISTRIBUTE.md) for the `pkg`/`cas` subsystem.
@@ -88,14 +90,18 @@ tool reaches into compiler internals.
| `build-exe` | Kit-native build verb: compile a polyglot source set (C / asm / wasm, per file) in memory and link it — with any `.o`/`.a`/`.so` inputs — into an executable. No intermediate files. |
| `build-lib` | Compile a polyglot source set in memory into a static `.a` (default) or, with `-dynamic`, an ELF shared library. |
| `build-obj` | Compile sources to one object (or `--emit=asm\|c\|ir`, or `-fsyntax-only` check); multiple sources combine into one relocatable object (`ld -r`). The kit-native replacement for the retired `compile` tool. |
+| `build` | Resolve workspace targets with the content-addressed build coordinator; run test targets; manage workspace repositories/packages; and serve the recipe-side source/glob/fetch/config/need/export protocol. |
| `install` | Lay down per-tool links (symlinks; hard links on Windows) in a target dir so the toolchain works under bare names (`cc`, `ld`, `nm`, …). Default set is the toolchain + standard-named byte utils; `--all` / explicit names override. |
| `cpp` | Standalone preprocessor (alias for `cc -E` without link scaffolding). |
| `as` | Assemble one GAS-subset text source to a relocatable object. |
| `ld` | Link objects/archives into an executable, ELF shared library, or relocatable object; parses `-T` scripts into structured form. |
+| `gram` | Generate C lexer/parser/token-machine tables and allocation-free push runtimes from EBNF grammars. |
| `ar` / `ranlib` | Create/modify/list/extract `ar` archives; refresh the symbol index. |
+| `cpio` | Create, list, and extract SVR4 `newc` archives used for initramfs images. |
| `strip` / `objcopy` | Drop debug/symbols; rename/remove sections, reformat. |
+| `image` | Emit flat load/kernel images from linked objects. |
| `objdump` / `nm` / `size` | Inspect sections, symbols, disassembly, relocations, sizes. |
-| `addr2line` / `strings` | Address→`file:line` via DWARF; printable runs. |
+| `addr2line` / `symbolize` / `strings` | Address→`file:line` via DWARF; annotate kit backtrace streams; print printable runs. |
| `xxd` | Hex dump *any* file (format-agnostic, unlike `objdump -s`); reverse a dump to binary (`-r`), plain (`-p`), C array (`-i`). |
| `cmp` | Compare two files byte by byte; GNU/BSD-compatible messages and 0/1/2 exit codes. |
| `hash` | SHA-256, BLAKE2b-256, or CRC-32 (`-a`) of files or stdin; coreutils-style output. Backed by the public `<kit/hash.h>`. |
@@ -107,6 +113,9 @@ tool reaches into compiler internals.
| `run` | JIT-compile inputs and call the entry symbol in-process. |
| `dbg` | Interactive JIT debugger on hard-green `test-dbg` host lanes (REPL over a `KitDebugSession`). |
| `cas` / `pkg` | Content-addressed store and signed `.kpkg` distribution. |
+| `targets` | List or inspect the public target-profile registry, separating capability from local provisioning. |
+| `version` | Print the canonical release, build, and host identity. |
+| `update` | Authenticate a release channel/package, install under `KIT_HOME`, atomically switch versions, list/prune, and roll back. |
`run` and `dbg` share the `--`-terminated argv convention: flags before
`--` configure the tool, tokens after `--` become the JITed program's argv.
@@ -128,15 +137,15 @@ flags) that apply to the whole build, and a small scopable set (`-I`/`-isystem`/
and the same language-neutral per-source compile step
(`driver/lib/compile_engine.c`).
-For v1, `-O0` and `-O1` are the real optimization levels. `-O2` is accepted by
-the driver and public CG API as a compatibility spelling, but it aliases `-O1`
-and does not enable a separate optimizer schedule. This is intentional release
-policy and may change after v1.
+`-O0` and `-O1` are the current optimization levels. `-O1` records IR and uses
+the fast no-SSA optimizer/register-allocation path. `-O2` is accepted by the
+driver and public CG API as a compatibility spelling, but it aliases `-O1` and
+does not yet enable the maintained SSA schedule.
-The emulator command and Toy frontend are internal for v1: they may remain
-compiled for development and regression tests, but they are not listed in
-top-level help, installed by `install --all`, or presented as public release
-surface.
+The emulator command and Toy frontend are development surfaces: they may remain
+compiled for regression tests, but they are not listed in top-level help or
+installed by `install --all`. The separately documented `<kit/emu.h>` library
+API remains available when that component is enabled.
`run` doubles as a `#!` script interpreter so a C file can be made executable
and run directly. The kernel's shebang mechanism appends the script path *and*
@@ -196,9 +205,11 @@ and consistent. All are freestanding (no host calls except through `env/`).
default libraries, system include dirs, interpreter path, and predefined
macros needed to link a *hosted* executable for a target profile. This is the
classification of which inputs the link step must inject implicitly.
-- **runtime** (`lib/runtime.c`): discovers the kit support root (next to
- `argv[0]`, or `--support-dir`), then locates-or-builds `libkit_rt.a` for the
- selected target. It carries a per-target `RuntimeVariant` table (sources, ABI
+- **runtime** (`lib/runtime.c`): takes an explicit `--support-dir` as
+ authoritative; otherwise resolves the canonical running executable and finds
+ the development or packaged sibling support tree. It then
+ locates-or-builds `libkit_rt.a` for the selected target. It carries a
+ per-target `RuntimeVariant` table (sources, ABI
include dir, `HAS_INT128`/`LDBL128` defines) and rebuilds the archive into a
cache dir (`$XDG_CACHE_HOME`/`~/.cache/kit`, falling back) when any source
or the tool binary is newer than the cached archive. This is how `cc` ships a
diff --git a/doc/DWARF.md b/doc/DWARF.md
@@ -398,4 +398,4 @@ consumer be tested against each other purely through emitted bytes.
---
-Planned work: see doc/plan/DEBUG.md.
+Planned work is tracked in [plan/DEBUG.md](plan/DEBUG.md).
diff --git a/doc/EMBEDDING.md b/doc/EMBEDDING.md
@@ -0,0 +1,167 @@
+# Embedding libkit
+
+Kit ships as both the `kit` multi-call executable and `lib/libkit.a`. The driver
+is the reference host for the library: it uses the public headers under
+`include/kit/` and supplies the OS-facing callbacks that freestanding libkit
+does not provide itself.
+
+This document is the entry point for an application embedding compilation,
+objects, linking, JIT, debugging, packages, or builds. Exact signatures and
+ownership annotations live in the public headers; the architectural boundary
+inventory is in [INTERFACES.md](INTERFACES.md).
+
+## Link against the distribution
+
+For an extracted native distribution:
+
+```sh
+ROOT=/path/to/kit
+K="$ROOT/bin/kit"
+
+"$K" cc -I "$ROOT/include" embed.c "$ROOT/lib/libkit.a" -o embed
+./embed
+```
+
+Native support and SDK discovery follow the same rules as `kit cc`. An explicit
+`--support-dir`, `--sysroot`, or `-isysroot` overrides discovery. The static
+library has no extra user-selected dependency when linked through the native
+hosted profile.
+
+Include the narrow headers for the APIs in use; there is intentionally no
+whole-library `kit.h` umbrella. Common entry points are:
+
+| Task | Header |
+|---|---|
+| Context, compiler, writers, diagnostics | `<kit/core.h>` |
+| Target profiles and triples | `<kit/target.h>` |
+| High-level source compilation | `<kit/compile.h>` |
+| Language/frontend code generation | `<kit/frontend.h>`, `<kit/cg.h>` |
+| Objects and archives | `<kit/object.h>`, `<kit/archive.h>` |
+| Linking and JIT publication | `<kit/link.h>`, `<kit/jit.h>` |
+| Debug information and debugger sessions | `<kit/dwarf.h>`, `<kit/dbg.h>` |
+| Content store and packages | `<kit/cas.h>`, `<kit/package.h>` |
+| Content-addressed builds | `<kit/build_coord.h>` |
+
+## Host contract
+
+Libkit is freestanding and owns no process-global host adapter. The embedder
+constructs a `KitContext` and keeps its referenced callbacks alive for every
+object that uses them.
+
+The common context may provide:
+
+- `KitHeap` for aligned allocation, reallocation, and release;
+- `KitDiagSink` for diagnostics and maintained error/warning counters;
+- `KitFileIO` when an API should resolve files through the host;
+- optional metrics and clock callbacks.
+
+The heap callbacks must honor the requested alignment. Input slices are usually
+borrowed for the duration stated by the API; a context callback's user data must
+outlive every operation that can call it.
+
+JIT and debugger operations require additional, deliberately separate host
+interfaces:
+
+- `KitJitHost` supplies executable-memory reservation, protection, release, and
+ instruction-cache flushing through `KitExecMem`;
+- `KitDbgHost` supplies the thread, event, signal/trap, guarded-memory, and
+ code-patching operations required by a debug session.
+
+Keeping these interfaces separate means an embedder that only compiles or links
+does not need to provide executable-memory or signal machinery.
+
+## Common lifecycle
+
+1. Initialize the embedder-owned `KitHeap`, `KitDiagSink`, optional
+ `KitFileIO`, and `KitContext`.
+2. Parse a target with `kit_target_from_triple`, or select a public target
+ profile from `<kit/target.h>`.
+3. Create a `KitTarget` with `kit_target_new`.
+4. Create a `KitCompiler` with `kit_compiler_new` or `kit_compiler_new_ex`.
+5. Create short-lived compile, object, link, JIT, debug, package, or build
+ sessions under that compiler/context.
+6. Free sessions and builders before freeing the compiler; free the target
+ after the compiler.
+
+No mutable process-global compiler exists. Independent contexts and compiler
+handles may coexist, subject to the thread-safety rules documented by each
+specific public API.
+
+## Compile and link lifecycle
+
+The high-level source path is defined by `<kit/compile.h>`:
+
+1. Fill `KitCompileSessionOptions`, including the registered language and
+ frontend input kind.
+2. Create a `KitCompileSession` with `kit_compile_session_new`.
+3. Stage a caller-owned `KitSourceInput` with
+ `kit_compile_session_stage`. Source names and bytes must remain valid for the
+ duration documented by the header.
+4. Consume the returned `KitObjBuilder`: emit it, inspect it, or add it to a
+ link session.
+5. Publish the final output through a caller-owned `KitWriter`.
+6. Call `kit_compile_session_commit` only after publication succeeds. On every
+ abandoned or failed staged path, call `kit_compile_session_abort`.
+
+For a file image, create a `KitLinkSession` from `<kit/link.h>`, add object
+builders or borrowed object/archive/DSO bytes in command-line order, resolve,
+and emit through a `KitWriter`. The linker owns resolution and layout policy;
+the caller owns its input buffers and output sink unless a specific API says
+otherwise.
+
+Cleanup is the reverse of construction:
+
+```text
+writer -> link session -> object builder -> compile session
+ -> compiler -> target -> embedder-owned context services
+```
+
+## Language frontends
+
+A language can bypass the high-level compile session and emit directly through
+`KitCg` from `<kit/cg.h>`. Frontends should include `<kit/frontend.h>`, the
+tier-scoped front door that re-exports the code-generation, compile, source, and
+arena facilities intended for frontend authors.
+
+The frontend provides a `KitFrontendVTable`, registers it with the compiler,
+and emits semantic operations into a `KitObjBuilder`. It does not own target
+object formats, ABI layout policy, or linking. Those remain behind the public
+codegen/object/link boundaries.
+
+The C, cpp, and internal Toy frontends are built without access to `src/`
+headers and are useful boundary examples. The Wasm frontend has one documented
+internal-module exception; external frontends should not copy that exception.
+
+See [FRONTENDS.md](FRONTENDS.md) and [CODEGEN.md](CODEGEN.md).
+
+## Object, JIT, and distribution paths
+
+The public API is intentionally composable:
+
+- `<kit/object.h>` builds, reads, inspects, and rewrites format-neutral objects.
+- `<kit/archive.h>` reads and writes POSIX archives.
+- `<kit/link.h>` emits files or a JIT link image from the same object inputs.
+- `<kit/jit.h>` publishes a resolved image through embedder-supplied executable
+ memory.
+- `<kit/disasm.h>` and `<kit/dwarf.h>` inspect code and debug information.
+- `<kit/cas.h>` and `<kit/package.h>` expose content-addressed trees and signed
+ packages without imposing network transport.
+- `<kit/build_coord.h>` exposes the content-addressed build coordinator through
+ a host scheduler/filesystem/process adapter.
+
+The command-line tools are thin hosted examples of these compositions. They are
+not additional privileged entry points into libkit internals.
+
+## Error handling and ownership checklist
+
+- Check every `KitStatus`; diagnostics provide detail but do not replace status
+ handling.
+- Keep borrowed source/object/archive buffers alive for the documented call or
+ session lifetime.
+- Close every writer and check its status before committing staged work.
+- Abort an uncommitted compile session on every failure path.
+- Free child sessions/builders before their compiler and target.
+- Keep context services and their user pointers alive until all kit handles are
+ gone.
+- Supply executable-memory, TLS, signal, and thread hooks only to the JIT/debug
+ operations that require them.
diff --git a/doc/EMU.md b/doc/EMU.md
@@ -1,9 +1,10 @@
# Emulator
-The emulator is an internal/development subsystem for v1. `kit emu` and the
-`kit_emu_*` API may be built and tested, but they are not part of the v1 public
-release surface unless [plan/RELEASE.md](plan/RELEASE.md) is updated to promote
-them.
+The emulator is a library and development subsystem. Its `kit_emu_*` API is
+exposed through `<kit/emu.h>` when the component is enabled. The `kit emu`
+development command may be built and tested, but it is not registered in the
+current public command inventory or installed by `kit install --all`. This
+document covers both the API and that maintainer-facing command.
`kit emu` is a user-mode emulator for guest ELF executables. It loads a
guest program image into a host-managed address space, then runs it by
diff --git a/doc/FRONTENDS.md b/doc/FRONTENDS.md
@@ -11,8 +11,8 @@ pipeline, and the smaller toy and wasm frontends. For testing, see
kit ships four frontends in-tree: C (the public C frontend), asm (lives inside
the codegen substrate), wasm (the public WAT/wasm lowering frontend), and toy
-(an internal CG-API exercise vehicle). Toy may remain in developer tests, but it
-is not part of the v1 public release surface.
+(an internal CG-API exercise vehicle). Toy remains a development/test frontend
+rather than part of the public language set.
## The frontend contract
diff --git a/doc/GRAM.md b/doc/GRAM.md
@@ -6,8 +6,9 @@ optional standalone (re2c-style) scanners. It is **not** a `lang/` frontend —
registers no `KitFrontendVTable` and emits no `KitCg`. Its surface is consumed by
embedders, by the `kit gram` driver command, and by the C it generates.
-It was imported (one-time fork) from the standalone `gramgen` project; see
-`doc/plan/GRAM_IMPORT.md` for the import plan and rename scheme.
+It was imported as a one-time fork of the standalone `gramgen` project. The
+public `kit_gram_*` names and the interfaces described here are the maintained
+Kit surface.
## Public API
diff --git a/doc/INTERFACES.md b/doc/INTERFACES.md
@@ -78,33 +78,25 @@ something — add it to `include/kit/`, don't grow the edge.
## Tier 1 — Public API (`include/kit/`)
-The library's entire stable contract: nineteen headers in `include/kit/` plus
-two in `include/kit/support/`. No umbrella header — each consumer includes what
-it uses.
-
-| Header | Purpose | Key opaque type(s) | Primary consumer |
-|--------|---------|--------------------|------------------|
-| `core.h` | Foundational substrate: compiler lifecycle, target triple, slices, status codes, host vtables (`KitHeap`/`KitWriter`/`KitDiagSink`/`KitContext`), symbol interning. | `KitCompiler` | everyone |
-| `config.h` | Build-time component enable flags (arch / obj-format / language / subsystem / tool). Preprocessor-only. | — | build |
-| `compile.h` | High-level source->object compilation; frontend registration vtable; dep iteration. | `KitCompileSession`, `KitDepIter` | driver, frontends |
-| `cg.h` | Code-generation API (the largest contract): a stack-machine typed IR over `KitCg`. Types/ABI, functions, control flow, memory, arithmetic, calls, intrinsics, inline+file asm, static data. | `KitCg` | frontends |
-| `frontend.h` | Frontend **front door**: re-exports `cg.h` / `compile.h` / `source.h` / `support/arena.h`, plus the panic boundary (`kit_frontend_run`), metrics scopes, and fatal helpers. Including this alone is enough to write and register a frontend. | — | frontends |
-| `source.h` | Source registry: stable file IDs + include-edge recording. | — | frontends |
-| `preprocess.h` | Standalone C preprocessor entry. | — | driver |
-| `object.h` | Format-neutral object model: builder + read-only inspection; section/symbol/reloc enums. | `KitObjBuilder`, `KitObjFile` | cg, link, jit, disasm, dwarf |
-| `link.h` | Linker: byte/object/archive/DSO inputs, linker-script model, emit or JIT. | `KitLinkSession`, `KitLinkScript` | driver, jit |
-| `jit.h` | JIT image: mapped pages, symbol resolution, publish/append/replace, object view. | `KitJit` | runtime, dbg |
-| `interp.h` | Threaded-bytecode interpreter over the optimizer IR; host-identity and emu/guest configurations. | `KitInterpProgram` | `run --no-jit`, emu |
-| `dbg.h` | In-process JIT execution: the `kit_dbg_session_*` control substrate (breakpoints, stepping, regs/mem, signal host) plus a `kit_dbg_*` symbolic layer (backtraces, typed/navigable values + formatting, scope enumeration, location resolution, disasm-at-PC) composed over the session's DWARF + JIT image. | `KitDebugSession`, `KitDebugValue`, `KitDebugFrame` | debuggers |
-| `dwarf.h` | DWARF5 consumer: PC<->line, type/var/subprogram queries, structural iterators. | `KitDebugInfo`, `KitDwarfType` | debuggers, dumpers |
-| `disasm.h` | Disassembly of byte ranges and objects, with symbol/reloc annotation. | `KitDisasmIter` | objdump, dbg |
-| `emu.h` | User-mode guest-ELF emulator (per-block JIT). | `KitEmu` | emu tool |
-| `arch.h` | Arch-agnostic register / unwind-frame metadata helpers. | — | dbg, dwarf, disasm |
-| `archive.h` | POSIX `ar` reader/writer + symbol index. | `KitArIter` | ar/ranlib |
-| `asm_emit.h` | Emit assembled object bytes as GAS text. | — | objdump |
-| `wasm.h` | WebAssembly host-import resolver/binder. | `KitWasmInstance` | wasm runners |
-| `support/arena.h` | Public bump allocator (narrowed mirror of `src/core/arena.h`). | `KitArena` | frontends |
-| `support/hashmap.h` | Header-only `KIT_HASHMAP_DEFINE` template + hash fns. | — (macro) | frontends |
+The headers under `include/kit/` and `include/kit/support/` are the library's
+entire stable contract. There is no whole-library umbrella header: consumers
+include the narrow surfaces they use. The API comments in each header are the
+signature, ownership, and lifetime authority; [EMBEDDING.md](EMBEDDING.md) is
+the task-oriented entry point.
+
+The public surface is grouped as follows. This table deliberately avoids a
+fixed header count, which becomes stale whenever a public component is added.
+
+| Header group | Responsibility | Primary handles/consumers |
+|---|---|---|
+| `core.h`, `target.h`, `driver.h`, `os.h`, `profile.h`, `trace.h`, `config.h` | Context services, compiler/target lifecycle, target registry, hosted-driver contracts, profiling/tracing, component gates | every embedder and the driver |
+| `compile.h`, `frontend.h`, `source.h`, `preprocess.h`, `cg.h`, `asm_constraints.h` | High-level compilation, frontend registration, source tracking, preprocessing, semantic code generation, inline-asm constraints | compiler drivers and language frontends |
+| `object.h`, `archive.h`, `asm_emit.h`, `image.h` | Format-neutral objects, archives, assembly rendering, load/kernel images | codegen, linker, binary tools |
+| `link.h`, `jit.h`, `interp.h`, `dbg.h`, `dwarf.h`, `disasm.h`, `arch.h`, `emu.h`, `wasm.h` | Linking, execution, debugging, debug information, disassembly, architecture metadata, guest/Wasm hosts | execution and inspection tools |
+| `cas.h`, `package.h`, `hash.h`, `compress.h` | Content-addressed storage, signed packages, hashes, gzip/LZ4 | distribution tools and embedders |
+| `build.h`, `build_coord.h` | Build definitions, coordinator lifecycle, requests/results, host scheduler/process/filesystem contract | `kit build` and build hosts |
+| `gram.h`, `gram_lex.h`, `gram_parse.h`, `gram_pos.h`, `gram_unicode.h` | Grammar generation and generated lexer/parser runtime APIs | `gram` and generated parsers |
+| `support/arena.h`, `support/hashmap.h`, `support/symtab.h`, `support/gram_*_tables.h` | Public support containers and generated-table contracts | frontends and generated code |
**Public-tier notes:**
- `cg.h` is by far the largest contract and the one frontends couple to hardest.
@@ -225,7 +217,7 @@ subsystems are allowed to include; the internal header is not.
| obj | `src/obj/obj.h` | format headers private | Format-neutral object model (`ObjBuilder`, sections, symbols, relocs) plus read side; the hub cg/link/jit/disasm/dwarf depend on. |
| ↳ formats | `src/obj/{elf,macho,coff}/*.h`, `format.h`, `reloc_apply.h` | — | Per-format emit/read behind `ObjFormatImpl`; `link_reloc_apply` for relocation. |
| link | `src/link/link.h` (+ `link_arch.h`) | `link_internal.h` | Byte/object/archive/DSO inputs, symbol resolution (single-shot and incremental), ELF/JIT output; `kit_jit_from_image`. |
-| opt | `src/opt/opt.h` (+ `ir.h`) | `opt_internal.h` | SSA construction, CFG passes, register allocation, MIR lowering; `opt_cgtarget_new(Compiler, CgTarget, level)` wraps a backend target. |
+| opt | `src/opt/opt.h` (+ `ir.h`) | `opt_internal.h` | Current no-SSA O1 CFG/local passes, maintained future O2 SSA passes, register allocation, and MIR lowering; `opt_cgtarget_new(Compiler, CgTarget, level)` wraps a backend target. |
| cg | `src/cg/{ir,ir_recorder,type}.h` | `internal.h` | IR recording and the codegen type system (`cg_type_*`). |
| debug | `src/debug/debug.h` (+ `dwarf_defs.h`) | `debug_internal.h`, `dwarf_internal.h` | DWARF producer: types, subprograms, line program, emit. |
| emu | `<kit/emu.h>` (public face) | `src/emu/emu.h` | Guest-ELF emulator; format hooks via `ObjFormatEmuOps`. |
diff --git a/doc/INTRODUCING_KIT.md b/doc/INTRODUCING_KIT.md
@@ -0,0 +1,258 @@
+# Kit: a BusyBox for compilation
+
+A Unix C toolchain is already a collection of programs. `cc` coordinates several
+of them: preprocessing and compilation, often an assembler, and finally a
+linker with the appropriate startup files and system libraries. Around that is
+the binutils suite for archives, symbols, object inspection, stripping, copying,
+and disassembly.
+
+That still stops at producing a program. JIT execution and WebAssembly runtimes
+usually arrive as separate systems. Build tools sit above the toolchain, package
+tools sit after it, and SDK acquisition is another concern again. Each layer has
+its own configuration, target vocabulary, cache, and distribution conventions.
+
+BusyBox simplified a similar problem for basic Unix utilities: put one coherent
+implementation behind many familiar command names. Kit applies that model to a
+compilation toolchain.
+
+Kit is one multi-call executable containing a C compiler, assembler, linker,
+JIT, debugger, binary utilities, build system, and package tools. It can be used
+through the `kit` command:
+
+```sh
+kit cc main.c -o app
+kit ar rcs libapp.a app.o
+kit objdump -h -t app
+```
+
+Or `kit install` can create the usual tool names as symlinks, with hard links on
+Windows:
+
+```sh
+cc main.c -o app
+ar rcs libapp.a app.o
+objdump -h -t app
+```
+
+The command set includes the usual compiler and binutils surface—`cc`, `cpp`,
+`as`, `ld`, `ar`, `ranlib`, `nm`, `size`, `strip`, `objcopy`, `objdump`, and
+`addr2line`—along with less conventional tools such as `run`, `dbg`, `mc`,
+`disas`, `build`, `cas`, `pkg`, and `update`.
+
+The BusyBox analogy explains the interface, but not the more useful property:
+these are views of one library, not unrelated programs packed into one file.
+
+## One compilation model
+
+The compiler, linker, object tools, and JIT share the same target registry,
+code-generation interfaces, object model, relocation machinery, and debug
+information. A source file can move through the same implementation and end up
+as an object file, a linked executable, an in-process JIT image, optimizer IR,
+or portable C.
+
+```sh
+kit cc -c add.c -o add.o
+kit cc --emit=ir -O1 add.c -o add.ir
+kit run add.c
+kit run --no-jit add.c
+```
+
+At `-O0`, semantic code generation feeds a native backend directly. At `-O1`,
+kit records an IR, performs lightweight optimization and register allocation,
+and then replays into the same backend. `-O2` currently aliases `-O1`; the
+planned SSA pipeline belongs to a future distinct `-O2` implementation.
+
+The target backend produces kit's format-neutral object model. That object can
+be written as ELF, Mach-O, PE/COFF, or Wasm, passed to the linker, inspected by
+the binary tools, or turned into a JIT image. The standalone assembler and
+inline assembler use the same machine-code emitter. `mc` exposes it directly:
+
+```text
+$ kit mc -target aarch64-none-elf 'add x0, x0, #1'
+add x0, x0, #1 # encoding: [0x00,0x04,0x00,0x91]
+```
+
+Cross-compilation uses the same binary. The compiled target registry covers
+x86-64, AArch64, RISC-V, Arm freestanding targets, and WebAssembly across ELF,
+Mach-O, COFF, and Wasm environments. `kit targets` reports both what a profile
+can do and what local provisioning it needs:
+
+```text
+freestanding-rv64 riscv64-none-elf elf compile,assemble,link,execute [qemu]
+macos-aa64 aarch64-apple-darwin macho compile,assemble,link,execute,selfhost [native]
+windows-x64 x86_64-windows coff compile,assemble,link,execute,selfhost [vm]
+wasm32-wasi wasm32-wasi wasm compile,link,execute [sysroot]
+```
+
+A profile being present does not imply that its SDK, sysroot, emulator, or VM is
+installed. Hosted cross-compilation still needs the target's system files.
+
+## Rough performance
+
+Kit's compile-speed target is closer to tcc than to a large optimizing compiler,
+while its generated code is intended to stay in the same general size range.
+A representative Apple M1 compile of the 9 MB SQLite amalgamation gives the
+following orientation:
+
+| Compiler | `-O0` compile | `-O1` compile | `-O0` text | `-O1` text | Speedup vs clang | Text vs clang |
+|----------|--------------:|--------------:|------------:|------------:|-----------------:|--------------:|
+| tcc | 0.060 s | N/A | 1.31 MiB | N/A | 13x / N/A | 1.3x / N/A |
+| kit | 0.160 s | 0.88 s | 1.29 MiB | 0.95 MiB | 5x / 7x | 1.3x / 1.1x |
+| clang | 0.783 s | 6.34 s | 0.97 MiB | 0.88 MiB | 1x / 1x | 1x / 1x |
+
+Ratio columns are `-O0 / -O1`; higher speedup and lower text ratio are better.
+Times are warm means: seven `-O0` runs and three `-O1` runs. Text is emitted
+machine code, not total object size. At `-O0`, kit is about 3 times slower than
+tcc and 5 times faster than clang; its text is 1% smaller than tcc's and 32%
+larger than clang's. `-O1` shrinks text about 25% for kit and 10% for clang.
+Across the nine-source corpus, kit's `-O1` text was about 6% larger. Results vary
+by workload and revision.
+
+## A C library, not a command-line wrapper
+
+The executable is the reference host for `libkit`. The driver and language
+frontends consume the public headers under `include/kit/`; they cannot reach
+into compiler internals. Compilation, object construction, linking, JIT,
+debugging, hashing, compression, content storage, and packaging are all
+available through that library boundary.
+
+Libkit is freestanding C11. It has no mutable global state and does not quietly
+reach into the operating system. The host supplies allocation, diagnostics,
+file I/O, clocks, executable memory, TLS, and debugger operations through
+explicit context structs and vtables. State belongs to a compiler, builder,
+link session, JIT session, or another appropriate context.
+
+This is useful for embedding, but it also matters for bootstrapping. Many
+compiler bootstrap paths start with a small C compiler and eventually have to
+construct a C++ toolchain before they can build the compiler they actually want.
+Kit is implemented in C, including the compiler, assembler, linker, object
+tools, and runtime support, so the bootstrap can go directly from a capable C
+compiler to kit without a C++ stage.
+
+The normal self-host build starts with a host C compiler, uses that kit to build
+kit again, and then repeats the build once more. The second and third `kit`
+binaries must be byte-identical. Replacing the initial host compiler with a
+smaller seed is a separate trust and engineering problem, but it does not
+require ascending from that seed into a C++ compiler first.
+
+## `.kpkg`: content identity plus trust
+
+Software distribution often grows as a collection of conventions: a tarball, a
+checksum file, a detached signature, a package manifest, an update feed, and a
+separate cache format. Kit defines one package and trust model for these pieces.
+
+The bottom layer is the content-addressed store exposed by `kit cas`. A blob is
+identified by the BLAKE2b-256 hash of its bytes. A tree is a canonical manifest
+of paths, modes, sizes, and blob IDs. Blobs and trees are self-verifying, so they
+can be copied from an untrusted cache or mirror.
+
+The package layer adds claims that hashes alone cannot provide: this tree is a
+particular version of a named package, these paths are its executables or
+libraries, and this signer authorizes that manifest. A canonical `kit-package`
+manifest names one or more output trees and their artifact roles.
+Minisign-compatible Ed25519 signatures bind the manifest to a trusted key.
+
+The native `.kpkg` format carries that model in a seekable container. A fat
+package embeds all trees and content; metadata and thin forms can externalize
+content into a CAS without changing the logical package identity. A portable
+`.tar.gz` representation carries the same signed manifest and objects for use
+with ordinary archive tooling.
+
+Hosted SDKs are planned to use this distribution path as well. Packaging SDK
+files as signed `.kpkg` artifacts gives cross-toolchain provisioning the same
+content identity, mirrors, and trust model as other kit artifacts rather than a
+separate SDK mechanism.
+
+The command-line workflow is explicit:
+
+```sh
+kit pkg keygen -o release-key
+kit pkg create --name app --version 1 \
+ -s release-key.key --root out -o app.kpkg
+kit pkg verify -p release-key.pub app.kpkg
+kit pkg unpack --verify -p release-key.pub app.kpkg -C installed
+```
+
+Trust can come from an explicit public key, a managed trusted-key store, or a
+deliberate trust-on-first-use operation. A public key bundled inside a package
+does not become trusted merely because it is present. Content mirrors remain
+untrusted: bytes must match their signed content IDs before use.
+
+Kit uses the same mechanism to distribute itself. `kit update` authenticates a
+signed release-channel index and its selected `.kpkg`, installs the version
+under `KIT_HOME`, and atomically changes the active toolchain. Older versions
+remain available for offline rollback. The package format does not attempt to
+be a dependency solver, and network transport remains driver policy; it defines
+the artifact, identity, and trust boundary.
+
+## `kit build` is a build system
+
+Once artifacts have a standard content identity, the same model can be applied
+to producing them. Putting the compiler and linker in one executable removes
+one layer of toolchain assembly, but it does not answer which commands should
+run, with which inputs, or when their results can be reused.
+
+`kit build` is kit's answer. It is a full content-addressed build system built
+on the CAS and tree model used by `.kpkg`.
+
+A package-local `BUILD.kit` maps target names to recipe executables:
+
+```text
+kit-build 1
+[target app]
+recipe recipes/app.sh
+```
+
+The target can then be requested by label:
+
+```sh
+kit build //:app
+```
+
+A recipe is an ordinary executable, often a shell script. It receives a clean
+environment, writes its result below `KIT_BUILD_OUT`, and asks the coordinator
+for inputs through the recipe protocol. `kit build source`, `glob`, `need`,
+`fetch`, and `config-get` declare source files, filesystem selections, target
+dependencies, hash-pinned downloads, and configuration values. Arguments after
+`--` form local target configuration and participate in the cache key.
+
+The output is a canonical directory tree identified by its BLAKE2b-256 hash. A
+successful build prints both the tree ID and its materialized path. Configuration
+maps, argument vectors, source blobs, dependency closures, and output trees are
+also stored by content identity rather than timestamps.
+
+The cache records two forms of trace. A deep trace is the fast path for the
+ordinary case where none of a target's transitive inputs changed. A shallow
+trace handles the more interesting case where something changed below a target
+but the direct dependency's output did not. If a comment-only edit causes a
+library recipe to run but produces the same library tree, its dependent
+application does not need to relink.
+
+The build system also has workspace packages, canonical target labels,
+configuration profiles, external repositories pinned by content, test targets,
+and explicit dependency requests that can be submitted and awaited separately.
+The build language stays small; complicated policy lives in recipe programs
+rather than in a second general-purpose language embedded in `BUILD.kit`.
+
+There are some deliberate limits. Recipes are responsible for declaring all
+inputs; filesystem hermeticity is not yet enforced. Workspace files are live
+rather than snapshotted during a build, the current hosted scheduler is
+sequential, and build-store garbage collection is not implemented. The cache is
+only as correct as the recipe's declared-input contract.
+
+## Scope
+
+Kit is not intended to hide that it is a relatively small toolchain. `-O1` is
+the current optimizer. Shared-library creation is an ELF feature. WebAssembly
+supports same-invocation source builds and partial WASI, but not general
+separate-object archive linking. Hosted cross targets require their SDKs or
+sysroots. Some debugger and execution paths necessarily depend on the host.
+
+Those boundaries are easier to reason about because the system is coherent. A
+target is described once. An object is represented once. The linker and JIT use
+the same relocation machinery. Builds and packages agree on what a content tree
+is. The command-line tools exercise the same APIs available to an embedder.
+
+BusyBox made a base Unix environment easier to carry by turning many utilities
+into one program. Kit takes the same approach to compiling, linking, building,
+and distributing code.
diff --git a/doc/IR.md b/doc/IR.md
@@ -75,8 +75,9 @@ frontend
|-> direct native target (O0 emit)
|-> direct C-source target (--emit=c)
\-> IR recorder -> CgIrModule (O1, O2-as-O1, interpreter)
- |-> opt: derive Func (CFG/SSA/MIR) -> native emit
- \-> opt: derive Func (reduced) -> interpreter
+ |-> O1: Func CFG/PReg/MIR -> native emit
+ |-> future O2: Func SSA -> O1 backend tail
+ \-> reduced Func -> interpreter
```
`KitCg` lowers the frontend's stack/lvalue source operations into flat
@@ -650,11 +651,13 @@ Two consumers exist today, and they take different paths:
- The optimizer (see [OPT.md](OPT.md)) does not run passes on the CG IR in
place. It converts each `CgIrFunc` into its own `Func` IR
- (`opt_func_from_cg_ir` in src/opt/cg_ir_lower.c), which materializes basic
- blocks, SSA, virtual registers, and frame objects, then runs CFG cleanup,
- simplification, machinization, liveness, register allocation, and emission,
- and finally replays into the wrapped direct backend. This conversion is why
- SSA/phi/const ops live in the optimizer's enum and never in the CG IR.
+ (`opt_func_from_cg_ir` in `src/opt/cg_ir_lower.c`), which materializes basic
+ blocks, pseudo-registers, and frame objects. The current O1 schedule stays in
+ that non-SSA namespace through CFG/local cleanup, machinization, liveness,
+ linear-scan register allocation, and emission before replaying into the
+ wrapped direct backend. The maintained future O2 schedule additionally uses
+ the optimizer-only SSA/phi/value ops; those ops live in the optimizer's enum
+ and never in the CG IR.
- The interpreter (see [INTERPRETER.md](INTERPRETER.md)) also goes through the
optimizer's `Func` form, but via a reduced pipeline (`opt_run_o1_interp` in
diff --git a/doc/LINK.md b/doc/LINK.md
@@ -24,7 +24,7 @@ sysroots) lives entirely in the driver — the library boundary is
byte-buffer-shaped. Every bytes input is read through `Compiler.env->
file_io` by the driver before it reaches the linker.
-For v1, shared-library **creation** is supported only for ELF targets. Mach-O
+Shared-library **creation** is currently supported only for ELF targets. Mach-O
and COFF/PE image and DSO readers still support executable links against
existing dylibs/DLL import surfaces, but the driver rejects non-ELF
`-shared`/`-dynamic` output requests.
diff --git a/doc/OBJ.md b/doc/OBJ.md
@@ -397,5 +397,5 @@ peer writer and the module model hangs off the builder via `OBJ_EXT_WASM` /
- **Stable ids + tombstones.** Segmented storage and `removed` flags let
`strip`/`objcopy` mutate freely without invalidating outstanding handles.
-Planned work (image-inspection extensions, fuller Wasm object support): see
-doc/plan/.
+Planned work (image-inspection extensions and fuller Wasm object support) is
+indexed under [plan/](plan/README.md).
diff --git a/doc/PORT.md b/doc/PORT.md
@@ -17,10 +17,16 @@ Related: [BUILD.md](BUILD.md) (the 3-stage self-build mechanism),
[plan/SYSROOTS.md](plan/SYSROOTS.md) (sysroot provisioning),
[WINDOWS.md](WINDOWS.md).
+Target identity and compiler capability come from the public registry exposed
+by `kit targets`. This document owns a narrower concern: which registered
+profiles have cross/self-host validation lanes, and how those lanes provision
+and execute. `scripts/hosted.sh` is the selector/provisioning authority for that
+test support set, not a second compiler target registry.
+
## Model: two modes over one matrix
```
- support set (one canonical list in scripts/hosted.sh)
+ portability test support set (scripts/hosted.sh)
┌──────────────────────────────────────────────────────┐
mode cross │ host kit builds for T → artifact runs correctly on T │
mode selfhost│ build a kit that runs on T → it builds + runs a program │
@@ -153,15 +159,19 @@ GNU/lld and kit ld take `--gc-sections`, Apple ld (clang on darwin) takes
## Architecture
-### Source of truth — `scripts/hosted.sh`
+### Test-matrix authority — `scripts/hosted.sh`
-Already owns the support set and the `triple`/`path`/`tag` resolvers. Extended
-with:
+The public target registry owns canonical triples, architecture/OS/object
+identity, and compiler capabilities. `scripts/hosted.sh` selects the subset with
+portability lanes and owns their runner/provisioning metadata plus the
+`triple`/`path`/`tag` adapters. It provides:
- `hosted.sh list [selector]` — emit tokens (one per line).
- `hosted.sh expand <selector> [--mode=…]` — the selector grammar above.
-The Makefile reads it via `$(shell …)`; nothing else re-encodes the matrix.
+The Makefile reads it via `$(shell …)`; nothing else re-encodes the test matrix.
+Where a token maps to a compiler profile, its triple and capability must agree
+with `kit targets`; provisioning remains script-owned local state.
### Two orchestrators
diff --git a/doc/README.md b/doc/README.md
@@ -0,0 +1,83 @@
+# Documentation map
+
+The top-level [README](../README.md) is the product overview and quick start.
+This page routes readers to the durable references under `doc/`.
+
+Documentation has three status levels:
+
+- Files directly under `doc/` describe implemented behavior and maintained
+ interfaces.
+- [plan/](plan/README.md) describes forward-looking work. A plan is not a
+ release claim.
+- [ideas/](ideas/README.md) holds speculative designs that are not commitments.
+
+`kit --help`, `kit help COMMAND`, and `kit targets` are the authoritative
+description of the commands and target profiles compiled into a particular
+binary.
+
+## Start here
+
+| Goal | Read |
+|---|---|
+| Understand the motivation and overall shape | [Introducing kit](INTRODUCING_KIT.md) |
+| Understand the architecture and subsystem boundaries | [Design](DESIGN.md) |
+| Use the command-line tools | [Driver](DRIVER.md), then `kit help COMMAND` |
+| Inspect targets and provisioning | [Portability](PORT.md), then `kit targets` |
+| Embed `libkit.a` | [Embedding libkit](EMBEDDING.md), [Interfaces](INTERFACES.md) |
+| Package, authenticate, and install artifacts | [Code distribution](DISTRIBUTE.md), [Release/update](RELEASE.md) |
+| Define content-addressed builds | [Build coordinator](BUILD_COORDINATOR.md) |
+| Build and test kit itself | [Build](BUILD.md), [Testing](TESTING.md) |
+| Measure performance or component size | [Benchmarking](BENCHMARKING.md), [Code size](CODE_SIZE.md) |
+
+## Compiler and language pipeline
+
+- [Frontends](FRONTENDS.md) describes frontend registration and the C, cpp,
+ Wasm/WAT, and internal Toy frontends.
+- [Code generation](CODEGEN.md) describes the public `KitCg` API and the direct
+ versus recorded lowering paths.
+- [IR](IR.md) defines the recorded semantic IR.
+- [Optimizer](OPT.md) distinguishes the current no-SSA `-O1` pipeline from the
+ maintained but not-yet-enabled SSA `-O2` schedule.
+- [Architecture backends](ARCH.md) covers target dispatch, native backends,
+ instruction emission, and ABI seams.
+- [Assembler](ASM.md) covers standalone and inline assembly.
+- [Grammar generator](GRAM.md) covers the EBNF compiler and generated
+ lexer/parser runtimes.
+- [Portable C backend](CBACKEND.md) and [WebAssembly](WASM.md) cover the
+ source-like output backends.
+- [Interpreter](INTERPRETER.md) covers `run --no-jit`.
+
+## Objects, linking, execution, and debugging
+
+- [Object model](OBJ.md) covers ELF, Mach-O, COFF/PE, and Wasm objects behind
+ the format-neutral builder and reader APIs.
+- [Linker](LINK.md) covers resolution, layout, relocation, linker scripts, and
+ JIT image creation.
+- [JIT](JIT.md) covers executable-memory publication and symbol lookup.
+- [DWARF](DWARF.md), [Debugger](DBG.md), and [Kernel/image support](KERNEL.md)
+ cover debug information, interactive execution, and freestanding images.
+- [Emulator](EMU.md) documents the guest-ELF API and development command. The
+ command is not part of the public inventory.
+
+## Runtime, hosts, and portability
+
+- [Runtime](RUNTIME.md) describes the freestanding headers and support library.
+- [OS interfaces](INTERFACES.md) inventories the public and internal boundaries
+ through which hosts, frontends, and backends interact.
+- [Portability](PORT.md) owns the cross/self-host test matrix and provisioning
+ substrates; the public target registry owns target identity and capability.
+- [Windows](WINDOWS.md) records Windows-specific hosting and self-host details.
+
+## Project maintenance
+
+- [Build](BUILD.md) covers make products, component gates, reproducibility, and
+ the three-stage fixed-point bootstrap.
+- [Testing](TESTING.md) is the test-suite and harness reference.
+- [Benchmarking](BENCHMARKING.md) defines reproducible compile-speed and
+ generated-code-size measurements.
+- [Release/update](RELEASE.md) documents versioning, signed artifacts, channel
+ indexes, installation, rollback, and key rotation.
+
+The historical black-box release audit is retained as evidence, not as current
+product documentation. Its baseline findings must not be used as descriptions
+of the current binary.
diff --git a/doc/RELEASE.md b/doc/RELEASE.md
@@ -58,8 +58,12 @@ build/dist/
```
The staging tree is `bin/kit`, `lib/libkit.a`, `include/`,
-`support/rt/{include,lib}/`, `VERSION`, and README/license. The target requires
-`KIT_SIGN_KEY=<path>`, `KIT_RELEASE_PUBKEYS=<path...>`, and
+`support/rt/{include,lib}/`, `doc/`, `VERSION`, and README/license. The
+documentation tree includes the maintained references plus the explicitly
+forward-looking `plan/` and `ideas/` indexes; the historical release audit is
+not shipped. The overview is `README.md`. The target requires
+`KIT_SIGN_KEY=<path>`,
+`KIT_RELEASE_PUBKEYS=<path...>`, and
`KIT_UPDATE_INDEX_URL=<stable-url>`. It rejects the in-tree **NON-RELEASE** test
key unless a hermetic harness explicitly sets `KIT_RELEASE_ALLOW_TEST_KEY=1`.
For a local packaging smoke test, `make dist-dev` invokes `make dist` with the
@@ -95,7 +99,7 @@ stock-`minisign`-compatible signature.
## Channel index and hosting
-Each channel (`stable` for v1) is described by a small signed, byte-stable text
+Each channel (normally `stable`) is described by a small signed, byte-stable text
file, `kit-release 1`, emitted/parsed by libkit (`src/dist/release.c`,
`kit_release_index_*`):
@@ -168,7 +172,8 @@ prior one is an instant **offline** flip.
`kit install DIR [TOOL...]` is the standalone link-layout tool for an existing
binary. With no explicit tools it installs the default drop-in compiler/binutils
and standard byte-utility names. `kit install --all` installs every public tool
-compiled into the binary, while internal v1 tools such as `emu` are excluded.
+compiled into the public registry, while development tools such as `emu` are
+excluded.
`kit update` uses the same link writer after installing or flipping a version, so
`$KIT_HOME/bin` and an explicit `kit install` directory expose the same public
tool names for the selected mode.
@@ -204,7 +209,8 @@ re-acquire or use the OS package manager.
## macOS Gatekeeper
-A downloaded Mach-O is quarantined; v1 ships without Apple notarization, so
+A downloaded Mach-O is quarantined; current releases ship without Apple
+notarization, so
remove the quarantine flag once:
```
diff --git a/doc/RUNTIME.md b/doc/RUNTIME.md
@@ -117,9 +117,9 @@ native instruction.
`__atomic_*_N` fallbacks for objects the backend cannot lower to a native
atomic instruction. A pointer-sized `_Atomic(uintptr_t)` spinlock pool
(`atomic_common.inc`) provides the lock, hashed by address — no OS dependency.
- Implemented over the GCC-style `__atomic_*` builtin family that kit itself
- documents (`doc/builtins.md`), with upstream's Clang-only `__c11_atomic_*`
- calls translated. 16-byte cases are keyed off `HAS_INT128`. On 32-bit targets
+ Implemented over the GCC-style `__atomic_*` builtin family accepted by kit,
+ with upstream's Clang-only `__c11_atomic_*` calls translated. 16-byte cases
+ are keyed off `HAS_INT128`. On 32-bit targets
(rv32 `ilp32`/`ilp32f`) the ISA has no 64-bit atomic (`lr.d`/`sc.d`/`amo*.d`
are rv64-only), so 8-byte `_Atomic` / `__atomic_*` lower to the `__atomic_*_8`
entries here — spinlock-backed, correct but **not** lock-free; the front end's
diff --git a/doc/TESTING.md b/doc/TESTING.md
@@ -128,7 +128,7 @@ stdout, and an optional `<name>.expected` oracle). This is the end-to-end "it
runs the same" signal, tolerant of benign encoding differences L1 would flag.
Crucially, **no qemu is needed for the host arch**: execution goes through the
in-process JIT (`kit run` / the `jit-runner`). Developer lanes may also use the
-internal emulator (`kit emu`, not v1 public surface; see [EMU.md](EMU.md)), but
+development emulator command (`kit emu`; see [EMU.md](EMU.md)), but
L2 runs only when the target arch matches the host (native JIT); otherwise it
self-skips.
@@ -498,4 +498,4 @@ Conventions shared across all four test types:
`<name>.skip`, `<name>.objdump`, the `err/` cases), so adding or quarantining a
case is a data change, not a script edit.
-Planned work: see doc/plan/.
+Planned work is indexed under [plan/](plan/README.md).
diff --git a/doc/WASM.md b/doc/WASM.md
@@ -28,10 +28,10 @@ module model serves both:
Neither direction builds a private reader or writer: both go through the one
`src/wasm` layer. That non-duplication is the central design constraint.
-## V1 support boundary
+## Current support boundary
The shipped target boundary is intentionally narrow. `wasm32` is the only Wasm
-output target for v1. `wasm64` remains a reserved triple/ISA spelling so the
+output target today. `wasm64` remains a reserved triple/ISA spelling so the
parser can name it, but target construction rejects it with an explicit
unsupported diagnostic.
@@ -45,7 +45,7 @@ WASI implementation.
For C-to-Wasm output, same-invocation multi-source `wasm32` is supported through
the source-batch path (`build-obj -target wasm32-none ...` or
`build-exe -target wasm32-none ...`). Those sources are merged before the final
-module is emitted. Separate-object/static Wasm linking is not supported in v1:
+module is emitted. Separate-object/static Wasm linking is not currently supported:
`build-exe -target wasm32-none` rejects `.o`, `.a`, `-l`, DSO, and framework
inputs, and `emit_wasm` does not create relocatable Wasm objects with
`linking`/`reloc.*` metadata.
diff --git a/driver/cmd/build_coord.c b/driver/cmd/build_coord.c
@@ -60,10 +60,16 @@ void driver_help_build(void) {
"USAGE\n"
" kit build [--store DIR] [--root DIR] [--def FILE] [--profile NAME]\n"
" [--config K=V|env.NAME]... [--env NAME[=V]]...\n"
- " [--verify] [--stats] TARGET [-- ARG...]\n"
+ " [--verify] [--stats] [--trace] TARGET [-- ARG...]\n"
" kit build test [--store DIR] [--root DIR] [--def FILE] [--profile NAME]\n"
" [--config K=V|env.NAME]... [--env NAME[=V]]...\n"
- " [--verify] [--stats] TARGET [-- ARG...]\n"
+ " [--verify] [--stats] [--trace] TARGET [-- ARG...]\n"
+ " kit build [--root DIR] [--def FILE] list [--scan-do] [//PACKAGE[/...]]\n"
+ " kit build [--root DIR] repo add NAME URL\n"
+ " [--format tar.gz|kpkg] [--strip-prefix DIR]\n"
+ " kit build [--root DIR] repo fetch NAME\n"
+ " kit build [--root DIR] repo list\n"
+ " kit build [--root DIR] workspace package [--format tar.gz] -o OUT\n"
" kit build config-get [--default VALUE] KEY # inside a build recipe\n"
" kit build source [--optional] [--format path|id|id-path] PATH\n"
" # inside a build recipe\n"
@@ -71,6 +77,9 @@ void driver_help_build(void) {
" # inside a build recipe\n"
" kit build depfile [--lines] FILE # inside a build recipe\n"
" kit build glob PATTERN # inside a build recipe\n"
+ " kit build export-set VAR -- VALUE... # inside a build recipe\n"
+ " kit build export-get TARGET VAR # inside a build recipe\n"
+ " kit build export-collect VAR TARGET... # inside a build recipe\n"
" kit build need [--format path|id|id-path]\n"
" [--config K=V|env.NAME]... [--env NAME[=V]]...\n"
" TARGET [-- ARG...]\n"
@@ -94,7 +103,8 @@ void driver_help_build(void) {
" traces. Package paths are resolved relative to --root; recipes and\n"
" source paths are package-relative. Arguments after -- participate in\n"
" the target key and are available to the recipe protocol.\n"
- "\n"
+ "\n");
+ driver_printf(
"RECIPE PROTOCOL\n"
" A recipe is an executable that writes its output tree below\n"
" $KIT_BUILD_OUT. It receives a clean environment containing\n"
@@ -102,16 +112,30 @@ void driver_help_build(void) {
" KIT_BUILD_PACKAGE, and KIT_BUILD_LOCAL, plus values explicitly\n"
" propagated with --env/--config env.NAME.\n"
"\n"
- " Recipe-only `source` records a source dependency and prints its CAS\n"
- " materialization path or requested id form. `need` records another\n"
+ " Recipe-only `source` records a source dependency and prints its\n"
+ " workspace path or requested id form. `need` records another\n"
" target dependency; need-submit/need-await permit parallel requests.\n"
" config-get, fetch, depfile, and glob also require KIT_BUILD_SOCK and\n"
- " are rejected outside a running recipe.\n"
+ " are rejected outside a running recipe. export-set publishes ordered\n"
+ " metadata in the output tree; export-get/collect read it through need\n"
+ " dependencies. Use `kit build --client VERB ...` to select recipe\n"
+ " client mode explicitly.\n"
+ "\n"
+ "WORKSPACE COMMANDS\n"
+ " list prints targets in one package; a trailing /... scans packages\n"
+ " recursively. --scan-do lists Redo-style do/*.do rules instead. repo\n"
+ " add hashes a local path or file:// archive and records the pinned\n"
+ " entry in WORKSPACE.kit. repo fetch validates that a configured name\n"
+ " exists; external content is fetched and materialized when its label is\n"
+ " resolved. repo list prints the configured names, formats, and ids.\n"
+ " workspace package writes the workspace as a tar.gz using the hosted\n"
+ " system tar. Signed kpkg creation is provided by `kit pkg create`.\n"
"\n"
"OPTIONS\n"
" --store DIR Build store root (default: Kit platform cache/build)\n"
" --root DIR Workspace root (default: .)\n"
- " --def FILE Package build-file basename (default: WORKSPACE def-name or BUILD.kit)\n"
+ " --def FILE Package build-file basename (alias: --def-name;\n"
+ " default: WORKSPACE def-name or BUILD.kit)\n"
" --profile NAME Apply WORKSPACE.kit [config NAME] after [config default]\n"
" --config K=V Seed propagated configuration\n"
" --config env.N Seed env.N from current $N\n"
diff --git a/mk/dist.mk b/mk/dist.mk
@@ -56,7 +56,8 @@ dist:
cp -r rt/include $(DIST_STAGING)/support/rt/include
cp -r rt/lib $(DIST_STAGING)/support/rt/lib
cp VERSION $(DIST_STAGING)/VERSION
- @cp README.md $(DIST_STAGING)/README.txt 2>/dev/null || true
+ cp README.md $(DIST_STAGING)/README.md
+ @sh scripts/stage_docs.sh . $(DIST_STAGING)/doc
@for f in LICENSE LICENSE.txt LICENSE.md NOTICE NOTICE.txt; do \
[ -f "$$f" ] && cp "$$f" "$(DIST_STAGING)/$$f"; done; true
$(DIST_REL_BIN) pkg create --name kit --version $(KIT_VERSION) \
diff --git a/scripts/release.sh b/scripts/release.sh
@@ -289,7 +289,8 @@ EOF
cp -r "$ROOT/rt/lib" "$stage/support/rt/lib"
cp "$ROOT/VERSION" "$stage/VERSION"
cp "$rt_archive" "$stage/support/rt/lib/libkit_rt-$rt_variant.a"
- cp "$ROOT/README.md" "$stage/README.txt" 2>/dev/null || true
+ cp "$ROOT/README.md" "$stage/README.md"
+ sh "$ROOT/scripts/stage_docs.sh" "$ROOT" "$stage/doc"
local f
for f in LICENSE LICENSE.txt LICENSE.md NOTICE NOTICE.txt; do
[ -f "$ROOT/$f" ] && cp "$ROOT/$f" "$stage/$f"
diff --git a/scripts/stage_docs.sh b/scripts/stage_docs.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+# Stage the maintained documentation tree beside README.md in a release.
+
+set -eu
+
+if [ "$#" -ne 2 ]; then
+ echo "usage: $0 ROOT DEST" >&2
+ exit 2
+fi
+
+root=$1
+dest=$2
+
+for file in README.md DESIGN.md DRIVER.md PORT.md EMBEDDING.md \
+ DISTRIBUTE.md RELEASE.md BUILD_COORDINATOR.md; do
+ if [ ! -f "$root/doc/$file" ]; then
+ echo "stage_docs: missing doc/$file" >&2
+ exit 1
+ fi
+done
+
+mkdir -p "$dest" "$dest/plan" "$dest/ideas"
+
+for src in "$root"/doc/*.md; do
+ case ${src##*/} in
+ RELEASE_AUDIT_*) continue ;;
+ esac
+ cp "$src" "$dest/${src##*/}"
+done
+
+cp "$root"/doc/plan/*.md "$dest/plan/"
+cp "$root"/doc/ideas/*.md "$dest/ideas/"