commit 84f59b9951ab1c267c3938e30897244d8e2caca6
parent 21fd4234fd63e43ca4828e8ff798dc05f845a941
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Wed, 3 Jun 2026 10:30:16 -0700
lang/c: collapse per-TypeKind switches into one property table
c_type_is_signed_integer (c_abi.c), type_is_signed_integer_for_cg
(type.c), and pcg_type_is_signed (cg_adapter.c) were byte-identical
signed-integer switches; type_is_int/type_is_arith plus cint_rank and
cint_unsigned_variant (parse_expr.c) re-enumerated the prim kinds.
Introduce one static const property table in type.c indexed by TypeKind
(sized TY_ENUM+1, aggregate kinds are zero-filled holes) with columns
is_signed/is_int/is_fp/rank/uvariant, and expose type_kind_* accessors
plus a type_is_signed_integer(const Type*) wrapper via type.h. All the
scattered switches now read the table. Net -46 LOC, no behavior change.
(cherry picked from commit 586ec934b24c48e645254928b35c25bdc7bf548a)
Diffstat:
5 files changed, 81 insertions(+), 127 deletions(-)
diff --git a/lang/c/abi/c_abi.c b/lang/c/abi/c_abi.c
@@ -2,23 +2,6 @@
#include <string.h>
-static int c_type_is_signed_integer(const Type* t) {
- if (!t) return 0;
- switch ((TypeKind)t->kind) {
- case TY_CHAR:
- case TY_SCHAR:
- case TY_SHORT:
- case TY_INT:
- case TY_LONG:
- case TY_LLONG:
- case TY_INT128:
- case TY_ENUM:
- return 1;
- default:
- return 0;
- }
-}
-
ABITypeInfo c_abi_type_info(KitCompiler* a, const Type* t) {
KitCgTypeId id = type_cg_id(a, t);
KitCgTypeKind kind = kit_cg_type_kind(a, id);
@@ -47,7 +30,7 @@ ABITypeInfo c_abi_type_info(KitCompiler* a, const Type* t) {
r.scalar_kind = ABI_SC_VOID;
break;
}
- r.signed_ = c_type_is_signed_integer(t);
+ r.signed_ = type_is_signed_integer(t);
return r;
}
diff --git a/lang/c/parse/cg_adapter.c b/lang/c/parse/cg_adapter.c
@@ -240,27 +240,11 @@ void pcg_codegen_suppress_pop(Parser* p) {
}
int pcg_type_is_fp(const Type* ty) {
- return ty && (ty->kind == TY_FLOAT || ty->kind == TY_DOUBLE ||
- ty->kind == TY_LDOUBLE);
-}
-
-int pcg_type_is_signed(const Type* ty) {
- if (!ty) return 0;
- switch ((TypeKind)ty->kind) {
- case TY_CHAR:
- case TY_SCHAR:
- case TY_SHORT:
- case TY_INT:
- case TY_LONG:
- case TY_LLONG:
- case TY_INT128:
- case TY_ENUM:
- return 1;
- default:
- return 0;
- }
+ return ty && type_kind_is_fp((TypeKind)ty->kind);
}
+int pcg_type_is_signed(const Type* ty) { return type_is_signed_integer(ty); }
+
KitCgIntBinOp pcg_int_binop(BinOp op) {
switch (op) {
case BO_IADD:
diff --git a/lang/c/parse/parse_expr.c b/lang/c/parse/parse_expr.c
@@ -598,60 +598,12 @@ static CConstInt cint_cast(Parser* p, CConstInt v, const Type* ty) {
}
static u32 cint_rank(const Type* ty) {
- if (!ty) return 0;
- switch ((TypeKind)ty->kind) {
- case TY_BOOL:
- return 1;
- case TY_CHAR:
- case TY_SCHAR:
- case TY_UCHAR:
- return 2;
- case TY_SHORT:
- case TY_USHORT:
- return 3;
- case TY_INT:
- case TY_UINT:
- case TY_ENUM:
- return 4;
- case TY_LONG:
- case TY_ULONG:
- return 5;
- case TY_LLONG:
- case TY_ULLONG:
- return 6;
- case TY_INT128:
- case TY_UINT128:
- return 7;
- default:
- return 0;
- }
+ return ty ? type_kind_int_rank((TypeKind)ty->kind) : 0;
}
static const Type* cint_unsigned_variant(Parser* p, const Type* ty) {
- if (!ty) return type_prim(p->pool, TY_UINT);
- switch ((TypeKind)ty->kind) {
- case TY_BOOL:
- case TY_CHAR:
- case TY_SCHAR:
- case TY_UCHAR:
- case TY_SHORT:
- case TY_USHORT:
- case TY_INT:
- case TY_UINT:
- case TY_ENUM:
- return type_prim(p->pool, TY_UINT);
- case TY_LONG:
- case TY_ULONG:
- return type_prim(p->pool, TY_ULONG);
- case TY_LLONG:
- case TY_ULLONG:
- return type_prim(p->pool, TY_ULLONG);
- case TY_INT128:
- case TY_UINT128:
- return type_prim(p->pool, TY_UINT128);
- default:
- return type_prim(p->pool, TY_UINT);
- }
+ TypeKind k = ty ? (TypeKind)ty->kind : TY_UINT;
+ return type_prim(p->pool, type_kind_unsigned_variant(k));
}
static const Type* cint_promote_type(Parser* p, const Type* ty) {
diff --git a/lang/c/type/type.c b/lang/c/type/type.c
@@ -444,53 +444,78 @@ const Type* type_composite(Pool* p, const Type* a, const Type* b) {
}
}
+/* Single source of truth for per-TypeKind scalar facts. Indexed directly by
+ * TypeKind (sized to TY_ENUM + 1); the aggregate kinds PTR/ARRAY/FUNC/STRUCT/
+ * UNION are zero-filled holes. Columns:
+ * is_signed - signed integer (drives sign-extension / signed cg ops)
+ * is_int - integer type (bool/char/.../enum)
+ * is_fp - floating-point type
+ * rank - C integer conversion rank (0 for non-integers)
+ * uvariant - corresponding unsigned TypeKind (TY_UINT for non-integers,
+ * matching the historical default)
+ * Accessors below read this table instead of re-enumerating the kinds. */
+typedef struct TypeKindProps {
+ u8 is_signed;
+ u8 is_int;
+ u8 is_fp;
+ u8 rank;
+ u8 uvariant; /* TypeKind */
+} TypeKindProps;
+
+static const TypeKindProps kTypeKindProps[TY_ENUM + 1] = {
+ [TY_VOID] = {0, 0, 0, 0, TY_UINT},
+ [TY_BOOL] = {0, 1, 0, 1, TY_UINT},
+ [TY_CHAR] = {1, 1, 0, 2, TY_UINT},
+ [TY_SCHAR] = {1, 1, 0, 2, TY_UINT},
+ [TY_UCHAR] = {0, 1, 0, 2, TY_UINT},
+ [TY_SHORT] = {1, 1, 0, 3, TY_UINT},
+ [TY_USHORT] = {0, 1, 0, 3, TY_UINT},
+ [TY_INT] = {1, 1, 0, 4, TY_UINT},
+ [TY_UINT] = {0, 1, 0, 4, TY_UINT},
+ [TY_LONG] = {1, 1, 0, 5, TY_ULONG},
+ [TY_ULONG] = {0, 1, 0, 5, TY_ULONG},
+ [TY_LLONG] = {1, 1, 0, 6, TY_ULLONG},
+ [TY_ULLONG] = {0, 1, 0, 6, TY_ULLONG},
+ [TY_INT128] = {1, 1, 0, 7, TY_UINT128},
+ [TY_UINT128] = {0, 1, 0, 7, TY_UINT128},
+ [TY_FLOAT] = {0, 0, 1, 0, TY_UINT},
+ [TY_DOUBLE] = {0, 0, 1, 0, TY_UINT},
+ [TY_LDOUBLE] = {0, 0, 1, 0, TY_UINT},
+ /* PTR/ARRAY/FUNC/STRUCT/UNION: zero-filled holes (uvariant 0 == TY_VOID
+ * is never read for non-integers; callers map non-int to TY_UINT). */
+ [TY_ENUM] = {1, 1, 0, 4, TY_UINT},
+};
+
+static const TypeKindProps* type_kind_props(TypeKind k) {
+ if ((unsigned)k > (unsigned)TY_ENUM) return &kTypeKindProps[TY_VOID];
+ return &kTypeKindProps[k];
+}
+
+int type_kind_is_int(TypeKind k) { return type_kind_props(k)->is_int; }
+int type_kind_is_fp(TypeKind k) { return type_kind_props(k)->is_fp; }
+int type_kind_is_signed_integer(TypeKind k) {
+ return type_kind_props(k)->is_signed;
+}
+u32 type_kind_int_rank(TypeKind k) { return type_kind_props(k)->rank; }
+TypeKind type_kind_unsigned_variant(TypeKind k) {
+ const TypeKindProps* p = type_kind_props(k);
+ return p->is_int ? (TypeKind)p->uvariant : TY_UINT;
+}
+
int type_is_int(const Type* t) {
- if (!t) return 0;
- switch (t->kind) {
- case TY_BOOL:
- case TY_CHAR:
- case TY_SCHAR:
- case TY_UCHAR:
- case TY_SHORT:
- case TY_USHORT:
- case TY_INT:
- case TY_UINT:
- case TY_LONG:
- case TY_ULONG:
- case TY_LLONG:
- case TY_ULLONG:
- case TY_INT128:
- case TY_UINT128:
- case TY_ENUM:
- return 1;
- default:
- return 0;
- }
+ return t ? type_kind_is_int((TypeKind)t->kind) : 0;
}
int type_is_arith(const Type* t) {
if (!t) return 0;
- if (type_is_int(t)) return 1;
- return t->kind == TY_FLOAT || t->kind == TY_DOUBLE || t->kind == TY_LDOUBLE;
+ return type_kind_is_int((TypeKind)t->kind) ||
+ type_kind_is_fp((TypeKind)t->kind);
}
int type_is_ptr(const Type* t) { return t && t->kind == TY_PTR; }
-static int type_is_signed_integer_for_cg(const Type* t) {
- if (!t) return 0;
- switch ((TypeKind)t->kind) {
- case TY_CHAR:
- case TY_SCHAR:
- case TY_SHORT:
- case TY_INT:
- case TY_LONG:
- case TY_LLONG:
- case TY_INT128:
- case TY_ENUM:
- return 1;
- default:
- return 0;
- }
+int type_is_signed_integer(const Type* t) {
+ return t ? type_kind_is_signed_integer((TypeKind)t->kind) : 0;
}
static KitCgTypeId type_cg_builtin(KitCompiler* c, TypeKind kind) {
@@ -619,7 +644,7 @@ static KitCgTypeId type_cg_record_layout(TypeCgLower* l, const Type* t) {
fields[i].flags |= KIT_CG_FIELD_BITFIELD;
fields[i].bit_width = t->rec.fields[i].bitfield_width;
fields[i].bit_signed =
- type_is_signed_integer_for_cg(t->rec.fields[i].type);
+ type_is_signed_integer(t->rec.fields[i].type);
if (t->rec.fields[i].flags & FIELD_ZERO_WIDTH) {
fields[i].flags |= KIT_CG_FIELD_ZERO_WIDTH;
}
diff --git a/lang/c/type/type.h b/lang/c/type/type.h
@@ -171,6 +171,16 @@ const Type* type_composite(Pool*, const Type*, const Type*);
int type_is_arith(const Type*);
int type_is_int(const Type*);
int type_is_ptr(const Type*);
+int type_is_signed_integer(const Type*);
+
+/* Per-TypeKind scalar facts, backed by a single property table in type.c.
+ * These take a bare TypeKind so callers that already have one (and the
+ * Type* wrappers above) share the same source of truth. */
+int type_kind_is_int(TypeKind);
+int type_kind_is_fp(TypeKind);
+int type_kind_is_signed_integer(TypeKind);
+u32 type_kind_int_rank(TypeKind);
+TypeKind type_kind_unsigned_variant(TypeKind);
KitCgTypeId type_cg_id_in_pool(KitCompiler*, Pool*, const Type*);
KitCgTypeId type_cg_id(KitCompiler*, const Type*);