kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit aa58c8dc227553adba1fef5fc3553e1c37a1fb09
parent 56198fafd1ed82cecb144b87171f9b88a6ad66b0
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Fri,  8 May 2026 17:23:42 -0700

DESIGN.md update

Diffstat:
Mdoc/DESIGN.md | 36+++++++++++++++++++++++++++---------
1 file changed, 27 insertions(+), 9 deletions(-)

diff --git a/doc/DESIGN.md b/doc/DESIGN.md @@ -359,6 +359,18 @@ or already-built `ObjBuilder*` (`link_add_obj`). Path-shaped inputs are a driver-level concern: the driver calls `c->env->file_io->read_all`, then feeds the bytes APIs. +**Incremental-linking forward compat.** The single-shot `link_resolve` +implementation must not destroy or consume input-side state that a future +incremental re-resolve would need. `LinkRelocApply` records stay as data +(they are not burned into segment bytes destructively without preserving the +originals); `LinkInputId → ObjBuilder*` mappings stay stable for the +lifetime of the `Linker`; resolution is a function from inputs to a fresh +`LinkImage`, not in-place mutation of the `Linker`. Incremental linking is +the single most likely future addition, and the existing surface +(`LinkInputId` stable handles, separable `LinkImage`, byte/`ObjBuilder` +inputs) is already amenable — this discipline keeps it amenable without +adding a speculative API. + ### 5.6 `MemAccess` — explicit memory semantics `MemAccess` is attached to every typed memory operation (`load`, `store`, @@ -572,9 +584,10 @@ operation (signed overflow, shift-by-≥-width, division by zero, null deref) is unreachable. WASM traps deterministically on the first three and faults on the fourth — the program terminates rather than time-traveling. Real-target behavior is also more predictable this way. The "70% of -O2" goal is -achievable without these rules; reserved bits in `Inst.flags` can host -`nsw`/`nuw`-style annotations later if a specific non-UB-exploiting pass -needs them. +achievable without these rules. `Inst.flags` is general-purpose; no specific +bit allocations are reserved. If a non-UB-exploiting pass that benefits from +operation-level annotations arrives later, the path is to thread a flags +argument through `CGTarget.binop` and into `IR_*` then — not before. ### 9.1 Lifecycle @@ -617,7 +630,8 @@ not in the IR arena. ``` build_cfg block_cloning (hot path duplication; skipped if it would block addr_xform) -build_ssa +build_ssa (incl. promotion of non-address-taken FrameSlots — + mem2reg is folded in, not a separate pass) addr_xform (fold GEP-equivalent address insns into uses) gvn (incl. constprop, redundant-load elimination) copy_prop (incl. redundant-extension elimination) @@ -760,11 +774,15 @@ equal types thanks to `Pool global`). diagnostics, DWARF, and dependency generation. - **Locals and parameters always start frame-resident.** `cg_local` and `cg_param` allocate stable `FrameSlot`s through `CGTarget.frame_slot` and - `CGTarget.param`. A mem2reg-style pass during opt's lowering pipeline - promotes non-address-taken slots to virtual registers (and to WASM-locals on - that target). At -O0 every slot stays on the frame, which is the same shape - `Debug` wants for `DVL_FRAME` (§11) — full debuggability for free, no parser - pre-scan needed. + `CGTarget.param`. Promotion to virtual registers (and to WASM-locals on + that target) happens *inside* SSA construction: `build_ssa` (§9.2) promotes + any slot whose `FrameSlotFlag` never had `FSF_ADDR_TAKEN` set. Address- + taken slots remain as memory ops and are reasoned about through `MemAccess` + alias roots. There is no separate mem2reg pass — SSA construction already + has to decide which `FrameSlot` accesses become Phi chains vs which stay + loads/stores, and a second pass would re-walk the same decisions. At -O0 + every slot stays on the frame, which is the same shape `Debug` wants for + `DVL_FRAME` (§11) — full debuggability for free, no parser pre-scan needed. - **Function-pointer ABI is a linker concern.** A function symbol's address taken via `&f` lowers to a normal `ObjSymId`-relative `Operand`. ELF/COFF/Mach-O resolve this directly. WASM file emitters and the JIT linker