kit

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

commit 3142c122a8d1a3ed829736bc52450b470a66c452
parent 36ae51be96a81e40ad3b4235fec8ee1fc3895195
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Tue, 16 Jun 2026 16:48:31 -0700

Merge root TODO.md into doc/plan/TODO.md

Fold the Round-6 cleanup/symmetry backlog (container _reserve symmetry,
linker symbol-map pre-sizing, obj-emitter de-triplication, assembler
sym-minus-sym differences) into the single deferred-fixes catalog and
drop the duplicate root file.

Diffstat:
DTODO.md | 59-----------------------------------------------------------
Mdoc/plan/TODO.md | 41+++++++++++++++++++++++++++++++++++++++++
2 files changed, 41 insertions(+), 59 deletions(-)

diff --git a/TODO.md b/TODO.md @@ -1,59 +0,0 @@ -# TODO - -Cleanup / symmetry items noticed during the Round-6 perf work. None are -blocking; recorded so they aren't lost. (Forward-looking *perf levers* — -copy-and-patch codegen, 16B `Tok`, the `writev` object-output micro-lever — -live in `doc/plan/PERF.md`, not here.) - -## Container facility symmetry - -- **`KIT_HASHSET_DEFINE` lacks `_reserve`.** Round-6 added `NAME##_reserve(m, n)` - to `KIT_HASHMAP_DEFINE` (`include/kit/support/hashmap.h`) so a bulk insert with - a known count skips the resize cascade. The hashset variant in the same file - was not given the matching primitive. Mirror it (same body: grow `cap` to hold - `n` at the load factor, power-of-two) if/when a set needs it — don't ship it - unused. - -- **`SegVec` has no `_reserve`.** The object readers now pre-size the - `SymNameIndex` hashmap (`obj_reserve_symbols`), but the parallel `Symbols` - (src/obj) / `LinkSyms` (src/link) segvecs still grow one 64-entry segment at a - time — ~16k small allocations for a 1M-symbol object. A `SEGVEC` reserve - (pre-allocate ⌈n/seg⌉ segments) would cut that alloc churn on large ingests. - Touch points: `src/core/segvec.h`, the readers in `src/obj/*/read.c`, and - `link_resolve_symbols`. - -## Linker symbol-map pre-sizing (partial) - -- Only `img->globals` got `symhash_reserve` (`link_resolve.c`). The other - `symhash_init`-without-capacity maps — `alias_map` (`link_resolve.c:~401`), - `defined`/`undefs` (`link_resolve.c:~1139`), `globals_by_name` - (`link_relocatable.c:~451`) — could pre-size from a known count for - consistency. Lower value (the measured resize churn was `img->globals` + the - reader `SymNameIndex`); do it if a profile shows them. - -## Object-emitter de-duplication (macho / elf / coff) - -- The three `src/obj/*/emit.c` carry near-identical code: the `strtab_add` - linear-dedup (flatten-to-search), the final strtab flatten+write, and the - section-bytes write loop. A small shared `src/obj` helper would de-triplicate - them. NB: streaming each section's `Buf` chunks instead of flatten-to-one - `write()` was tried and is *slower* (more syscalls) — keep the single big - write; only the dedup is wanted here. - -## Assembler: symbol-minus-symbol differences - -- **`.quad _end - _start` is rejected** by kit's own assembler with - `asm: cannot subtract symbol from constant` (`src/asm/asm.c` `parse_add`, - ~line 391). Only `sym - constant` and `sym - .` (PC-relative) are handled; - a `sym1 - sym2` difference (a link-time-resolvable constant when both are in - one section, or a relocation pair otherwise) is not. GNU as supports it. This - hides on hosts where the only path that assembles such sources is clang: e.g. - `test/link/cases/35_linker_script_kernel/entry.aa64.S` uses - `.quad _end - _start` for its Image-header `image_size`, but that fixture's - R-lane assembles with clang and its kit-assembled E-lane is qemu-gated (skipped - on macOS). It surfaces the moment kit's assembler is driven directly - (`kit build-exe`/`kit as`) on such a source — notably an author-written flat - kernel `Image` header that computes `image_size = _end - _start` (see - doc/plan/KERNEL.md). Fix in `parse_add`: when both operands carry a symbol, - record a symbol-difference expression and lower it to a constant (same section) - or a relocation pair, rather than panicking. diff --git a/doc/plan/TODO.md b/doc/plan/TODO.md @@ -85,6 +85,22 @@ Add new deferred fixes below as they are discovered. the existing scratch between mem-staging and operand-staging — a register-policy decision, hence "reviewed change." +- **Assembler rejects symbol-minus-symbol differences (`.quad _end - _start`).** + kit's own assembler panics with `asm: cannot subtract symbol from constant` + (`src/asm/asm.c` `parse_add`, ~line 391). Only `sym - constant` and `sym - .` + (PC-relative) are handled; a `sym1 - sym2` difference (a link-time-resolvable + constant when both are in one section, or a relocation pair otherwise) is not. + GNU as supports it. This hides on hosts where the only path that assembles such + sources is clang: e.g. `test/link/cases/35_linker_script_kernel/entry.aa64.S` + uses `.quad _end - _start` for its Image-header `image_size`, but that fixture's + R-lane assembles with clang and its kit-assembled E-lane is qemu-gated (skipped + on macOS). It surfaces the moment kit's assembler is driven directly + (`kit build-exe`/`kit as`) on such a source — notably an author-written flat + kernel `Image` header that computes `image_size = _end - _start` (see + doc/plan/KERNEL.md). Fix in `parse_add`: when both operands carry a symbol, + record a symbol-difference expression and lower it to a constant (same section) + or a relocation pair, rather than panicking. + ## Deferred dedups & abstraction cleanups ("use the shared seam") - **A.2 — optimizer-path inline-asm dedup.** The three `aa_/x64_/rv_asm_block_native` @@ -122,6 +138,31 @@ Add new deferred fixes below as they are discovered. the generic `(Operand*, is_def)` callback without losing information. (`addr_cse_apply_to_inst` and the SSA use-rewrite `reg_replace_inst_uses` now route through the central walk; `opt_hard_inst_use_def` stays intentionally bespoke per its hardcoded opcode dispatch.) +- **Container-facility symmetry (Round-6 follow-ups).** Mirror the bulk-insert + `_reserve` primitive where the matching container still grows incrementally: + - `KIT_HASHSET_DEFINE` lacks `_reserve`. Round-6 added `NAME##_reserve(m, n)` to + `KIT_HASHMAP_DEFINE` (`include/kit/support/hashmap.h`) so a bulk insert with a + known count skips the resize cascade; the hashset variant in the same file was + not given the matching primitive. Mirror it (same body: grow `cap` to hold `n` + at the load factor, power-of-two) if/when a set needs it — don't ship it unused. + - `SegVec` has no `_reserve`. The object readers now pre-size the `SymNameIndex` + hashmap (`obj_reserve_symbols`), but the parallel `Symbols` (src/obj) / + `LinkSyms` (src/link) segvecs still grow one 64-entry segment at a time — ~16k + small allocations for a 1M-symbol object. A `SEGVEC` reserve (pre-allocate + ⌈n/seg⌉ segments) would cut that alloc churn on large ingests. Touch points: + `src/core/segvec.h`, the readers in `src/obj/*/read.c`, and `link_resolve_symbols`. +- **Linker symbol-map pre-sizing (partial).** Only `img->globals` got + `symhash_reserve` (`link_resolve.c`). The other `symhash_init`-without-capacity + maps — `alias_map` (`link_resolve.c:~401`), `defined`/`undefs` + (`link_resolve.c:~1139`), `globals_by_name` (`link_relocatable.c:~451`) — could + pre-size from a known count for consistency. Lower value (the measured resize churn + was `img->globals` + the reader `SymNameIndex`); do it if a profile shows them. +- **Object-emitter de-duplication (macho / elf / coff).** The three + `src/obj/*/emit.c` carry near-identical code: the `strtab_add` linear-dedup + (flatten-to-search), the final strtab flatten+write, and the section-bytes write + loop. A small shared `src/obj` helper would de-triplicate them. NB: streaming each + section's `Buf` chunks instead of flatten-to-one `write()` was tried and is + *slower* (more syscalls) — keep the single big write; only the dedup is wanted here. ## God-function decompositions (highest risk / lowest ROI — do when next touching)