diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index 4dbea470..377246c3 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -15041,34 +15041,6 @@ fn callee_variadic_param(c: *cgen, callee: *node, nfixed_out: *i32) *node = { return findvariadicparam(ps, nfixed_out); }; -// mkvarargname — fresh local-slot name "". Used for -// the per-variadic-call scratch buffers (`@vararg_d_N` for the -// element-data buffer, `@vararg_sl_N` for the 24B slice descriptor). -// N is recorded on the N_CALL node at first emit so re-entry into -// cgcall picks the same names regardless of walk order. -fn mkvarargname(c: *cgen, prefix: str, seq: i32) str = { - let buf: [128]u8; - let i: i32 = 0; - let j: i32 = 0; - for (j < prefix.len) { - buf[i] = prefix[j]; - i += 1; j += 1; - }; - let ns: str = strconv.i64tos(seq: i64, strconv.base.DEC); - let n: i32 = ns.len; - let dk: i32 = 0; - for (dk < n) { buf[i + dk] = ns.ptr[dk]; dk += 1; }; - let total: i32 = i + n; - let p: []u8 = alloc([], (total: u64) + 1u64)!; - let k: i32 = 0; - for (k < total) { p[k] = buf[k]; k += 1; }; - p[total] = 0u8; - let r: str; - r.ptr = p.ptr; - r.len = total; - return r; -}; - // ---- expression cgen ------------------------------------------------- // pushargsrev — recursively walks the arg list, evaluates rightmost @@ -22469,15 +22441,16 @@ fn cgcall(c: *cgen, n: *node) void = { }; }; }; // Hare-style variadic last param: gather N tail args into a - // frame-resident [N]T (`@vararg_d_`) plus a 24B slice - // descriptor (`@vararg_sl_`), then splice a synthesised + // frame-resident [N]T (vararg_d slot) plus a 24B slice + // descriptor (vararg_sl slot), then splice a synthesised // N_IDENT pointing at the descriptor into n.list so the rest // of the call machinery sees one slice slot for the variadic. // Forwarding shape (`xs...`) skips the gather: the spread's // inner slice expression replaces the wrapper in place. Empty - // (no trailing args) writes a {nil, 0, 0} descriptor. Per-call - // seq comes from c.varargseq bumped at gather emit (mirrors - // cstage's mklabel("vararg_d/sl") freshness). + // (no trailing args) writes a {nil, 0, 0} descriptor. Slot + // names come from mklabel (mirrors cstage cgen.c:5427/5431) so + // the shared labelseq advances in lockstep — vararg_d only when + // nvar>0, vararg_sl always — keeping later match labels aligned. { let nfixed_v: i32 = 0; let varp: *node = callee_variadic_param(c, callee, &nfixed_v); @@ -22515,10 +22488,6 @@ fn cgcall(c: *cgen, n: *node) void = { if (prev == nil) { n.list = inner; } else { prev.next = inner; }; } else { - let seq: i32 = c.varargseq; - c.varargseq += 1; - let dname: str = mkvarargname(c, "@vararg_d_", seq); - let sname: str = mkvarargname(c, "@vararg_sl_", seq); // Use raw element size, not stack-padded // slotsize. cstage cmd/w6c/cgen.c cgcall // gathers a `T...` slice at velem->size stride @@ -22555,6 +22524,11 @@ fn cgcall(c: *cgen, n: *node) void = { let velemslice: bool = isslicetype(c, velem); let doff: i32 = 0; if (nvar > 0) { + // mklabel, not a separate vararg counter, so + // labelseq advances with cstage cgen.c:5427 — the + // slot name never reaches asm, but the shared + // counter numbers later match labels. + let dname: str = mklabel(c, "vararg_d"); doff = localadd(c, dname, nvar * esz, nil); }; // #60: vararg gather builds a {ptr,len,cap} slice @@ -22562,6 +22536,9 @@ fn cgcall(c: *cgen, n: *node) void = { // slice-header bump propagates here. varp.lhs is // already the []T wrap from installparams, so we // consume it directly (re-slicewrap → [][]T). + // vararg_sl always allocated (cstage cgen.c:5431), + // bumping labelseq whether or not nvar>0. + let sname: str = mklabel(c, "vararg_sl"); let soff: i32 = localadd(c, sname, tyslicesize(): i32, varp.lhs); let aa2: *node = n.list; @@ -29104,13 +29081,6 @@ type cgen = struct { yieldbuf: []str, // stack of match end labels for yield defertop: i32, deferbuf: []*node, // stack of deferred exprs (LIFO at return) - // Variadic-call gather state. cgcall bumps this on each gather - // emit and uses it to mint `@vararg_d_N` / `@vararg_sl_N` per - // callsite; mirrors cstage's mklabel("vararg_d/sl") freshness - // so two variadic callsites with different arities in one fn - // get distinct slots (the shared slot fail-louds under #15's - // @-prefix grow-on-pin discipline). - varargseq: i32, // System V AMD64 sret discipline (#23). Plain TY_STRUCT returns // with size > 24B are passed via a hidden first-arg pointer // (RDI) to a caller-prealloc dest; the callee writes through @@ -29160,7 +29130,6 @@ fn cgeninit(c: *cgen) void = { c.frame = 0; c.lastwasreturn = 0; c.labelseq = 0; - c.varargseq = 0; c.sretdestoff = 0; c.sretdestnode = nil; c.sretforward = 0; diff --git a/selfhost/cmd/wcc/cgen.ww b/selfhost/cmd/wcc/cgen.ww index 917609a3..d3eeca41 100644 --- a/selfhost/cmd/wcc/cgen.ww +++ b/selfhost/cmd/wcc/cgen.ww @@ -491,13 +491,6 @@ type cgen = struct { yieldbuf: []str, // stack of match end labels for yield defertop: i32, deferbuf: []*node, // stack of deferred exprs (LIFO at return) - // Variadic-call gather state. cgcall bumps this on each gather - // emit and uses it to mint `@vararg_d_N` / `@vararg_sl_N` per - // callsite; mirrors cstage's mklabel("vararg_d/sl") freshness - // so two variadic callsites with different arities in one fn - // get distinct slots (the shared slot fail-louds under #15's - // @-prefix grow-on-pin discipline). - varargseq: i32, // System V AMD64 sret discipline (#23). Plain TY_STRUCT returns // with size > 24B are passed via a hidden first-arg pointer // (RDI) to a caller-prealloc dest; the callee writes through @@ -547,7 +540,6 @@ fn cgeninit(c: *cgen) void = { c.frame = 0; c.lastwasreturn = 0; c.labelseq = 0; - c.varargseq = 0; c.sretdestoff = 0; c.sretdestnode = nil; c.sretforward = 0; diff --git a/selfhost/cmd/wcc/cgenexpr.ww b/selfhost/cmd/wcc/cgenexpr.ww index 1682e146..a03f176a 100644 --- a/selfhost/cmd/wcc/cgenexpr.ww +++ b/selfhost/cmd/wcc/cgenexpr.ww @@ -3828,15 +3828,16 @@ fn cgcall(c: *cgen, n: *node) void = { }; }; }; // Hare-style variadic last param: gather N tail args into a - // frame-resident [N]T (`@vararg_d_`) plus a 24B slice - // descriptor (`@vararg_sl_`), then splice a synthesised + // frame-resident [N]T (vararg_d slot) plus a 24B slice + // descriptor (vararg_sl slot), then splice a synthesised // N_IDENT pointing at the descriptor into n.list so the rest // of the call machinery sees one slice slot for the variadic. // Forwarding shape (`xs...`) skips the gather: the spread's // inner slice expression replaces the wrapper in place. Empty - // (no trailing args) writes a {nil, 0, 0} descriptor. Per-call - // seq comes from c.varargseq bumped at gather emit (mirrors - // cstage's mklabel("vararg_d/sl") freshness). + // (no trailing args) writes a {nil, 0, 0} descriptor. Slot + // names come from mklabel (mirrors cstage cgen.c:5427/5431) so + // the shared labelseq advances in lockstep — vararg_d only when + // nvar>0, vararg_sl always — keeping later match labels aligned. { let nfixed_v: i32 = 0; let varp: *node = callee_variadic_param(c, callee, &nfixed_v); @@ -3874,10 +3875,6 @@ fn cgcall(c: *cgen, n: *node) void = { if (prev == nil) { n.list = inner; } else { prev.next = inner; }; } else { - let seq: i32 = c.varargseq; - c.varargseq += 1; - let dname: str = mkvarargname(c, "@vararg_d_", seq); - let sname: str = mkvarargname(c, "@vararg_sl_", seq); // Use raw element size, not stack-padded // slotsize. cstage cmd/w6c/cgen.c cgcall // gathers a `T...` slice at velem->size stride @@ -3914,6 +3911,11 @@ fn cgcall(c: *cgen, n: *node) void = { let velemslice: bool = isslicetype(c, velem); let doff: i32 = 0; if (nvar > 0) { + // mklabel, not a separate vararg counter, so + // labelseq advances with cstage cgen.c:5427 — the + // slot name never reaches asm, but the shared + // counter numbers later match labels. + let dname: str = mklabel(c, "vararg_d"); doff = localadd(c, dname, nvar * esz, nil); }; // #60: vararg gather builds a {ptr,len,cap} slice @@ -3921,6 +3923,9 @@ fn cgcall(c: *cgen, n: *node) void = { // slice-header bump propagates here. varp.lhs is // already the []T wrap from installparams, so we // consume it directly (re-slicewrap → [][]T). + // vararg_sl always allocated (cstage cgen.c:5431), + // bumping labelseq whether or not nvar>0. + let sname: str = mklabel(c, "vararg_sl"); let soff: i32 = localadd(c, sname, tyslicesize(): i32, varp.lhs); let aa2: *node = n.list; diff --git a/selfhost/cmd/wcc/cgenutil.ww b/selfhost/cmd/wcc/cgenutil.ww index 9e7a9e4b..7be2c28b 100644 --- a/selfhost/cmd/wcc/cgenutil.ww +++ b/selfhost/cmd/wcc/cgenutil.ww @@ -86,34 +86,6 @@ fn callee_variadic_param(c: *cgen, callee: *node, nfixed_out: *i32) *node = { return findvariadicparam(ps, nfixed_out); }; -// mkvarargname — fresh local-slot name "". Used for -// the per-variadic-call scratch buffers (`@vararg_d_N` for the -// element-data buffer, `@vararg_sl_N` for the 24B slice descriptor). -// N is recorded on the N_CALL node at first emit so re-entry into -// cgcall picks the same names regardless of walk order. -fn mkvarargname(c: *cgen, prefix: str, seq: i32) str = { - let buf: [128]u8; - let i: i32 = 0; - let j: i32 = 0; - for (j < prefix.len) { - buf[i] = prefix[j]; - i += 1; j += 1; - }; - let ns: str = strconv.i64tos(seq: i64, strconv.base.DEC); - let n: i32 = ns.len; - let dk: i32 = 0; - for (dk < n) { buf[i + dk] = ns.ptr[dk]; dk += 1; }; - let total: i32 = i + n; - let p: []u8 = alloc([], (total: u64) + 1u64)!; - let k: i32 = 0; - for (k < total) { p[k] = buf[k]; k += 1; }; - p[total] = 0u8; - let r: str; - r.ptr = p.ptr; - r.len = total; - return r; -}; - // ---- expression cgen ------------------------------------------------- // pushargsrev — recursively walks the arg list, evaluates rightmost diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 21ff61ac..3b14f7c8 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -15041,34 +15041,6 @@ fn callee_variadic_param(c: *cgen, callee: *node, nfixed_out: *i32) *node = { return findvariadicparam(ps, nfixed_out); }; -// mkvarargname — fresh local-slot name "". Used for -// the per-variadic-call scratch buffers (`@vararg_d_N` for the -// element-data buffer, `@vararg_sl_N` for the 24B slice descriptor). -// N is recorded on the N_CALL node at first emit so re-entry into -// cgcall picks the same names regardless of walk order. -fn mkvarargname(c: *cgen, prefix: str, seq: i32) str = { - let buf: [128]u8; - let i: i32 = 0; - let j: i32 = 0; - for (j < prefix.len) { - buf[i] = prefix[j]; - i += 1; j += 1; - }; - let ns: str = strconv.i64tos(seq: i64, strconv.base.DEC); - let n: i32 = ns.len; - let dk: i32 = 0; - for (dk < n) { buf[i + dk] = ns.ptr[dk]; dk += 1; }; - let total: i32 = i + n; - let p: []u8 = alloc([], (total: u64) + 1u64)!; - let k: i32 = 0; - for (k < total) { p[k] = buf[k]; k += 1; }; - p[total] = 0u8; - let r: str; - r.ptr = p.ptr; - r.len = total; - return r; -}; - // ---- expression cgen ------------------------------------------------- // pushargsrev — recursively walks the arg list, evaluates rightmost @@ -22469,15 +22441,16 @@ fn cgcall(c: *cgen, n: *node) void = { }; }; }; // Hare-style variadic last param: gather N tail args into a - // frame-resident [N]T (`@vararg_d_`) plus a 24B slice - // descriptor (`@vararg_sl_`), then splice a synthesised + // frame-resident [N]T (vararg_d slot) plus a 24B slice + // descriptor (vararg_sl slot), then splice a synthesised // N_IDENT pointing at the descriptor into n.list so the rest // of the call machinery sees one slice slot for the variadic. // Forwarding shape (`xs...`) skips the gather: the spread's // inner slice expression replaces the wrapper in place. Empty - // (no trailing args) writes a {nil, 0, 0} descriptor. Per-call - // seq comes from c.varargseq bumped at gather emit (mirrors - // cstage's mklabel("vararg_d/sl") freshness). + // (no trailing args) writes a {nil, 0, 0} descriptor. Slot + // names come from mklabel (mirrors cstage cgen.c:5427/5431) so + // the shared labelseq advances in lockstep — vararg_d only when + // nvar>0, vararg_sl always — keeping later match labels aligned. { let nfixed_v: i32 = 0; let varp: *node = callee_variadic_param(c, callee, &nfixed_v); @@ -22515,10 +22488,6 @@ fn cgcall(c: *cgen, n: *node) void = { if (prev == nil) { n.list = inner; } else { prev.next = inner; }; } else { - let seq: i32 = c.varargseq; - c.varargseq += 1; - let dname: str = mkvarargname(c, "@vararg_d_", seq); - let sname: str = mkvarargname(c, "@vararg_sl_", seq); // Use raw element size, not stack-padded // slotsize. cstage cmd/w6c/cgen.c cgcall // gathers a `T...` slice at velem->size stride @@ -22555,6 +22524,11 @@ fn cgcall(c: *cgen, n: *node) void = { let velemslice: bool = isslicetype(c, velem); let doff: i32 = 0; if (nvar > 0) { + // mklabel, not a separate vararg counter, so + // labelseq advances with cstage cgen.c:5427 — the + // slot name never reaches asm, but the shared + // counter numbers later match labels. + let dname: str = mklabel(c, "vararg_d"); doff = localadd(c, dname, nvar * esz, nil); }; // #60: vararg gather builds a {ptr,len,cap} slice @@ -22562,6 +22536,9 @@ fn cgcall(c: *cgen, n: *node) void = { // slice-header bump propagates here. varp.lhs is // already the []T wrap from installparams, so we // consume it directly (re-slicewrap → [][]T). + // vararg_sl always allocated (cstage cgen.c:5431), + // bumping labelseq whether or not nvar>0. + let sname: str = mklabel(c, "vararg_sl"); let soff: i32 = localadd(c, sname, tyslicesize(): i32, varp.lhs); let aa2: *node = n.list; @@ -29104,13 +29081,6 @@ type cgen = struct { yieldbuf: []str, // stack of match end labels for yield defertop: i32, deferbuf: []*node, // stack of deferred exprs (LIFO at return) - // Variadic-call gather state. cgcall bumps this on each gather - // emit and uses it to mint `@vararg_d_N` / `@vararg_sl_N` per - // callsite; mirrors cstage's mklabel("vararg_d/sl") freshness - // so two variadic callsites with different arities in one fn - // get distinct slots (the shared slot fail-louds under #15's - // @-prefix grow-on-pin discipline). - varargseq: i32, // System V AMD64 sret discipline (#23). Plain TY_STRUCT returns // with size > 24B are passed via a hidden first-arg pointer // (RDI) to a caller-prealloc dest; the callee writes through @@ -29160,7 +29130,6 @@ fn cgeninit(c: *cgen) void = { c.frame = 0; c.lastwasreturn = 0; c.labelseq = 0; - c.varargseq = 0; c.sretdestoff = 0; c.sretdestnode = nil; c.sretforward = 0; diff --git a/test/wcc/777_fmt_handle_run.c b/test/wcc/777_fmt_handle_run.c index 652e5d84..fb9840c5 100644 --- a/test/wcc/777_fmt_handle_run.c +++ b/test/wcc/777_fmt_handle_run.c @@ -117,7 +117,7 @@ static const struct row rows[] = { " return 42;\n" "};\n", 42, - STAGE_CS, 0 }, + STAGE_CS | STAGE_WW, 1 }, { "fprintln_file_multi", "package main;\n" "import os;\n" @@ -145,7 +145,7 @@ static const struct row rows[] = { " return 43;\n" "};\n", 43, - STAGE_CS, 0 }, + STAGE_CS | STAGE_WW, 1 }, { "fprint_file_raw", "package main;\n" "import os;\n" @@ -173,7 +173,7 @@ static const struct row rows[] = { " return 44;\n" "};\n", 44, - STAGE_CS, 0 }, + STAGE_CS | STAGE_WW, 1 }, { "branched_fprintf", "package main;\n" "import os;\n" @@ -206,7 +206,7 @@ static const struct row rows[] = { " return 45;\n" "};\n", 45, - STAGE_CS, 0 }, + STAGE_CS | STAGE_WW, 1 }, { "fprintf_stream", "package main;\n" "import os;\n" @@ -230,7 +230,7 @@ static const struct row rows[] = { " return 46;\n" "};\n", 46, - STAGE_CS, 0 }, + STAGE_CS | STAGE_WW, 1 }, }; static int @@ -357,7 +357,6 @@ main(void) int total = 0, fail = 0; int wwpresent = (access(wdrv, X_OK) == 0); int seq = 0; - (void)asm_byte_identical; /* cstage-only until #226/#227 land */ for (int i = 0; i < n; i++) { if (rows[i].stage_mask & STAGE_CS) { diff --git a/test/wcc/780_fmt_mods_run.c b/test/wcc/780_fmt_mods_run.c index 101b89ef..084d9f3e 100644 --- a/test/wcc/780_fmt_mods_run.c +++ b/test/wcc/780_fmt_mods_run.c @@ -115,7 +115,7 @@ static const struct row rows[] = { " return 50;\n" "};\n", 50, - STAGE_CS, 0 }, + STAGE_CS | STAGE_WW, 1 }, { "precision", "package main;\n" "import os;\n" @@ -143,7 +143,7 @@ static const struct row rows[] = { " return 51;\n" "};\n", 51, - STAGE_CS, 0 }, + STAGE_CS | STAGE_WW, 1 }, { "base_hex", "package main;\n" "import os;\n" @@ -171,7 +171,7 @@ static const struct row rows[] = { " return 52;\n" "};\n", 52, - STAGE_CS, 0 }, + STAGE_CS | STAGE_WW, 1 }, { "sign_plus", "package main;\n" "import os;\n" @@ -199,7 +199,7 @@ static const struct row rows[] = { " return 53;\n" "};\n", 53, - STAGE_CS, 0 }, + STAGE_CS | STAGE_WW, 1 }, { "zero_pad", "package main;\n" "import os;\n" @@ -227,7 +227,7 @@ static const struct row rows[] = { " return 54;\n" "};\n", 54, - STAGE_CS, 0 }, + STAGE_CS | STAGE_WW, 1 }, }; static int diff --git a/test/wcc/781_fmt_compositions_run.c b/test/wcc/781_fmt_compositions_run.c index 10341443..609f709b 100644 --- a/test/wcc/781_fmt_compositions_run.c +++ b/test/wcc/781_fmt_compositions_run.c @@ -125,7 +125,7 @@ static const struct row rows[] = { " return 60;\n" "};\n", 60, - STAGE_CS, 0 }, + STAGE_CS | STAGE_WW, 1 }, { "fprintfln_file_fmt", "package main;\n" "import os;\n" @@ -153,7 +153,7 @@ static const struct row rows[] = { " return 61;\n" "};\n", 61, - STAGE_CS, 0 }, + STAGE_CS | STAGE_WW, 1 }, { "fprintln_basic", "package main;\n" "import os;\n" @@ -180,7 +180,7 @@ static const struct row rows[] = { " return 64;\n" "};\n", 64, - STAGE_CS, 0 }, + STAGE_CS | STAGE_WW, 1 }, { "fprintfln_basic", "package main;\n" "import os;\n" @@ -205,7 +205,7 @@ static const struct row rows[] = { " return 65;\n" "};\n", 65, - STAGE_CS, 0 }, + STAGE_CS | STAGE_WW, 1 }, { "bsprintf_basic", "package main;\n" "import os;\n" @@ -226,7 +226,7 @@ static const struct row rows[] = { " return 62;\n" "};\n", 62, - STAGE_CS, 0 }, + STAGE_CS | STAGE_WW, 1 }, { "asprintf_basic", "package main;\n" "import os;\n" @@ -242,7 +242,7 @@ static const struct row rows[] = { " return 63;\n" "};\n", 63, - STAGE_CS, 0 }, + STAGE_CS | STAGE_WW, 1 }, }; static int