selfhost/cmd/wcc: route remaining wwstage size dispatch through SSoT

Followup to 8e93b31 (#43).  Audit caught dispatch-gate sites the
sweep missed:

  - cgen.ww letpreintern's `sz == 16` str-let detector — would
    desync from emitletdataw's matching `sz == primtypesize("str"):
    i32` strlit-init branch under #1.
  - cgenstmt.ww cglet str-init MOVQ-BX gate and slice-init MOVQ-BX/CX
    gate (and the belt-and-suspenders N_TSLICE shape check at l.607).
  - cgenexpr.ww cgindex str-element loads (3 sites: globalarr,
    baselocal, generic fallback) and the matching cgassign N_INDEX
    str-element write pair (BX spill + post-index store).

All gates now read `primtypesize("str"): i32` / `tyslicesize(): i32`,
so #1's ty_str.size bump propagates through the same two-place edit
the original commit advertised.  Combined files (w6c/wwdump) updated
in lockstep.

131/131 + 994 + 995 byte-identity green; smoke.combined.ww (lib-only
consumer) emits the same asm pre vs post, confirming the change is
SSoT routing only (no behaviour shift).
This commit is contained in:
2026-05-20 09:06:50 +09:00
parent 8e93b31088
commit 087c85c3cf
5 changed files with 108 additions and 30 deletions

View File

@@ -799,7 +799,9 @@ fn cgindex(c: *cgen, n: *node) void = {
emitline("\tMOVQ\t(BX), AX\n");
return;
};
if (esz == 16) {
// #43: str element-stride routes through primtypesize so the
// 16-vs-24 dispatch tracks ty_str.size for #1.
if (esz == primtypesize("str"): i32) {
emitline("\tMOVQ\t8(BX), CX\n");
emitline("\tMOVQ\t(BX), AX\n");
emitline("\tMOVQ\tCX, BX\n");
@@ -838,9 +840,10 @@ fn cgindex(c: *cgen, n: *node) void = {
emitline("\tMOVQ\t(BX), AX\n");
return;
};
// str element (16B): load (ptr, len) into (AX, BX) so
// str element (16B today): load (ptr, len) into (AX, BX) so
// the value flows through the str-rhs convention.
if (esz == 16) {
// #43: route via primtypesize so the stride tracks #1.
if (esz == primtypesize("str"): i32) {
emitline("\tMOVQ\t8(BX), CX\n");
emitline("\tMOVQ\t(BX), AX\n");
emitline("\tMOVQ\tCX, BX\n");
@@ -870,7 +873,9 @@ fn cgindex(c: *cgen, n: *node) void = {
emitline("\tMOVQ\t(BX), AX\n");
return;
};
if (esz == 16) {
// #43: str element-stride routes through primtypesize so the
// 16-vs-24 dispatch tracks ty_str.size for #1.
if (esz == primtypesize("str"): i32) {
emitline("\tMOVQ\t8(AX), BX\n");
emitline("\tMOVQ\t(AX), AX\n");
return;
@@ -3764,7 +3769,10 @@ fn cgassign(c: *cgen, n: *node) void = {
};
};
cgexpr(c, n.rhs); // value → AX
if (esz == 16) { emitline("\tPUSHQ\tBX\n"); };
// #43: spill BX (str.len) before computing
// the index so the post-index store can pop
// it; the stride gate tracks ty_str.size.
if (esz == primtypesize("str"): i32) { emitline("\tPUSHQ\tBX\n"); };
emitline("\tPUSHQ\tAX\n");
cgexpr(c, idx); // idx → AX
if (esz > 1) {
@@ -3802,7 +3810,10 @@ fn cgassign(c: *cgen, n: *node) void = {
emitline("\tPOPQ\tAX\n"); // scaled idx
emitline("\tADDQ\tAX, BX\n");
emitline("\tPOPQ\tAX\n"); // value
if (esz == 16) {
// #43: str-element write — pop the saved
// .len and store both halves. Stride gate
// routes through primtypesize for #1.
if (esz == primtypesize("str"): i32) {
emitline("\tMOVQ\tAX, (BX)\n");
emitline("\tPOPQ\tCX\n");
emitline("\tMOVQ\tCX, 8(BX)\n");