wcc: defer capacity 32 with a loud cap error, both stages

wwstage capped defers at 16 and SILENTLY DROPPED the 17th; cstage
capped at 32. Align the cap at 32 and make exceeding it a loud
compile error in BOTH stages — the silent 16-vs-32 split was the bug
(a defer that never runs is a leaked resource). Both stages move in
one commit: one cap contract.
This commit is contained in:
2026-06-13 04:31:12 +09:00
parent 1f2bc7fc26
commit 92cd573197
7 changed files with 230 additions and 15 deletions

View File

@@ -35682,10 +35682,17 @@ fn cgstmt(c: *cgen, n: *node) void = {
if (k == nkind.N_YIELD) { cgyield(c, n); return; };
if (k == nkind.N_DEFER) {
if (c.defertop < DEFER_MAX) {
c.deferbuf[c.defertop] = n.lhs;
c.defertop += 1;
// #40: at the cap, fail loud in BOTH stages rather than
// silently drop the deferred call. cstage's DEFER_MAX was 32
// and also dropped silently past it; the runtime-correct target
// is a hard stop at the shared cap (cgen.c twin fatals too).
if (c.defertop >= DEFER_MAX) {
let msg: str = "cgen: too many defers in one function\n";
os.write(2, msg.ptr, msg.len: u64);
os.exit(1);
};
c.deferbuf[c.defertop] = n.lhs;
c.defertop += 1;
return;
};
@@ -41060,7 +41067,7 @@ type enumtype = struct {
};
def LOOP_MAX: i32 = 16;
def DEFER_MAX: i32 = 16;
def DEFER_MAX: i32 = 32; // #40: match cstage cgen.c DEFER_MAX (shared cap)
// The SysV register-return-ABI caps — the SINGLE SSoT shared by the sret
// classifier (sretretsize over-cap-tuple arm) AND every emit/receive site