wcc_ww/cgen: #101 narrow-alias fill-stride via aliasprimsize SSoT
A struct-literal array fill sized a narrow-alias element off a bare
primsize(name): `type my32 = u32` gave primsize("my32")=0, so the
element width defaulted to 8 and a [3]my32 strode MOVQ -24/-16/-8 —
field n collided with arr[2] (kw1_101 run exit 1). cstage chases
my32->u32->4 (MOVL stride-4) at the twin sites and is runtime-correct;
this is a ww-only align-up, cs untouched.
Fix: a new aliasprimsize(c, nm) SSoT helper — primsize(nm), else an
aliaslookup-chase N_TNAME loop then primsize — and route the SIZE-use
primsize() family through it. The 7 c-bearing bare-no-chase size-use
sites are routed: cgen:993 (letemitsize), cgenstmt:1896 (cgarrlitfillbp),
cgenutil:1579 (elemsizeofc fallback)/1657+1665 (nodeprimwidth)/4791
(cgstructlitfill = the kw1_101 site), cgenexpr:6902 (cgcall vararg esz).
This is the rule-13 close-by-construction shape (one accessor for
"resolved primitive size"), not a per-site patch.
kw1_101 is the SOLE asm mover (byte-id NO->YES, run 1->0, MOVL
stride-4); every other routed site is latent/byte-neutral. Bootstrap:
all 5 combined units stay w6c==w6c_ww byte-identical. sizelint 0,
peellint 0, test-unit 296/296.
Scope fence (rob route-7-decline-6 ruling): three DESIGNED-exemption
sites carry inline primsize-ok annotations — elemsizeof :1475/:1499 and
paramfieldsize :3541 are structural (no-`c`, non-chasing) BY DESIGN;
their alias-chasing twin elemsizeofc is the routed :1579 leg. These are
the #109 peellint-whitelist seeds. Three further declines are already
correct chasing paths, not bare-no-chase bug shapes (typenodeprimresolved
:2026 / exprprimresolved :2063 are the chase machinery itself; cgassign
:7631 already chases via typenodeprimresolved, #11). The ~17 GUARD sites
(is-primitive dispatch) + the peellint finale are the committed #109
follow-on. Threading `c` into the structural sizers is dormant #110.
#101
This commit is contained in:
@@ -17613,6 +17613,10 @@ fn elemsizeof(t: *node) i32 = {
|
||||
// reads eff->sub->size (cmd/w6c/cgen.c N_INDEX).
|
||||
if (streq(nm, "str")) { return primtypesize("u8"): i32; };
|
||||
// Indexing a primitive name (rare): element size = the prim.
|
||||
// primsize-ok (#101/#109): elemsizeof is the STRUCTURAL (non-
|
||||
// chasing) sizer by design — its alias-resolving twin elemsizeofc
|
||||
// owns the chase (routed through aliasprimsize at the :1579 leg).
|
||||
// A bare primsize here is correct, not the #101 bug shape.
|
||||
let ps: i32 = primsize(nm);
|
||||
if (ps > 0) { return ps; };
|
||||
return 1;
|
||||
@@ -17637,6 +17641,8 @@ fn elemsizeof(t: *node) i32 = {
|
||||
let nm: str = elem.str;
|
||||
// str element is 16B (ptr+len). primsize returns 0 for it.
|
||||
if (streq(nm, "str")) { return primtypesize("str"): i32; };
|
||||
// primsize-ok (#101/#109): structural sizer — the chase lives
|
||||
// in elemsizeofc (:1579), not here. See the :1475 leg.
|
||||
let ps: i32 = primsize(nm);
|
||||
if (ps > 0) { return ps; };
|
||||
};
|
||||
@@ -17717,7 +17723,7 @@ fn elemsizeofc(c: *cgen, t: *node) i32 = {
|
||||
let elem: *node = idxelemtn(t);
|
||||
if (elem == nil) { return direct; };
|
||||
if (elem.kind == nkind.N_TNAME) {
|
||||
let ps: i32 = primsize(elem.str);
|
||||
let ps: i32 = aliasprimsize(c, elem.str);
|
||||
if (ps > 0) { return ps; };
|
||||
};
|
||||
return slotsize(c, elem);
|
||||
@@ -17795,7 +17801,7 @@ fn nodeprimwidth(c: *cgen, n: *node) i32 = {
|
||||
if (lc != nil) {
|
||||
let tn: *node = lc.tnode;
|
||||
if (tn != nil) {
|
||||
if (tn.kind == nkind.N_TNAME) { return primsize(tn.str); };
|
||||
if (tn.kind == nkind.N_TNAME) { return aliasprimsize(c, tn.str); };
|
||||
};
|
||||
};
|
||||
return 0;
|
||||
@@ -17803,7 +17809,7 @@ fn nodeprimwidth(c: *cgen, n: *node) i32 = {
|
||||
if (k == nkind.N_CAST) {
|
||||
let tn: *node = n.rhs;
|
||||
if (tn != nil) {
|
||||
if (tn.kind == nkind.N_TNAME) { return primsize(tn.str); };
|
||||
if (tn.kind == nkind.N_TNAME) { return aliasprimsize(c, tn.str); };
|
||||
};
|
||||
return 0;
|
||||
};
|
||||
@@ -18136,6 +18142,31 @@ fn primsize(name: str) i32 = {
|
||||
return 0;
|
||||
};
|
||||
|
||||
// aliasprimsize — resolved primitive byte width for a type NAME: the
|
||||
// prim width if `nm` is itself a primitive, else chase the alias chain
|
||||
// (aliaslookup) to its bottom and take that prim's width. Returns 0
|
||||
// when the name doesn't reduce to a width-known primitive (struct /
|
||||
// tagged / `!`/enum-bottom / unresolved). SSoT for the size-use
|
||||
// primsize() family: a bare primsize(name) is alias-blind — a narrow
|
||||
// alias (`type my32 = u32`) returns 0, defaulting the stride/width to
|
||||
// 8 (the #101 struct-fill miscompile: [3]my32 strode 8 not 4, field n
|
||||
// collided with arr[2]). cstage chases my32→u32→4 via type_chase_named
|
||||
// at the twin sites; this is the ww align-up. The bare-primsize GUARD
|
||||
// family (is-primitive dispatch) is the #109 follow-on, NOT routed
|
||||
// here. #101.
|
||||
fn aliasprimsize(c: *cgen, nm: str) i32 = {
|
||||
let ps: i32 = primsize(nm);
|
||||
if (ps > 0) { return ps; };
|
||||
let cur: *node = aliaslookup(c, nm);
|
||||
for (cur != nil) {
|
||||
if (cur.kind != nkind.N_TNAME) { return 0; };
|
||||
let p: i32 = primsize(cur.str);
|
||||
if (p > 0) { return p; };
|
||||
cur = aliaslookup(c, cur.str);
|
||||
};
|
||||
return 0;
|
||||
};
|
||||
|
||||
// typenodeprimresolved — walk N_TBANG / N_TENUM / N_TNAME alias
|
||||
// chains to the underlying primitive, returning its byte size and
|
||||
// signedness. Sets *sz_out = 0 when the type doesn't reduce to a
|
||||
@@ -20929,7 +20960,7 @@ fn cgstructlitfill(c: *cgen, si: *structinfo, lit: *node,
|
||||
let esz: i32 = 8;
|
||||
if (elemn != nil) {
|
||||
if (elemn.kind == nkind.N_TNAME) {
|
||||
let ps: i32 = primsize(elemn.str);
|
||||
let ps: i32 = aliasprimsize(c, elemn.str);
|
||||
if (ps > 0) { esz = ps; };
|
||||
};
|
||||
};
|
||||
@@ -28044,7 +28075,7 @@ fn cgcall(c: *cgen, n: *node) void = {
|
||||
let esz: i32 = 8;
|
||||
if (velem != nil) {
|
||||
if (velem.kind == nkind.N_TNAME) {
|
||||
let ps: i32 = primsize(velem.str);
|
||||
let ps: i32 = aliasprimsize(c, velem.str);
|
||||
if (ps > 0) { esz = ps; }
|
||||
else { esz = slotsize(c, velem); };
|
||||
} else {
|
||||
@@ -34352,7 +34383,7 @@ fn cgarrlitfillbp(c: *cgen, arrtn: *node, rhs: *node, off: i32) void = {
|
||||
esz = primtypesize("str"): i32;
|
||||
isstrel = true;
|
||||
} else {
|
||||
let ps: i32 = primsize(elemn.str);
|
||||
let ps: i32 = aliasprimsize(c, elemn.str);
|
||||
if (ps > 0) { esz = ps; };
|
||||
};
|
||||
};
|
||||
@@ -35997,6 +36028,11 @@ fn paramfieldsize(t: *node) i32 = {
|
||||
if (k == nkind.N_TNAME) {
|
||||
let nm: str = t.str;
|
||||
if (streq(nm, "str")) { return primtypesize("str"): i32; };
|
||||
// primsize-ok (#101/#109): paramfieldsize is a STRUCTURAL
|
||||
// (no-`c`, no-chase) sizer by design — it takes a *node, not a
|
||||
// *cgen, so it cannot run aliasprimsize's aliaslookup chase
|
||||
// (threading c is the dormant #110). A bare primsize is correct
|
||||
// here, not the #101 narrow-alias bug shape.
|
||||
let ps: i32 = primsize(nm);
|
||||
if (ps > 0) { return ps; };
|
||||
};
|
||||
@@ -38157,7 +38193,7 @@ fn letemitsize(c: *cgen, d: *node) i32 = {
|
||||
let esz: i32 = 8;
|
||||
if (elemn != nil) {
|
||||
if (elemn.kind == nkind.N_TNAME) {
|
||||
let ps: i32 = primsize(elemn.str);
|
||||
let ps: i32 = aliasprimsize(c, elemn.str);
|
||||
if (ps > 0) { esz = ps; };
|
||||
};
|
||||
};
|
||||
|
||||
@@ -990,7 +990,7 @@ fn letemitsize(c: *cgen, d: *node) i32 = {
|
||||
let esz: i32 = 8;
|
||||
if (elemn != nil) {
|
||||
if (elemn.kind == nkind.N_TNAME) {
|
||||
let ps: i32 = primsize(elemn.str);
|
||||
let ps: i32 = aliasprimsize(c, elemn.str);
|
||||
if (ps > 0) { esz = ps; };
|
||||
};
|
||||
};
|
||||
|
||||
@@ -6899,7 +6899,7 @@ fn cgcall(c: *cgen, n: *node) void = {
|
||||
let esz: i32 = 8;
|
||||
if (velem != nil) {
|
||||
if (velem.kind == nkind.N_TNAME) {
|
||||
let ps: i32 = primsize(velem.str);
|
||||
let ps: i32 = aliasprimsize(c, velem.str);
|
||||
if (ps > 0) { esz = ps; }
|
||||
else { esz = slotsize(c, velem); };
|
||||
} else {
|
||||
|
||||
@@ -1893,7 +1893,7 @@ fn cgarrlitfillbp(c: *cgen, arrtn: *node, rhs: *node, off: i32) void = {
|
||||
esz = primtypesize("str"): i32;
|
||||
isstrel = true;
|
||||
} else {
|
||||
let ps: i32 = primsize(elemn.str);
|
||||
let ps: i32 = aliasprimsize(c, elemn.str);
|
||||
if (ps > 0) { esz = ps; };
|
||||
};
|
||||
};
|
||||
@@ -3538,6 +3538,11 @@ fn paramfieldsize(t: *node) i32 = {
|
||||
if (k == nkind.N_TNAME) {
|
||||
let nm: str = t.str;
|
||||
if (streq(nm, "str")) { return primtypesize("str"): i32; };
|
||||
// primsize-ok (#101/#109): paramfieldsize is a STRUCTURAL
|
||||
// (no-`c`, no-chase) sizer by design — it takes a *node, not a
|
||||
// *cgen, so it cannot run aliasprimsize's aliaslookup chase
|
||||
// (threading c is the dormant #110). A bare primsize is correct
|
||||
// here, not the #101 narrow-alias bug shape.
|
||||
let ps: i32 = primsize(nm);
|
||||
if (ps > 0) { return ps; };
|
||||
};
|
||||
|
||||
@@ -1472,6 +1472,10 @@ fn elemsizeof(t: *node) i32 = {
|
||||
// reads eff->sub->size (cmd/w6c/cgen.c N_INDEX).
|
||||
if (streq(nm, "str")) { return primtypesize("u8"): i32; };
|
||||
// Indexing a primitive name (rare): element size = the prim.
|
||||
// primsize-ok (#101/#109): elemsizeof is the STRUCTURAL (non-
|
||||
// chasing) sizer by design — its alias-resolving twin elemsizeofc
|
||||
// owns the chase (routed through aliasprimsize at the :1579 leg).
|
||||
// A bare primsize here is correct, not the #101 bug shape.
|
||||
let ps: i32 = primsize(nm);
|
||||
if (ps > 0) { return ps; };
|
||||
return 1;
|
||||
@@ -1496,6 +1500,8 @@ fn elemsizeof(t: *node) i32 = {
|
||||
let nm: str = elem.str;
|
||||
// str element is 16B (ptr+len). primsize returns 0 for it.
|
||||
if (streq(nm, "str")) { return primtypesize("str"): i32; };
|
||||
// primsize-ok (#101/#109): structural sizer — the chase lives
|
||||
// in elemsizeofc (:1579), not here. See the :1475 leg.
|
||||
let ps: i32 = primsize(nm);
|
||||
if (ps > 0) { return ps; };
|
||||
};
|
||||
@@ -1576,7 +1582,7 @@ fn elemsizeofc(c: *cgen, t: *node) i32 = {
|
||||
let elem: *node = idxelemtn(t);
|
||||
if (elem == nil) { return direct; };
|
||||
if (elem.kind == nkind.N_TNAME) {
|
||||
let ps: i32 = primsize(elem.str);
|
||||
let ps: i32 = aliasprimsize(c, elem.str);
|
||||
if (ps > 0) { return ps; };
|
||||
};
|
||||
return slotsize(c, elem);
|
||||
@@ -1654,7 +1660,7 @@ fn nodeprimwidth(c: *cgen, n: *node) i32 = {
|
||||
if (lc != nil) {
|
||||
let tn: *node = lc.tnode;
|
||||
if (tn != nil) {
|
||||
if (tn.kind == nkind.N_TNAME) { return primsize(tn.str); };
|
||||
if (tn.kind == nkind.N_TNAME) { return aliasprimsize(c, tn.str); };
|
||||
};
|
||||
};
|
||||
return 0;
|
||||
@@ -1662,7 +1668,7 @@ fn nodeprimwidth(c: *cgen, n: *node) i32 = {
|
||||
if (k == nkind.N_CAST) {
|
||||
let tn: *node = n.rhs;
|
||||
if (tn != nil) {
|
||||
if (tn.kind == nkind.N_TNAME) { return primsize(tn.str); };
|
||||
if (tn.kind == nkind.N_TNAME) { return aliasprimsize(c, tn.str); };
|
||||
};
|
||||
return 0;
|
||||
};
|
||||
@@ -1995,6 +2001,31 @@ fn primsize(name: str) i32 = {
|
||||
return 0;
|
||||
};
|
||||
|
||||
// aliasprimsize — resolved primitive byte width for a type NAME: the
|
||||
// prim width if `nm` is itself a primitive, else chase the alias chain
|
||||
// (aliaslookup) to its bottom and take that prim's width. Returns 0
|
||||
// when the name doesn't reduce to a width-known primitive (struct /
|
||||
// tagged / `!`/enum-bottom / unresolved). SSoT for the size-use
|
||||
// primsize() family: a bare primsize(name) is alias-blind — a narrow
|
||||
// alias (`type my32 = u32`) returns 0, defaulting the stride/width to
|
||||
// 8 (the #101 struct-fill miscompile: [3]my32 strode 8 not 4, field n
|
||||
// collided with arr[2]). cstage chases my32→u32→4 via type_chase_named
|
||||
// at the twin sites; this is the ww align-up. The bare-primsize GUARD
|
||||
// family (is-primitive dispatch) is the #109 follow-on, NOT routed
|
||||
// here. #101.
|
||||
fn aliasprimsize(c: *cgen, nm: str) i32 = {
|
||||
let ps: i32 = primsize(nm);
|
||||
if (ps > 0) { return ps; };
|
||||
let cur: *node = aliaslookup(c, nm);
|
||||
for (cur != nil) {
|
||||
if (cur.kind != nkind.N_TNAME) { return 0; };
|
||||
let p: i32 = primsize(cur.str);
|
||||
if (p > 0) { return p; };
|
||||
cur = aliaslookup(c, cur.str);
|
||||
};
|
||||
return 0;
|
||||
};
|
||||
|
||||
// typenodeprimresolved — walk N_TBANG / N_TENUM / N_TNAME alias
|
||||
// chains to the underlying primitive, returning its byte size and
|
||||
// signedness. Sets *sz_out = 0 when the type doesn't reduce to a
|
||||
@@ -4788,7 +4819,7 @@ fn cgstructlitfill(c: *cgen, si: *structinfo, lit: *node,
|
||||
let esz: i32 = 8;
|
||||
if (elemn != nil) {
|
||||
if (elemn.kind == nkind.N_TNAME) {
|
||||
let ps: i32 = primsize(elemn.str);
|
||||
let ps: i32 = aliasprimsize(c, elemn.str);
|
||||
if (ps > 0) { esz = ps; };
|
||||
};
|
||||
};
|
||||
|
||||
@@ -17613,6 +17613,10 @@ fn elemsizeof(t: *node) i32 = {
|
||||
// reads eff->sub->size (cmd/w6c/cgen.c N_INDEX).
|
||||
if (streq(nm, "str")) { return primtypesize("u8"): i32; };
|
||||
// Indexing a primitive name (rare): element size = the prim.
|
||||
// primsize-ok (#101/#109): elemsizeof is the STRUCTURAL (non-
|
||||
// chasing) sizer by design — its alias-resolving twin elemsizeofc
|
||||
// owns the chase (routed through aliasprimsize at the :1579 leg).
|
||||
// A bare primsize here is correct, not the #101 bug shape.
|
||||
let ps: i32 = primsize(nm);
|
||||
if (ps > 0) { return ps; };
|
||||
return 1;
|
||||
@@ -17637,6 +17641,8 @@ fn elemsizeof(t: *node) i32 = {
|
||||
let nm: str = elem.str;
|
||||
// str element is 16B (ptr+len). primsize returns 0 for it.
|
||||
if (streq(nm, "str")) { return primtypesize("str"): i32; };
|
||||
// primsize-ok (#101/#109): structural sizer — the chase lives
|
||||
// in elemsizeofc (:1579), not here. See the :1475 leg.
|
||||
let ps: i32 = primsize(nm);
|
||||
if (ps > 0) { return ps; };
|
||||
};
|
||||
@@ -17717,7 +17723,7 @@ fn elemsizeofc(c: *cgen, t: *node) i32 = {
|
||||
let elem: *node = idxelemtn(t);
|
||||
if (elem == nil) { return direct; };
|
||||
if (elem.kind == nkind.N_TNAME) {
|
||||
let ps: i32 = primsize(elem.str);
|
||||
let ps: i32 = aliasprimsize(c, elem.str);
|
||||
if (ps > 0) { return ps; };
|
||||
};
|
||||
return slotsize(c, elem);
|
||||
@@ -17795,7 +17801,7 @@ fn nodeprimwidth(c: *cgen, n: *node) i32 = {
|
||||
if (lc != nil) {
|
||||
let tn: *node = lc.tnode;
|
||||
if (tn != nil) {
|
||||
if (tn.kind == nkind.N_TNAME) { return primsize(tn.str); };
|
||||
if (tn.kind == nkind.N_TNAME) { return aliasprimsize(c, tn.str); };
|
||||
};
|
||||
};
|
||||
return 0;
|
||||
@@ -17803,7 +17809,7 @@ fn nodeprimwidth(c: *cgen, n: *node) i32 = {
|
||||
if (k == nkind.N_CAST) {
|
||||
let tn: *node = n.rhs;
|
||||
if (tn != nil) {
|
||||
if (tn.kind == nkind.N_TNAME) { return primsize(tn.str); };
|
||||
if (tn.kind == nkind.N_TNAME) { return aliasprimsize(c, tn.str); };
|
||||
};
|
||||
return 0;
|
||||
};
|
||||
@@ -18136,6 +18142,31 @@ fn primsize(name: str) i32 = {
|
||||
return 0;
|
||||
};
|
||||
|
||||
// aliasprimsize — resolved primitive byte width for a type NAME: the
|
||||
// prim width if `nm` is itself a primitive, else chase the alias chain
|
||||
// (aliaslookup) to its bottom and take that prim's width. Returns 0
|
||||
// when the name doesn't reduce to a width-known primitive (struct /
|
||||
// tagged / `!`/enum-bottom / unresolved). SSoT for the size-use
|
||||
// primsize() family: a bare primsize(name) is alias-blind — a narrow
|
||||
// alias (`type my32 = u32`) returns 0, defaulting the stride/width to
|
||||
// 8 (the #101 struct-fill miscompile: [3]my32 strode 8 not 4, field n
|
||||
// collided with arr[2]). cstage chases my32→u32→4 via type_chase_named
|
||||
// at the twin sites; this is the ww align-up. The bare-primsize GUARD
|
||||
// family (is-primitive dispatch) is the #109 follow-on, NOT routed
|
||||
// here. #101.
|
||||
fn aliasprimsize(c: *cgen, nm: str) i32 = {
|
||||
let ps: i32 = primsize(nm);
|
||||
if (ps > 0) { return ps; };
|
||||
let cur: *node = aliaslookup(c, nm);
|
||||
for (cur != nil) {
|
||||
if (cur.kind != nkind.N_TNAME) { return 0; };
|
||||
let p: i32 = primsize(cur.str);
|
||||
if (p > 0) { return p; };
|
||||
cur = aliaslookup(c, cur.str);
|
||||
};
|
||||
return 0;
|
||||
};
|
||||
|
||||
// typenodeprimresolved — walk N_TBANG / N_TENUM / N_TNAME alias
|
||||
// chains to the underlying primitive, returning its byte size and
|
||||
// signedness. Sets *sz_out = 0 when the type doesn't reduce to a
|
||||
@@ -20929,7 +20960,7 @@ fn cgstructlitfill(c: *cgen, si: *structinfo, lit: *node,
|
||||
let esz: i32 = 8;
|
||||
if (elemn != nil) {
|
||||
if (elemn.kind == nkind.N_TNAME) {
|
||||
let ps: i32 = primsize(elemn.str);
|
||||
let ps: i32 = aliasprimsize(c, elemn.str);
|
||||
if (ps > 0) { esz = ps; };
|
||||
};
|
||||
};
|
||||
@@ -28044,7 +28075,7 @@ fn cgcall(c: *cgen, n: *node) void = {
|
||||
let esz: i32 = 8;
|
||||
if (velem != nil) {
|
||||
if (velem.kind == nkind.N_TNAME) {
|
||||
let ps: i32 = primsize(velem.str);
|
||||
let ps: i32 = aliasprimsize(c, velem.str);
|
||||
if (ps > 0) { esz = ps; }
|
||||
else { esz = slotsize(c, velem); };
|
||||
} else {
|
||||
@@ -34352,7 +34383,7 @@ fn cgarrlitfillbp(c: *cgen, arrtn: *node, rhs: *node, off: i32) void = {
|
||||
esz = primtypesize("str"): i32;
|
||||
isstrel = true;
|
||||
} else {
|
||||
let ps: i32 = primsize(elemn.str);
|
||||
let ps: i32 = aliasprimsize(c, elemn.str);
|
||||
if (ps > 0) { esz = ps; };
|
||||
};
|
||||
};
|
||||
@@ -35997,6 +36028,11 @@ fn paramfieldsize(t: *node) i32 = {
|
||||
if (k == nkind.N_TNAME) {
|
||||
let nm: str = t.str;
|
||||
if (streq(nm, "str")) { return primtypesize("str"): i32; };
|
||||
// primsize-ok (#101/#109): paramfieldsize is a STRUCTURAL
|
||||
// (no-`c`, no-chase) sizer by design — it takes a *node, not a
|
||||
// *cgen, so it cannot run aliasprimsize's aliaslookup chase
|
||||
// (threading c is the dormant #110). A bare primsize is correct
|
||||
// here, not the #101 narrow-alias bug shape.
|
||||
let ps: i32 = primsize(nm);
|
||||
if (ps > 0) { return ps; };
|
||||
};
|
||||
@@ -38157,7 +38193,7 @@ fn letemitsize(c: *cgen, d: *node) i32 = {
|
||||
let esz: i32 = 8;
|
||||
if (elemn != nil) {
|
||||
if (elemn.kind == nkind.N_TNAME) {
|
||||
let ps: i32 = primsize(elemn.str);
|
||||
let ps: i32 = aliasprimsize(c, elemn.str);
|
||||
if (ps > 0) { esz = ps; };
|
||||
};
|
||||
};
|
||||
|
||||
@@ -402,6 +402,36 @@ static const struct row rows[] = {
|
||||
" if (xs[0]: i64 + xs[1]: i64 + xs[2]: i64 != 18) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
/* #101: NARROW-alias struct-FILL stride (the cgstructlitfill
|
||||
* :4791 leg, twin of esub_2lvl's INDEX leg). Pre-fold ww sized
|
||||
* the [3]my32 element off primsize("my32")=0 → 8B-default stride,
|
||||
* so the fill stored at -24/-16/-8 and field n collided with
|
||||
* arr[2] (run exit 1); cs chased my32→u32→4 (MOVL stride-4). The
|
||||
* aliasprimsize route aligns ww UP — kw1_101 was the SOLE corpus
|
||||
* mover (cs0/ww1 byteid-NO → byteid-YES + run 0). */
|
||||
{ "kw1_101",
|
||||
"package main;\n"
|
||||
"type my32 = u32;\n"
|
||||
"type S = struct { arr: [3]my32, n: int };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let s = S { arr = [10u32, 20u32, 30u32], n = 4 };\n"
|
||||
" if (s.arr[0] + s.arr[1] + s.arr[2] != 60u32) { return 1; };\n"
|
||||
" if (s.n != 4) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
/* #101 control: a DIFFERENT narrow width (u16, stride-2 MOVW)
|
||||
* proves the routed esz is width-general, not a 4-only patch.
|
||||
* fld n must survive the fill untouched. */
|
||||
{ "kw1_ctl16",
|
||||
"package main;\n"
|
||||
"type my16 = u16;\n"
|
||||
"type S2 = struct { arr: [4]my16, n: int };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let s = S2 { arr = [1u16, 2u16, 3u16, 4u16], n = 9 };\n"
|
||||
" if (s.arr[0] + s.arr[1] + s.arr[2] + s.arr[3] != 10u16) { return 1; };\n"
|
||||
" if (s.n != 9) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
/* ---- c4: cast/is/try family */
|
||||
{ "strcast_2lvl",
|
||||
"package main;\n"
|
||||
|
||||
Reference in New Issue
Block a user