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:
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);