wwstage: name vararg-gather slots via mklabel; graduate fmt 777/780/781 (#227)
wwstage named variadic-gather slots with mkvarargname off a separate varargseq counter, never bumping the shared labelseq that names match labels. cstage names them via mklabel (cmd/w6c/cgen.c:5427,5431), which advances labelseq twice per gather. So by the time main.main reached its `match (wr)`, wwstage's match-label counter ran two behind cstage's (_4/_5/_6 vs _6/_7/_8) — a pure label-numbering divergence that kept fmt cs/ww byte-id failing. Drop varargseq and the mkvarargname helper; call the existing mklabel for the two gather slots, matching cstage's order (vararg_d only when nvar>0, vararg_sl always). The slot names are locals-table keys only — they resolve to BP offsets and never reach the asm — so only the labelseq advance is observable, which is exactly what realigns the downstream match labels. cstage untouched (align wwstage up). This was the match-label half of fmt's divergence; with the earlier compound-assign fix it completes fmt byte-identity. Graduate 777/780/781 to STAGE_CS|STAGE_WW with byte_id, and drop the now-stale (void)asm_byte_identical guard in 777.
This commit is contained in:
@@ -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_<seq>`) plus a 24B slice
|
||||
// descriptor (`@vararg_sl_<seq>`), 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;
|
||||
|
||||
Reference in New Issue
Block a user