kit

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

commit 407e8ac9402c41d518db4ec5f084baea375f33ae
parent 5ff33ea3ab65aa517e6dbb0e50f6c9734d18fe1d
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Sat, 13 Jun 2026 11:24:26 -0700

perf(type): field-init TypeCgLower + stamp builtin cg_id on the node (B3)

(cherry picked from commit 5a8f494350bb173399522ad2d59b7446f7aa907f)

Diffstat:
Mlang/c/type/type.c | 21+++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/lang/c/type/type.c b/lang/c/type/type.c @@ -840,15 +840,22 @@ static KitCgTypeId type_cg_lower(TypeCgLower* l, const Type* t, /* Only VALUE-mode lowering is memoized on the node: TYPE_CG_RECORD_FIELD * collapses pointers to void*, so the same Type* lowers differently there * (and that mode is used only transiently for record fields / func params). - * Check the cache BEFORE the builtin switch: a primitive node never carries a - * cg_id (it returns from the switch below before the cache-store), so this - * hoist only short-circuits already-lowered non-builtin types and never - * mis-returns a primitive's id — byte-identical, but skips the switch. */ + * Check the cache BEFORE the builtin switch: a cached cg_id (whether a builtin + * id stamped below or a non-builtin lowering) always equals what the switch + * would recompute, so this hoist only short-circuits already-lowered types — + * byte-identical, but skips the recompute. */ cacheable = (mode == TYPE_CG_VALUE); if (cacheable && t->cg_id != KIT_CG_TYPE_NONE) return t->cg_id; /* cached => was incomplete-free => still stable */ id = type_cg_builtin(l->c, (TypeKind)t->kind); - if (id != KIT_CG_TYPE_NONE) return id; + if (id != KIT_CG_TYPE_NONE) { + /* type_cg_builtin is a pure function of t->kind (and the fixed target), so + * a builtin id is mode-independent and incomplete-free: stamp it on the node + * so the next VALUE-mode crossing short-circuits above. A builtin id is + * never 0 (builtin_id(VOID)=64), so it can't alias the NONE sentinel. */ + if (cacheable) ((Type*)t)->cg_id = id; + return id; + } /* Scope saw_incomplete to this subtree so the post-recursion check reflects * only whether *this* node's lowering touched an incomplete record. */ outer_incomplete = l->saw_incomplete; @@ -916,10 +923,12 @@ static KitCgTypeId type_cg_lower(TypeCgLower* l, const Type* t, KitCgTypeId type_cg_id_in_pool(KitCompiler* c, Pool* p, const Type* t) { TypeCgLower l; if (!p) return KIT_CG_TYPE_NONE; - memset(&l, 0, sizeof l); + /* TypeCgLower has exactly these four fields; explicit init writes the same + * values the memset+assignments did, skipping a per-crossing struct clear. */ l.c = c; l.p = p; l.cache = cache_get(p); + l.saw_incomplete = 0; return type_cg_lower(&l, t, TYPE_CG_VALUE); }