cmd/w6c+selfhost/wcc: route cgparam/MLET/spill sizes through SSoT

#43 (8e93b31 + 087c85c) routed many sizeof(str) / sizeof(slice)
sites through primtypesize / tyslicesize / ty_*->size, but missed
the cgparam regs-fit, cgparam stack-stitch, cgmlet mixed
scalar+str receive, and vararg slice gather paths in both stages.
A bare #1 bump (str→24B) on top of #43 reds ~60 tests because
those paths still hardcoded 16/24.

Cstage:
- cgen.c:7360-7361 cgmlet: sz0/sz1 → (int)u0->size / (int)u1->size.
- cgen.c:7557 cgparam regs-fit: slice|is_str → (int)pu->size.
- cgen.c:7586 cgparam stack-stitch: same.
- cgen.c:4368 cgcall vararg gather: localoff slice descriptor →
  (int)vsu->size (the cstage twin of cgenexpr.ww:3084).

Wwstage:
- cgendecl.ww:225, :243 cgfnparams: 16 → primtypesize("str"): i32.
- cgenexpr.ww:3084 cgcall vararg gather: 24 → tyslicesize(): i32.

Plus a latent-bug fix at cgenstmt.ww cglet :1031 / :1040: the
str-init and slice-init arms dispatched on size only. Under #1's
str→24, both arms would have fired on a str let (duplicate
MOVQ BX,off+8 + bogus MOVQ CX,off+8). Added isstrtype / isslicetype
kind gates mirroring cstage cgen.c:6439's
`type_isstr(lt) && sz == ty_str->size`. Zero asm change today
because the size constants implicitly disambiguate at 16 vs 24.

Probe with temporary #1 bump (str.size=24) confirms 990_selfhost +
994_w6c_ww go green — the cgen-routing slice for #1 is now
closed. Remaining red under bump is lib/ww/typ.ww's parallel SSoT
seed + stringstest cap*16u64 strides + w6l_ww runtime SIGSEGV;
all tracked separately.

EIGHTBYTES register-count sites (cgen.c:7553-7554, cgendecl.ww:224
/:260) intentionally NOT touched — those are str ABI in-flight
3-reg work (task #34), not slot-width SSoT.
This commit is contained in:
2026-05-20 10:08:15 +09:00
parent 087c85c3cf
commit caa72f2365
6 changed files with 77 additions and 46 deletions

View File

@@ -4364,8 +4364,12 @@ cgexpr(Cg *c, Node *n, Local *locals)
dname, nvar * esz, cg_frame);
}
const char *slname = mklabel(c, "vararg_sl");
/* #60: route slice-descriptor width through
* vsu->size so a future slice-header bump
* propagates (mirrors wwstage cgcall vararg
* gather using tyslicesize()). */
int sloff = localoff(c, &locals,
slname, 24, cg_frame);
slname, (int)vsu->size, cg_frame);
if (nvar > 0) {
int v_is_tagged = velem &&
tagged_arg_size(velem) > 0;
@@ -7357,8 +7361,10 @@ cgstmt(Cg *c, Node *n, Local **locals, int *frame)
int s0_is_str = u0 && u0->kind == TY_STR;
int s1_is_str = u1 && u1->kind == TY_STR;
if (l0 && l1 && (s0_is_str ^ s1_is_str)) {
int sz0 = s0_is_str ? 16 : 8;
int sz1 = s1_is_str ? 16 : 8;
/* #60: route str-slot width through ty_str->size so #1
* propagates here. Scalar side keeps the 8B slot. */
int sz0 = s0_is_str ? (int)u0->size : 8;
int sz1 = s1_is_str ? (int)u1->size : 8;
int off0 = localoff(c, locals, l0->str, sz0, frame);
int off1 = localoff(c, locals, l1->str, sz1, frame);
if (s0_is_str) {
@@ -7554,9 +7560,12 @@ cgfn(Cg *c, FILE *out, Node *fn)
(is_tagged ? tagged_eb : 1)));
int regs_left = isf ? (8 - fargi) : (6 - argi);
if (regs_left >= eightbytes) {
int sz = slice ? 24 : (is_str ? 16 :
/* #60: route slice/str slot widths through Type.size SSoT
* so #1's ty_str.size bump propagates without retouching
* this site (or its stack-stitch mirror below). */
int sz = (slice || is_str) ? (int)pu->size :
(is_struct ? (int)pu->size :
(is_tagged ? tagged_sz : 8)));
(is_tagged ? tagged_sz : 8));
int off = localoff(c, &locals, p->str, sz, &frame);
if (slice || is_str || is_struct || is_tagged) {
for (int k = 0; k < eightbytes; k++, argi++)
@@ -7583,9 +7592,10 @@ cgfn(Cg *c, FILE *out, Node *fn)
* slot from both sources so the body sees a contiguous
* value. Mirrors the SysV greedy reg fill the caller
* does. */
int sz = slice ? 24 : (is_str ? 16 :
/* #60: same SSoT routing as the regs-fit arm above. */
int sz = (slice || is_str) ? (int)pu->size :
(is_struct ? (int)pu->size :
(is_tagged ? tagged_sz : 8)));
(is_tagged ? tagged_sz : 8));
int off = localoff(c, &locals, p->str, sz, &frame);
extern int cg_stack_arg_cursor;
int k = 0;