kit

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

commit df8e73dd8c00a501a3b593bb97730af95321f574
parent 3fd5286ad48412a72fd8adde095d9d1784622ef0
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Mon, 25 May 2026 15:07:10 -0700

Fix C backend bitfield base addresses

Diffstat:
Msrc/arch/c_target/emit.c | 46+++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/src/arch/c_target/emit.c b/src/arch/c_target/emit.c @@ -2736,13 +2736,57 @@ static const char* c_bf_storage_type(u32 size) { } } +/* Spell an address expression for a backend-addressable lvalue operand. + * Unlike c_emit_operand, this never reads the object value; it materializes + * the address of the local/global/indirect storage itself. */ +static void c_emit_lvalue_addr_expr_raw(CTarget* t, Operand addr) { + char buf[24]; + SrcLoc loc = t->cur_fn ? t->cur_fn->loc : (SrcLoc){0, 0, 0}; + switch (addr.kind) { + case OPK_LOCAL: + cbuf_putc(&t->body, '&'); + c_slot_name(addr.v.frame_slot, buf, sizeof buf); + cbuf_puts(&t->body, buf); + return; + case OPK_GLOBAL: { + obj_sym_mark_referenced(t->obj, addr.v.global.sym); + const char* nm = c_sym_name(t, addr.v.global.sym); + cbuf_puts(&t->body, "((char*)&"); + cbuf_puts(&t->body, nm); + if (addr.v.global.addend != 0) { + cbuf_puts(&t->body, " + "); + cbuf_put_i64(&t->body, addr.v.global.addend); + } + cbuf_putc(&t->body, ')'); + return; + } + case OPK_INDIRECT: { + CAddrMode m = c_addr_mode(addr); + if ((u32)m.base >= t->reg_cap || !t->reg_declared[m.base]) { + compiler_panic(t->c, loc, + "C target: bitfield on undeclared base reg v%u", + (unsigned)m.base); + } + cbuf_putc(&t->body, '('); + c_emit_indirect_addr_expr(t, m); + cbuf_putc(&t->body, ')'); + return; + } + default: + compiler_panic(t->c, loc, + "C target: bitfield address on operand kind %d not " + "supported", + (int)addr.kind); + } +} + /* Spell `*(uintN_t*)((char*)addr + bf.storage_offset)` into the body. */ static void c_bf_storage_lvalue(CTarget* t, Operand addr, BitFieldAccess bf, const char* storage_ty) { cbuf_puts(&t->body, "(*("); cbuf_puts(&t->body, storage_ty); cbuf_puts(&t->body, "*)((char*)"); - c_emit_operand(t, addr); + c_emit_lvalue_addr_expr_raw(t, addr); if (bf.storage_offset != 0) { cbuf_puts(&t->body, " + "); cbuf_put_u64(&t->body, (u64)bf.storage_offset);