kit

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

commit 75ba470e205bb1f666c1160cae5461a4bc4d8859
parent ac1e312614a908ba4f64f796ebb3fb3a37684ec9
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Mon, 15 Jun 2026 13:44:37 -0700

cg: prune CallConv, alias FuncResult, drop dead ZERO_WIDTH field flag

Three CG API cleanups ahead of the header rewrite:

- KitCgCallConv: drop SYSV/WIN64/AAPCS/WASM (these are the target's ABI
  identity, fixed by the triple, not a per-compilation choice) and
  INTERRUPT (a duplicate of the KIT_CG_FUNC_INTERRUPT function flag).
  Only KIT_CG_CC_TARGET_C — the target's own C ABI — remains; it is the
  sole convention any backend lowered. The four arch supports_call_conv
  hooks collapse to a single TARGET_C check, and the toy callconv name
  table loses the removed spellings.

- KitCgFuncResult is now a typedef of KitCgFuncParam: identical shape
  (type + ABI attrs); the differing legal-attr subsets were never
  enforced by the distinct struct anyway.

- Remove KIT_CG_FIELD_ZERO_WIDTH: it had no consumer. Zero-width
  bit-field layout barriers are already carried by BITFIELD + bit_width
  == 0, which the CG and ABI layout paths key off of; the C frontend
  stops setting the dead flag.

No behavior change. cg_api 291/0, toy 1392/0, parse 3928/0.

Diffstat:
Minclude/kit/cg.h | 31+++++++++++++++----------------
Mlang/c/type/type.c | 5++---
Mlang/toy/attrs.c | 4+---
Msrc/arch/aa64/arch.c | 12+-----------
Msrc/arch/arch.h | 5+++--
Msrc/arch/riscv/arch.c | 12+-----------
Msrc/arch/wasm/arch.c | 12+-----------
Msrc/arch/x64/arch.c | 15++-------------
8 files changed, 26 insertions(+), 70 deletions(-)

diff --git a/include/kit/cg.h b/include/kit/cg.h @@ -74,17 +74,17 @@ typedef enum KitCgDebugEncoding { KIT_CG_DEBUG_ENC_FLOAT, } KitCgDebugEncoding; +/* Source-selectable calling convention: the convention axis a frontend can vary + * *within one compilation*, not the target's ABI identity (that is fixed by the + * triple). KIT_CG_CC_TARGET_C selects the target's own C ABI — whichever of + * SysV / Win64 / AAPCS64 / wasm the triple implies — and is the only convention + * kit lowers today. A real variant that repartitions the call (e.g. an x86 + * vectorcall/regparm, preserve_most) would be added here and gated by + * kit_cg_target_supports_call_conv. Definition-side conventions that change the + * prologue but not the call ABI (naked, interrupt) are function attributes — + * KIT_CG_FUNC_NAKED / KIT_CG_FUNC_INTERRUPT — not values here. */ typedef enum KitCgCallConv { - /* Backend-selected C ABI for the target triple. Frontends should use this - * unless source semantics or ABI interop explicitly require another - * convention. Non-default values are requests that must be supported by the - * selected backend or diagnosed. */ KIT_CG_CC_TARGET_C, - KIT_CG_CC_SYSV, - KIT_CG_CC_WIN64, - KIT_CG_CC_AAPCS, - KIT_CG_CC_WASM, - KIT_CG_CC_INTERRUPT, } KitCgCallConv; typedef enum KitCgAbiAttrFlag { @@ -113,13 +113,13 @@ typedef struct KitCgFuncParam { KitCgAbiAttrs attrs; } KitCgFuncParam; -/* Symmetric with KitCgFuncParam. result.type is always a valid type id; use +/* A function result is described exactly like a parameter: a type plus ABI + * attrs. The legal attribute subsets differ (SRET on results; BYVAL/NEST on + * params), but the descriptor shape is identical, so KitCgFuncResult is an + * alias of KitCgFuncParam. result.type is always a valid type id; use * kit_cg_type_builtin(c, KIT_CG_BUILTIN_VOID) for a function that returns no * value. */ -typedef struct KitCgFuncResult { - KitCgTypeId type; - KitCgAbiAttrs attrs; -} KitCgFuncResult; +typedef KitCgFuncParam KitCgFuncResult; typedef struct KitCgFuncSig { KitCgFuncResult result; /* void builtin means no value */ @@ -135,7 +135,7 @@ typedef struct KitCgField { uint32_t align_override; /* 0 = natural, 1 = packed, >1 explicit align */ uint32_t max_align; /* 0 = natural, otherwise cap field alignment */ uint32_t flags; /* KitCgFieldFlag */ - uint16_t bit_width; /* valid for bit-fields, may be 0 for barriers */ + uint16_t bit_width; /* bit-field width; 0 w/ BITFIELD = layout barrier */ uint16_t bit_offset; /* filled by record-field queries */ uint32_t bit_storage_size; /* bytes, filled by record-field queries */ int bit_signed; /* signed extraction for bit-field loads */ @@ -143,7 +143,6 @@ typedef struct KitCgField { typedef enum KitCgFieldFlag { KIT_CG_FIELD_BITFIELD = 1u << 0, - KIT_CG_FIELD_ZERO_WIDTH = 1u << 1, } KitCgFieldFlag; typedef struct KitCgEnumValue { diff --git a/lang/c/type/type.c b/lang/c/type/type.c @@ -888,11 +888,10 @@ static KitCgTypeId type_cg_record_layout(TypeCgLower* l, const Type* t) { fields[i].max_align = t->rec.max_align; if (t->rec.fields[i].flags & FIELD_BITFIELD) { fields[i].flags |= KIT_CG_FIELD_BITFIELD; + /* A zero-width bit-field is carried to CG as bit_width 0 (the layout + * barrier); CG keys off BITFIELD && bit_width==0, no separate flag. */ fields[i].bit_width = t->rec.fields[i].bitfield_width; fields[i].bit_signed = 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; - } } if (t->rec.fields[i].packed && fields[i].align_override == 0) { fields[i].align_override = 1; diff --git a/lang/toy/attrs.c b/lang/toy/attrs.c @@ -52,9 +52,7 @@ static int toy_parse_attr_string_arg(ToyParser* p, KitSym* out) { int toy_parse_callconv_const(ToyParser* p, KitCgCallConv* out) { static const ToyConstRow rows[] = { - {"target_c", KIT_CG_CC_TARGET_C}, {"sysv", KIT_CG_CC_SYSV}, - {"win64", KIT_CG_CC_WIN64}, {"aapcs", KIT_CG_CC_AAPCS}, - {"wasm", KIT_CG_CC_WASM}, {"interrupt", KIT_CG_CC_INTERRUPT}, + {"target_c", KIT_CG_CC_TARGET_C}, }; uint64_t v; if (!toy_parse_dot_const(p, rows, sizeof rows / sizeof rows[0], 1, diff --git a/src/arch/aa64/arch.c b/src/arch/aa64/arch.c @@ -152,17 +152,7 @@ static KitStatus aa64_target_feature_apply_isa(const Target* target, * no SysV/Win64/WASM variant. */ static int aa64_supports_call_conv(const Compiler* c, KitCgCallConv cc) { (void)c; - switch (cc) { - case KIT_CG_CC_TARGET_C: - case KIT_CG_CC_AAPCS: - return 1; - case KIT_CG_CC_SYSV: - case KIT_CG_CC_WIN64: - case KIT_CG_CC_WASM: - case KIT_CG_CC_INTERRUPT: - return 0; - } - return 0; + return cc == KIT_CG_CC_TARGET_C; } /* Capability twin of aa_intrinsic (src/arch/aa64/native.c); keep the two in diff --git a/src/arch/arch.h b/src/arch/arch.h @@ -325,8 +325,9 @@ typedef struct ArchImpl { u32 atomic_lock_free_max; /* 1 if call convention `cc` is selectable for this compiler's (arch, os). - * KIT_CG_CC_TARGET_C is handled generically (always 1); INTERRUPT is 0. May - * read c->target.os (a property, not arch identity). Read via + * Today the only convention is KIT_CG_CC_TARGET_C (the target's C ABI); a + * backend that grows a real variant convention reports it here. May read + * c->target.os (a property, not arch identity). Read via * kit_cg_target_supports_call_conv. */ int (*supports_call_conv)(const Compiler* c, KitCgCallConv cc); diff --git a/src/arch/riscv/arch.c b/src/arch/riscv/arch.c @@ -329,17 +329,7 @@ static CgTarget* rv64_semantic_target_new(Compiler* c, ObjBuilder* o, * variant. Shared by rv64 and rv32 (one backend, one answer). */ static int rv64_supports_call_conv(const Compiler* c, KitCgCallConv cc) { (void)c; - switch (cc) { - case KIT_CG_CC_TARGET_C: - return 1; - case KIT_CG_CC_SYSV: - case KIT_CG_CC_WIN64: - case KIT_CG_CC_AAPCS: - case KIT_CG_CC_WASM: - case KIT_CG_CC_INTERRUPT: - return 0; - } - return 0; + return cc == KIT_CG_CC_TARGET_C; } /* Capability twin of rv_intrinsic (src/arch/riscv/native.c); keep the two in diff --git a/src/arch/wasm/arch.c b/src/arch/wasm/arch.c @@ -75,17 +75,7 @@ static CGTarget* wasm_backend_make(Compiler* c, ObjBuilder* o, * SysV/Win64/AAPCS. */ static int wasm_supports_call_conv(const Compiler* c, KitCgCallConv cc) { (void)c; - switch (cc) { - case KIT_CG_CC_TARGET_C: - case KIT_CG_CC_WASM: - return 1; - case KIT_CG_CC_SYSV: - case KIT_CG_CC_WIN64: - case KIT_CG_CC_AAPCS: - case KIT_CG_CC_INTERRUPT: - return 0; - } - return 0; + return cc == KIT_CG_CC_TARGET_C; } /* Capability twin of wasm_intrinsic (src/arch/wasm/emit.c); keep the two in diff --git a/src/arch/x64/arch.c b/src/arch/x64/arch.c @@ -120,19 +120,8 @@ static CgTarget* x64_semantic_target_new(Compiler* c, ObjBuilder* o, /* Which explicit calling conventions x86-64 can emit. SysV and Win64 split on * the OS (a property, not arch identity); TARGET_C is always available. */ static int x64_supports_call_conv(const Compiler* c, KitCgCallConv cc) { - switch (cc) { - case KIT_CG_CC_TARGET_C: - return 1; - case KIT_CG_CC_SYSV: - return c->target.os != KIT_OS_WINDOWS; - case KIT_CG_CC_WIN64: - return c->target.os == KIT_OS_WINDOWS; - case KIT_CG_CC_AAPCS: - case KIT_CG_CC_WASM: - case KIT_CG_CC_INTERRUPT: - return 0; - } - return 0; + (void)c; + return cc == KIT_CG_CC_TARGET_C; } /* Capability twin of x64_intrinsic (src/arch/x64/native.c); keep the two in