kit

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

commit f9ebea8f994b599258edb1f80ff8c84b247b672f
parent a44d4748e79698aa74936a6f9c5dacb3c5a9a943
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Wed,  3 Jun 2026 10:21:23 -0700

cg: collapse four parallel KitCgIntrinsic switches into one descriptor table

arith.c carried four switches over KitCgIntrinsic that had to be kept
in lockstep: api_map_intrinsic (->IntrinKind), api_intrinsic_is_void +
api_intrinsic_is_overflow (->bool), and api_intrinsic_name
(->const char*). Replace them with a single static const table indexed
by KitCgIntrinsic, one row per intrinsic {kind, name, is_void,
is_overflow}; the four accessors become field reads. Unmapped
intrinsics (FMA/SYSCALL/cache/coro) get an INTRIN_NONE row.

A _Static_assert on the table length restores the compile-time
exhaustiveness the -Wswitch'd switches gave us, so adding an enumerator
is a build error rather than a silently truncated index.

Also delete the redundant api_arch_name and call the existing
arch_kind_name (src/arch/registry.c, already linked) at its sole site;
the panic diagnostic now reads x86_32/arm32/unknown instead of
x86/arm/target (equivalent).

(cherry picked from commit 45e3947491d0ce590c42b5073515e7bfb960d070)

Diffstat:
Msrc/cg/arith.c | 258++++++++++++++++++++++---------------------------------------------------------
Msrc/cg/internal.h | 1-
2 files changed, 72 insertions(+), 187 deletions(-)

diff --git a/src/cg/arith.c b/src/cg/arith.c @@ -829,206 +829,92 @@ void kit_cg_float_to_uint(KitCg* g, KitCgTypeId dst, KitCgRounding rounding) { * Intrinsics (stub) * ============================================================ */ +/* One descriptor per KitCgIntrinsic, indexed by the enum value. The four + * accessors below are field reads off this single source of truth; unmapped + * intrinsics (FMA/SYSCALL/cache/coro) use an INTRIN_NONE row. The table is laid + * out in enum order; the _Static_assert guards its length so a new enumerator + * is a compile error rather than a silently truncated index. */ +typedef struct IntrinDesc { + IntrinKind kind; + const char* name; + bool is_void; + bool is_overflow; +} IntrinDesc; + +static const IntrinDesc kIntrinTable[] = { + [KIT_CG_INTRIN_TRAP] = {INTRIN_TRAP, "trap", true, false}, + [KIT_CG_INTRIN_CLZ] = {INTRIN_CLZ, "clz", false, false}, + [KIT_CG_INTRIN_CTZ] = {INTRIN_CTZ, "ctz", false, false}, + [KIT_CG_INTRIN_POPCOUNT] = {INTRIN_POPCOUNT, "popcount", false, false}, + [KIT_CG_INTRIN_BSWAP] = {INTRIN_BSWAP, "bswap", false, false}, + [KIT_CG_INTRIN_SETJMP] = {INTRIN_SETJMP, "setjmp", false, false}, + [KIT_CG_INTRIN_LONGJMP] = {INTRIN_LONGJMP, "longjmp", true, false}, + [KIT_CG_INTRIN_SADD_OVERFLOW] = + {INTRIN_SADD_OVERFLOW, "sadd_overflow", false, true}, + [KIT_CG_INTRIN_UADD_OVERFLOW] = + {INTRIN_UADD_OVERFLOW, "uadd_overflow", false, true}, + [KIT_CG_INTRIN_SSUB_OVERFLOW] = + {INTRIN_SSUB_OVERFLOW, "ssub_overflow", false, true}, + [KIT_CG_INTRIN_USUB_OVERFLOW] = + {INTRIN_USUB_OVERFLOW, "usub_overflow", false, true}, + [KIT_CG_INTRIN_SMUL_OVERFLOW] = + {INTRIN_SMUL_OVERFLOW, "smul_overflow", false, true}, + [KIT_CG_INTRIN_UMUL_OVERFLOW] = + {INTRIN_UMUL_OVERFLOW, "umul_overflow", false, true}, + [KIT_CG_INTRIN_FMA] = {INTRIN_NONE, "fma", false, false}, + [KIT_CG_INTRIN_PREFETCH] = {INTRIN_PREFETCH, "prefetch", true, false}, + [KIT_CG_INTRIN_EXPECT] = {INTRIN_EXPECT, "expect", false, false}, + [KIT_CG_INTRIN_ASSUME_ALIGNED] = + {INTRIN_ASSUME_ALIGNED, "assume_aligned", false, false}, + [KIT_CG_INTRIN_SYSCALL] = {INTRIN_NONE, "syscall", false, false}, + [KIT_CG_INTRIN_IRQ_SAVE] = {INTRIN_IRQ_SAVE, "irq_save", false, false}, + [KIT_CG_INTRIN_IRQ_RESTORE] = + {INTRIN_IRQ_RESTORE, "irq_restore", true, false}, + [KIT_CG_INTRIN_IRQ_DISABLE] = + {INTRIN_IRQ_DISABLE, "irq_disable", true, false}, + [KIT_CG_INTRIN_IRQ_ENABLE] = {INTRIN_IRQ_ENABLE, "irq_enable", true, false}, + [KIT_CG_INTRIN_DMB] = {INTRIN_DMB, "dmb", true, false}, + [KIT_CG_INTRIN_DSB] = {INTRIN_DSB, "dsb", true, false}, + [KIT_CG_INTRIN_ISB] = {INTRIN_ISB, "isb", true, false}, + [KIT_CG_INTRIN_DCACHE_CLEAN] = {INTRIN_NONE, "dcache_clean", false, false}, + [KIT_CG_INTRIN_DCACHE_INVALIDATE] = + {INTRIN_NONE, "dcache_invalidate", false, false}, + [KIT_CG_INTRIN_DCACHE_CLEAN_INVALIDATE] = + {INTRIN_NONE, "dcache_clean_invalidate", false, false}, + [KIT_CG_INTRIN_ICACHE_INVALIDATE] = + {INTRIN_NONE, "icache_invalidate", false, false}, + [KIT_CG_INTRIN_CPU_NOP] = {INTRIN_CPU_NOP, "cpu_nop", true, false}, + [KIT_CG_INTRIN_CPU_YIELD] = {INTRIN_CPU_YIELD, "cpu_yield", true, false}, + [KIT_CG_INTRIN_WFI] = {INTRIN_WFI, "wfi", true, false}, + [KIT_CG_INTRIN_WFE] = {INTRIN_WFE, "wfe", true, false}, + [KIT_CG_INTRIN_SEV] = {INTRIN_SEV, "sev", true, false}, + [KIT_CG_INTRIN_CORO_SWITCH] = {INTRIN_NONE, "coro_switch", false, false}, +}; + +_Static_assert(sizeof(kIntrinTable) / sizeof(kIntrinTable[0]) == + KIT_CG_INTRIN_CORO_SWITCH + 1, + "kIntrinTable must have exactly one row per KitCgIntrinsic"); + IntrinKind api_map_intrinsic(KitCg* g, KitCgIntrinsic intrin, KitCgTypeId result_type) { /* Width-by-type: backends derive operand width from the result type, so the * mapping no longer needs the size here. */ (void)g; (void)result_type; - switch (intrin) { - case KIT_CG_INTRIN_TRAP: - return INTRIN_TRAP; - case KIT_CG_INTRIN_CLZ: - return INTRIN_CLZ; - case KIT_CG_INTRIN_CTZ: - return INTRIN_CTZ; - case KIT_CG_INTRIN_POPCOUNT: - return INTRIN_POPCOUNT; - case KIT_CG_INTRIN_BSWAP: - return INTRIN_BSWAP; - case KIT_CG_INTRIN_SETJMP: - return INTRIN_SETJMP; - case KIT_CG_INTRIN_LONGJMP: - return INTRIN_LONGJMP; - case KIT_CG_INTRIN_SADD_OVERFLOW: - return INTRIN_SADD_OVERFLOW; - case KIT_CG_INTRIN_UADD_OVERFLOW: - return INTRIN_UADD_OVERFLOW; - case KIT_CG_INTRIN_SSUB_OVERFLOW: - return INTRIN_SSUB_OVERFLOW; - case KIT_CG_INTRIN_USUB_OVERFLOW: - return INTRIN_USUB_OVERFLOW; - case KIT_CG_INTRIN_SMUL_OVERFLOW: - return INTRIN_SMUL_OVERFLOW; - case KIT_CG_INTRIN_UMUL_OVERFLOW: - return INTRIN_UMUL_OVERFLOW; - case KIT_CG_INTRIN_PREFETCH: - return INTRIN_PREFETCH; - case KIT_CG_INTRIN_EXPECT: - return INTRIN_EXPECT; - case KIT_CG_INTRIN_ASSUME_ALIGNED: - return INTRIN_ASSUME_ALIGNED; - case KIT_CG_INTRIN_CPU_NOP: - return INTRIN_CPU_NOP; - case KIT_CG_INTRIN_CPU_YIELD: - return INTRIN_CPU_YIELD; - case KIT_CG_INTRIN_WFI: - return INTRIN_WFI; - case KIT_CG_INTRIN_WFE: - return INTRIN_WFE; - case KIT_CG_INTRIN_SEV: - return INTRIN_SEV; - case KIT_CG_INTRIN_ISB: - return INTRIN_ISB; - case KIT_CG_INTRIN_DMB: - return INTRIN_DMB; - case KIT_CG_INTRIN_DSB: - return INTRIN_DSB; - case KIT_CG_INTRIN_IRQ_SAVE: - return INTRIN_IRQ_SAVE; - case KIT_CG_INTRIN_IRQ_RESTORE: - return INTRIN_IRQ_RESTORE; - case KIT_CG_INTRIN_IRQ_ENABLE: - return INTRIN_IRQ_ENABLE; - case KIT_CG_INTRIN_IRQ_DISABLE: - return INTRIN_IRQ_DISABLE; - case KIT_CG_INTRIN_FMA: - case KIT_CG_INTRIN_SYSCALL: - case KIT_CG_INTRIN_DCACHE_CLEAN: - case KIT_CG_INTRIN_DCACHE_INVALIDATE: - case KIT_CG_INTRIN_DCACHE_CLEAN_INVALIDATE: - case KIT_CG_INTRIN_ICACHE_INVALIDATE: - case KIT_CG_INTRIN_CORO_SWITCH: - return INTRIN_NONE; - } - return INTRIN_NONE; + return kIntrinTable[intrin].kind; } int api_intrinsic_is_void(KitCgIntrinsic intrin) { - switch (intrin) { - case KIT_CG_INTRIN_TRAP: - case KIT_CG_INTRIN_LONGJMP: - case KIT_CG_INTRIN_PREFETCH: - case KIT_CG_INTRIN_CPU_NOP: - case KIT_CG_INTRIN_CPU_YIELD: - case KIT_CG_INTRIN_WFI: - case KIT_CG_INTRIN_WFE: - case KIT_CG_INTRIN_SEV: - case KIT_CG_INTRIN_ISB: - case KIT_CG_INTRIN_DMB: - case KIT_CG_INTRIN_DSB: - case KIT_CG_INTRIN_IRQ_RESTORE: - case KIT_CG_INTRIN_IRQ_ENABLE: - case KIT_CG_INTRIN_IRQ_DISABLE: - return 1; - default: - return 0; - } + return kIntrinTable[intrin].is_void; } int api_intrinsic_is_overflow(KitCgIntrinsic intrin) { - return intrin == KIT_CG_INTRIN_SADD_OVERFLOW || - intrin == KIT_CG_INTRIN_UADD_OVERFLOW || - intrin == KIT_CG_INTRIN_SSUB_OVERFLOW || - intrin == KIT_CG_INTRIN_USUB_OVERFLOW || - intrin == KIT_CG_INTRIN_SMUL_OVERFLOW || - intrin == KIT_CG_INTRIN_UMUL_OVERFLOW; -} - -const char* api_arch_name(KitArchKind arch) { - switch (arch) { - case KIT_ARCH_X86_32: - return "x86"; - case KIT_ARCH_X86_64: - return "x86_64"; - case KIT_ARCH_ARM_32: - return "arm"; - case KIT_ARCH_ARM_64: - return "aarch64"; - case KIT_ARCH_RV32: - return "riscv32"; - case KIT_ARCH_RV64: - return "riscv64"; - case KIT_ARCH_WASM: - return "wasm"; - } - return "target"; + return kIntrinTable[intrin].is_overflow; } const char* api_intrinsic_name(KitCgIntrinsic intrin) { - switch (intrin) { - case KIT_CG_INTRIN_TRAP: - return "trap"; - case KIT_CG_INTRIN_CLZ: - return "clz"; - case KIT_CG_INTRIN_CTZ: - return "ctz"; - case KIT_CG_INTRIN_POPCOUNT: - return "popcount"; - case KIT_CG_INTRIN_BSWAP: - return "bswap"; - case KIT_CG_INTRIN_SETJMP: - return "setjmp"; - case KIT_CG_INTRIN_LONGJMP: - return "longjmp"; - case KIT_CG_INTRIN_SADD_OVERFLOW: - return "sadd_overflow"; - case KIT_CG_INTRIN_UADD_OVERFLOW: - return "uadd_overflow"; - case KIT_CG_INTRIN_SSUB_OVERFLOW: - return "ssub_overflow"; - case KIT_CG_INTRIN_USUB_OVERFLOW: - return "usub_overflow"; - case KIT_CG_INTRIN_SMUL_OVERFLOW: - return "smul_overflow"; - case KIT_CG_INTRIN_UMUL_OVERFLOW: - return "umul_overflow"; - case KIT_CG_INTRIN_FMA: - return "fma"; - case KIT_CG_INTRIN_PREFETCH: - return "prefetch"; - case KIT_CG_INTRIN_EXPECT: - return "expect"; - case KIT_CG_INTRIN_ASSUME_ALIGNED: - return "assume_aligned"; - case KIT_CG_INTRIN_SYSCALL: - return "syscall"; - case KIT_CG_INTRIN_IRQ_SAVE: - return "irq_save"; - case KIT_CG_INTRIN_IRQ_RESTORE: - return "irq_restore"; - case KIT_CG_INTRIN_IRQ_DISABLE: - return "irq_disable"; - case KIT_CG_INTRIN_IRQ_ENABLE: - return "irq_enable"; - case KIT_CG_INTRIN_DMB: - return "dmb"; - case KIT_CG_INTRIN_DSB: - return "dsb"; - case KIT_CG_INTRIN_ISB: - return "isb"; - case KIT_CG_INTRIN_DCACHE_CLEAN: - return "dcache_clean"; - case KIT_CG_INTRIN_DCACHE_INVALIDATE: - return "dcache_invalidate"; - case KIT_CG_INTRIN_DCACHE_CLEAN_INVALIDATE: - return "dcache_clean_invalidate"; - case KIT_CG_INTRIN_ICACHE_INVALIDATE: - return "icache_invalidate"; - case KIT_CG_INTRIN_CPU_NOP: - return "cpu_nop"; - case KIT_CG_INTRIN_CPU_YIELD: - return "cpu_yield"; - case KIT_CG_INTRIN_WFI: - return "wfi"; - case KIT_CG_INTRIN_WFE: - return "wfe"; - case KIT_CG_INTRIN_SEV: - return "sev"; - case KIT_CG_INTRIN_CORO_SWITCH: - return "coro_switch"; - } - return "intrinsic"; + const char* name = kIntrinTable[intrin].name; + return name ? name : "intrinsic"; } void kit_cg_intrinsic(KitCg* g, KitCgIntrinsic intrin, uint32_t nargs, @@ -1051,7 +937,7 @@ void kit_cg_intrinsic(KitCg* g, KitCgIntrinsic intrin, uint32_t nargs, if (!kit_cg_target_supports_intrinsic(g->c, intrin) || kind == INTRIN_NONE) { compiler_panic( g->c, g->cur_loc, "KitCg: target '%s' does not support intrinsic '%s'", - api_arch_name(g->c->target.arch), api_intrinsic_name(intrin)); + arch_kind_name(g->c->target.arch), api_intrinsic_name(intrin)); return; } diff --git a/src/cg/internal.h b/src/cg/internal.h @@ -223,7 +223,6 @@ IntrinKind api_map_intrinsic(KitCg* g, KitCgIntrinsic intrin, int api_intrinsic_is_void(KitCgIntrinsic intrin); int api_intrinsic_is_overflow(KitCgIntrinsic intrin); const char* api_intrinsic_name(KitCgIntrinsic intrin); -const char* api_arch_name(KitArchKind arch); void kit_cg_intrinsic(KitCg* g, KitCgIntrinsic intrin, uint32_t nargs, KitCgTypeId result_type); KitCgTypeId api_atomic_pointee(KitCg* g, KitCgTypeId pty, const char* who);