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:
| D | TODO.md | | | 59 | ----------------------------------------------------------- |
| M | doc/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)