kit

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

commit a0397c63a404f4589469e97260336eeaffc04549
parent dce052f5cd1a9b361a65cb2e7573b35c0f6fd85f
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Tue,  2 Jun 2026 03:32:26 -0700

cg: explicit PLACE predicate + forbid aggregate VALUEs (Track 7.1/7.2)

Diffstat:
Msrc/cg/control.c | 16+++++-----------
Msrc/cg/internal.h | 2--
Msrc/cg/value.c | 25++++++++++++++++++++++---
3 files changed, 27 insertions(+), 16 deletions(-)

diff --git a/src/cg/control.c b/src/cg/control.c @@ -961,24 +961,18 @@ void cfree_cg_field(CfreeCg* g, uint32_t field_index) { 0) { Operand base_addr; ApiSValue sv; - BitFieldAccess bf; if (layout->fields[field_index].bit_width == 0) { compiler_panic(g->c, g->cur_loc, "CfreeCg: zero-width bit-field access"); api_release(g, &base); return; } + /* Push the record-base address as a place of the field type. The bit-field + * geometry (storage size/offset, bit offset/width, signedness) is carried + * by the CfreeCgMemAccess the frontend supplies on the following load/store, + * which rebuilds the descriptor via bf_from_access; the place itself only + * needs to address the enclosing storage. */ base_addr = api_lvalue_addr(g, &base, rec_ptr_ty); - memset(&bf, 0, sizeof bf); - bf.field_type = field_ty; - bf.storage = api_mem_for_lvalue(g, &base_addr, field_ty); - bf.storage.size = layout->fields[field_index].storage_size; - bf.storage_offset = layout->fields[field_index].offset; - bf.bit_offset = layout->fields[field_index].bit_offset; - bf.bit_width = layout->fields[field_index].bit_width; - bf.signed_ = rec_info->record.fields[field_index].bit_signed != 0; sv = api_make_lv(base_addr, field_ty); - sv.bitfield_lvalue = 1; - sv.delayed.bitfield = bf; api_release(g, &base); api_push(g, sv); return; diff --git a/src/cg/internal.h b/src/cg/internal.h @@ -64,14 +64,12 @@ typedef struct ApiSValue { union { ApiDelayedCmp cmp; ApiDelayedArith arith; - BitFieldAccess bitfield; } delayed; CfreeCgTypeId type; u8 kind; u8 res; u8 pinned; u8 lvalue; - u8 bitfield_lvalue; CfreeCgLocal source_local; } ApiSValue; diff --git a/src/cg/value.c b/src/cg/value.c @@ -125,10 +125,19 @@ int api_sv_op_is_local_or_imm(const ApiSValue* sv) { (sv->op.kind == OPK_IMM || sv->op.kind == OPK_LOCAL); } +/* A PLACE (lvalue) is exactly an SV_OPERAND whose operand addresses storage: + * op.kind in { OPK_LOCAL, OPK_GLOBAL, OPK_INDIRECT } (api_operand_can_address). + * This is a kind-based predicate, not a heuristic: the `lvalue` flag marks the + * value as a place, SV_OPERAND guarantees `op` is meaningful (SV_CMP/SV_ARITH + * never carry lvalue=1 — see fold.c, which clears it on materialization), and + * the operand kind decides addressability. The former heuristic OR'd in + * `bitfield_lvalue` and a (source_local && OPK_LOCAL) term, both subsumed here: + * a bitfield lvalue is built on the OPK_LOCAL address returned by + * api_lvalue_addr (see cfree_cg_field), and source_local only co-occurs with + * OPK_LOCAL — so api_operand_can_address already covers both. */ int api_is_lvalue_sv(const ApiSValue* sv) { - return sv->lvalue && - (sv->bitfield_lvalue || api_operand_can_address(&sv->op) || - (sv->source_local != CFREE_CG_LOCAL_NONE && sv->op.kind == OPK_LOCAL)); + return sv->lvalue && sv->kind == SV_OPERAND && + api_operand_can_address(&sv->op); } void api_stack_grow(CfreeCg* g, u32 want) { @@ -147,6 +156,16 @@ void api_stack_grow(CfreeCg* g, u32 want) { } void api_push(CfreeCg* g, ApiSValue v) { + /* An aggregate (record) can only ever be a PLACE: it is addressed, loaded, + * and passed by SRET/BYVAL/BYREF, never materialized as a scalar VALUE. Catch + * any aggregate VALUE at the point it would enter the stack. i128/f128 are + * scalars (cg_type_is_aggregate is false for them), so they remain valid + * VALUEs and are unaffected. */ + if (cg_type_is_aggregate(g->c, api_sv_type(&v)) && !api_is_lvalue_sv(&v)) { + compiler_panic(g->c, g->cur_loc, + "CfreeCg: aggregate must be a place, not a value; load the " + "place or pass it by reference"); + } api_stack_grow(g, g->sp + 1); g->stack[g->sp++] = v; }