kit

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

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:
Mlang/c/abi/c_abi.c | 19+------------------
Mlang/c/parse/cg_adapter.c | 22+++-------------------
Mlang/c/parse/parse_expr.c | 54+++---------------------------------------------------
Mlang/c/type/type.c | 103+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Mlang/c/type/type.h | 10++++++++++
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*);