kit — deferred fixes & code-smell backlog
This file is an open-backlog catalog, not a completion ledger. When an item is fixed, remove it instead of checking it off or keeping a closed entry.
Add new deferred fixes below as they are discovered.
Known bugs / correctness gaps
-ftrivial-auto-var-init=patterninkit cc.=zeroand=uninitializedare implemented: the C frontend zero-inits every automatic variable that has no explicit initializer (KitCodeOptions.trivial_auto_var_init, threaded throughparse_c→parse_init_declarator→zero_init_at), and the mk/flags.mkAUTO_INIT_CFLAGSprobe now passes under$(CC)=kit cc, so bootstrap stages get the same hardening (closing the gap that leftmake bootstrap-*exposed to the latent uninit-read flake).=patternis parsed but rejected as unsupported — implementing it needs a non-zero byte-fill for every scalar leaf (including the FP bit pattern), i.e. generalizingzero_init_atto a fill value. Lower priority: the hardening uses=zero.
Deferred dedups & abstraction cleanups ("use the shared seam")
- E.3 — OS-neutral env code duplicated between
driver/env/posix.candwindows.c(stdio writer + thunks,env→{context,jit_host,dbg_host}trio, dir-handle structs + read/close,read_stdingrow/shrink). Move todriver/env/common.c. Blocked on a Windows cross-build to verifywindows.cdoesn't break (it can't be host-compiled). - E.5 — cc/build glue. basename-stem+extension synthesis is triplicated
(
cc_default_obj_path_for_name,cc_dep_default_target,build_default_obj_name); its home is the driver util layer (driver/), notlink_inputs.c. (The link pipeline + flag-parse blocks were assessed and are not byte-identical — different option structs.) - I.2 — two parallel C-6.7.9 initializer walkers (
init_atruntime ~648-777;parse_static_init_atstatic ~1419-1612 inlang/c/parse/parse_init.c) share the array/struct/union/scalar traversal grammar (and already shareparse_designator_chain/designator_continues_inside) but diverge at load-bearing points that make a naive merge a §6.7.9 miscompile risk: (1) GAP FILL — runtime emits explicit zero-stores for array/designator gaps + unwritten struct fields (zero_init_at/zero_object_bytes_at), static relies on the pre-zeroed output buffer and emits nothing; (2) a static-only compound-literal cast-strip prologue; (3) struct iteration (runtime delegates to the sharedinit_struct_fields, static inlines its own field loop); (4) the value leaves differ (parse_assign_expr+pcg_storevsparse_static_const+encode;init_string_atvsparse_static_string_at; bitfield leaves). A real unification needs a grammar driver- a leaf vtable {scalar, string, bitfield, gap-fill, context=slot|buf}; treat it as its own heavily-tested change, not an opportunistic dedup.
- I.4 — two opt walks still hand-roll operand iteration that the central
opt_walk_inst_operandscannot express.reg_define_inst_defs(pass_ssa) needs a per-def index + version-stack (pushed) context, andopt_collect_inst_uses(pass_analysis) needs the operand index + IR_PHI pred-value handling — neither fits the generic(Operand*, is_def)callback without losing information. (addr_cse_apply_to_instand the SSA use-rewritereg_replace_inst_usesnow route through the central walk;opt_hard_inst_use_defstays intentionally bespoke per its hardcoded opcode dispatch.) - Container-facility symmetry (Round-6 follow-ups). Mirror the bulk-insert
_reserveprimitive where the matching container still grows incrementally:KIT_HASHSET_DEFINElacks_reserve. Round-6 addedNAME##_reserve(m, n)toKIT_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: growcapto holdnat the load factor, power-of-two) if/when a set needs it — don't ship it unused.SegVechas no_reserve. The object readers now pre-size theSymNameIndexhashmap (obj_reserve_symbols), but the parallelSymbols(src/obj) /LinkSyms(src/link) segvecs still grow one 64-entry segment at a time — ~16k small allocations for a 1M-symbol object. ASEGVECreserve (pre-allocate ⌈n/seg⌉ segments) would cut that alloc churn on large ingests. Touch points:src/core/segvec.h, the readers insrc/obj/*/read.c, andlink_resolve_symbols.
- Linker symbol-map pre-sizing (partial). Only
img->globalsgotsymhash_reserve(link_resolve.c). The othersymhash_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 wasimg->globals+ the readerSymNameIndex); do it if a profile shows them. - Object-emitter de-duplication (macho / elf / coff). The three
src/obj/*/emit.ccarry near-identical code: thestrtab_addlinear-dedup (flatten-to-search), the final strtab flatten+write, and the section-bytes write loop. A small sharedsrc/objhelper would de-triplicate them. NB: streaming each section'sBufchunks instead of flatten-to-onewrite()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)
link_emit_elf(src/obj/elf/link.c, ~940 lines, 14 phases incl. inline PIE dynamic-emit that is logically the emit-half oflayout_dyn).- Mach-O
plan_layout(src/obj/macho/link.c, ~574 lines; inlinesizeofcmdsprediction ~1500 lines from the actual emit — a drift hazard). jit_append_obj_inner(src/link/link_jit.c, ~482 lines reimplementing the AOT pipeline; had a verbatim-duplicated duplicate-global check).wasm_emit_cg_into(lang/wasm/cg.c, ~1960 lines fusing module setup with a 174-case opcode switch). (WasmCgControlis now hoisted to file scope; the module-setup/opcode-switch split remains.)c_emit_data_symbol(src/arch/c_target/c_emit.c, ~306 lines; doubled reloc-walk).
Deferred subsystem work (folded from retired plan docs)
Terse backlog rescued from plan docs that were deleted once their shipped design
moved up to the design set. Fuller context for each is in git history (the named
doc at HEAD~).
DataLayout-backed CG IR
- Add a
DataLayoutabstraction and delay aggregate address lowering in the existing CG IR. The IR should remain associated with a selected target data layout, as LLVM IR is, rather than become fully target-agnostic or gain another IR layer. Todaykit_cg_fieldbecomes a byte displacement andkit_cg_elembecomes a concrete byte stride before the recorder/backend sees them. Preserve record + field identity and element type/scale as GEP-like symbolic IR operations, then have each backend query the module'sDataLayoutfor concrete offsets and strides. MakeDataLayoutthe single authority for pointer/scalar sizes, alignment, record and bit-field layout, and endianness. This deliberately delays layout commitment without promising that an already-produced module can be safely retargeted to an incompatible ABI.
Arch-backend parity — x64/rv64 vs the aa64 reference (was ARCH.md)
- x64/rv64 tail-call realization.
x64_no_tail/rv_no_tailstill bail onframe.ncallee_saves != 0; aa64 gates on the outgoing-stack-arg size check alone. The restore-before-jump machinery (x64_emit_tail_site/rv_emit_tail_site) already exists — remove the callee-saves guard so it runs, add callee-saves-live tail-call corpus cases, and validate Win64 callee-save XMMs + forwarded sret and the rv64 s2–s11/fs2–fs11/s0/ra restore-then-jr. - Cost-model alignment. As the tail paths land, verify the optimizer's
per-call cost estimates (
signature_stack_bytes/call_stack_bytes) reflect the cheaper known-frame shapes. Also:cleanup_layout_fallthrough_branchesdoesn't yet threadb A; A: b Bchains (arch-shared optimizer pass fix). - x64 debugger step-out / unwind.
kit_dwarf_unwind_stephas no memory provider and x64 has no link register, so step-out can't recover the return address; also populate.eh_frame(or equivalent CFI) for JIT in-process images. - Niche
as/ inline-asm()encode-decode gaps (blocks no build): aa64CASP, LSE min/max (ldsmax/ldsmin/ldumax/ldumin),LDAPR/STLLRnot encoded; disasm rows missing for the new encode-only exclusive/LSE/reg-offset/ writeback forms (render as.inst); TLS reloc modifiers:tprel_*:(aa64) /%tls_*(rv64) not accepted in operands;.L-prefixed local labels in operand references.
Wasm object backend + linker (was WASM.md)
- Object backend (largest gap):
src/obj/wasmlacks relocatable-object + linker-metadata support at ELF/Mach-O/COFF parity. - Static linker: no separate-object/static Wasm linker —
kit_link_exealways builds a nativeLinker. Same-invocation source batches are merged before final module emission; independently emitted Wasm objects still need linker metadata + relocation apply. - Runtime helpers in final modules: an undefined helper call currently
becomes a host import, so non-trivial fallbacks such as 64-bit multiply-high
are expanded at every use site. Short term, intern private module-local
helpers and emit each body once (keeping cheap operations inline); then teach
the source-batch path to include the
wasm32runtime sources. Once relocatable Wasm linking lands, resolve these calls normally fromlibkit_rt.a. - Feature gaps: atomics, wrapper ABI; frontend lowering beyond the staged MVP; validator diagnostics for unsupported proposals.
- wasm64 + WASI: wasm64 is a reserved spelling rejected by target
construction, and WASI remains partial until the wasm32 object/link path
grows. Cleanup: move the shared Wasm core
lang/wasm/→src/wasm/.
Windows x64 self-host + bootstrap (was windows.md)
- x64 self-host
kit.execrashes (0xC0000005) on most subcommands (nm/size/cpp/as); aarch64-windows self-host works (design in../WINDOWS.md). Related: x64*srettail-call crash at-O1,118_decl_extra_attrsADRP-range link issue. - Open: a committed compile-on-VM test lane, default sysroot/distribution,
the Windows 3-stage bootstrap, and the SEH fault-guard
(
driver_run_with_crash_guardis a no-op on Windows — a crashingkit runtakes downkit.exe).
Bootstrap breadth (was BOOTSTRAP.md; fixed point + triage playbook now in ../BUILD.md)
- Widen the 3-stage byte-identical self-build beyond aarch64 (done on macOS /
Linux musl+glibc / FreeBSD at
-O0and-O1) to x86-64 (ELF + Mach-O) and rv64 (ELF), and run it as CI on the reference host. Cross-bootstrap is a stretch goal.
Cross-platform test failures
(Populated by the serial cross-platform run — macOS native, Linux, FreeBSD, Windows.)