commit 58f31a5e6f4252d8eb52be87c6e1d226f3ff6e17
parent 9e9e4d219953c1a7c1abdf8e319802a67047eed0
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Mon, 11 May 2026 11:49:54 -0700
cg fix INDIRECT reg leak
Diffstat:
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/cg/cg.c b/src/cg/cg.c
@@ -394,8 +394,9 @@ static SValue* pick_victim(CG* g, u8 cls) {
/* Release the resources owned by a single in-flight CGABIValue arg
* after the call has returned: REG storage goes back to the reg pool,
* LOCAL storage produced by spill_avs_victim returns its slot to the
- * per-class spill-slot pool. IMM and other kinds carry no runtime
- * ownership and need nothing.
+ * per-class spill-slot pool, INDIRECT storage (an aggregate arg reached
+ * through a pointer, e.g. `f(p->aggr)`) returns its base reg. IMM and
+ * other kinds carry no runtime ownership and need nothing.
*
* Aggregate-typed OPK_LOCAL is a borrowed lvalue — the slot belongs to
* a user local or a stable byval/return frame slot — and must NOT
@@ -409,6 +410,8 @@ static void release_arg_storage(CG* g, const Operand* st) {
const Type* t = st->type;
if (t && (t->kind == TY_STRUCT || t->kind == TY_UNION)) return;
return_spill_slot(g, st->v.frame_slot, st->cls);
+ } else if (st->kind == OPK_INDIRECT) {
+ g->target->free_reg(g->target, st->v.ind.base, RC_INT);
}
}