wcc/cgen: #19+#22 uniform index element-size for non-ident bases (wwstage)
Indexing a non-ident pointer-yielding base -- a direct cast ((&a):*[4]u32)[i], a call result mk(&a)[i], a slice, a type-assertion -- used wwstage's default 8-byte element stride/load instead of the real element type's, reading garbage (cast-base i32 index: cs=30, ww=0). The cgindex esz derivation gated on a whitelist of base node-kinds (DOT / UN-deref / INDEX); an N_CAST/N_CALL/N_SLICE/N_TYPEASSERT base matched none. Rather than extend the whitelist (whack-a-mole), this mirrors cstage's uniform idx_eff read: N_INDEX keeps its own arm (chained-index byte-id preserved), and every other non-ident base now derives esz/stride/load- width/signedness from the stamped n.type_ -- closing the class by construction (base set ident/dot/un/index/cast/call/slice/typeassert). cstage was already correct (uniform); w6c md5 unchanged. byte-id 990-997 8/8, no lib pin flips. test/wcc/830 (9 base shapes, byte-id per width, signed + unsigned). Folds the N_CALL sibling #22.
This commit is contained in:
@@ -23562,29 +23562,14 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
if (!elem_isarray) {
|
||||
elem_isarray = tinfoisarray(n.type_: *tinfo);
|
||||
};
|
||||
} else { if (base.kind == nkind.N_DOT
|
||||
|| (base.kind == nkind.N_UN && base.op == tkind.TK_STAR)) {
|
||||
// `s.ptr[i]` / struct-field index: stride is the
|
||||
// checker-stamped element tinfo's natural size, the
|
||||
// same idiom as the N_INDEX-base arm below (#60/#72).
|
||||
// cstage idx_eff(base->type)->sub->size (cmd/w6c/
|
||||
// cgen.c:3517-18). Signedness from the same element tinfo
|
||||
// so a signed-narrow field element sign-extends on load
|
||||
// (loadopsz keys on (signed,sz)); cstage's fldloadop reads
|
||||
// it from the element type — align ww up (#255).
|
||||
// N_UN deref base (`(*p)[i]`, #61 C): same stamped-tinfo
|
||||
// source — cstage reads base->type uniformly; without
|
||||
// this arm esz fell to the 8B default (wrong stride for
|
||||
// narrow elements once the deref base materializes).
|
||||
let dt: *tinfo = n.type_: *tinfo;
|
||||
if (dt != nil) { esz = dt.size: i32; signed_elem = typeissigned(dt); elemisstr = typeisstr(dt); elemisslice = typeisslice(dt); float_elem = typeisfloat(dt); f32_elem = typeisf32(dt); };
|
||||
elem_isarray = tinfoisarray(dt);
|
||||
} else { if (base.kind == nkind.N_INDEX) {
|
||||
// #60: chained `names[i][k]` — n.type_ is the checker-
|
||||
// stamped outer element tinfo (indexresult over the inner
|
||||
// index's value type). cstage reads base->type->sub->size
|
||||
// for esz (cmd/w6c/cgen.c:2070-2071). Drops the
|
||||
// indexvaluetnode walk.
|
||||
// indexvaluetnode walk. Kept as its OWN arm (it does not set
|
||||
// elemisstr/elemisslice) so the chained-index byte-id is
|
||||
// preserved verbatim; the catch-all below would re-stamp it.
|
||||
let et: *tinfo = n.type_: *tinfo;
|
||||
if (et != nil) {
|
||||
esz = et.size: i32;
|
||||
@@ -23593,7 +23578,29 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
f32_elem = typeisf32(et);
|
||||
elem_isarray = tinfoisarray(et);
|
||||
};
|
||||
};};};
|
||||
} else {
|
||||
// Every OTHER non-ident base — N_DOT (`s.arr[i]`), N_UN-deref
|
||||
// (`(*p)[i]`, #61), N_CAST (`(e:*[N]T)[i]`, #19old), N_CALL
|
||||
// (`f()[i]`), N_SLICE (`s[a:b][i]`), N_TYPEASSERT
|
||||
// (`(v as *[N]T)[i]`), … — derives esz/stride/load-width/
|
||||
// signedness from the checker-stamped index-RESULT tinfo
|
||||
// n.type_ (the element T: u32->4). cstage reads it UNIFORMLY
|
||||
// via idx_eff(base->type)->sub->size with NO node-kind gate
|
||||
// (cmd/w6c/cgen.c:3517-18); wwstage's prior node-kind whitelist
|
||||
// (DOT/UN/CAST only) silently left N_CALL/N_SLICE/N_TYPEASSERT
|
||||
// (and any future base kind) at the 8B default — wrong stride
|
||||
// AND full-word MOVQ load for narrow elements. One stamped-tinfo
|
||||
// read mirrors cstage and closes the class by construction
|
||||
// (#19old + its CALL/SLICE/TYPEASSERT residuals). esz via
|
||||
// dt.size (type table, rule-13). Signedness from the same tinfo
|
||||
// so a signed-narrow element sign-extends on load (loadopsz keys
|
||||
// on (signed,sz); cstage's fldloadop reads it from the element
|
||||
// type — align ww up, #255). The base ADDRESS materialization
|
||||
// below is unchanged; only the stride/load-width was wrong.
|
||||
let dt: *tinfo = n.type_: *tinfo;
|
||||
if (dt != nil) { esz = dt.size: i32; signed_elem = typeissigned(dt); elemisstr = typeisstr(dt); elemisslice = typeisslice(dt); float_elem = typeisfloat(dt); f32_elem = typeisf32(dt); };
|
||||
elem_isarray = tinfoisarray(dt);
|
||||
};};
|
||||
};
|
||||
// Tagged-union element: load slot words into (AX=tag, DX=val0,
|
||||
// CX=val1) matching the tagged-return ABI so call-arg / let /
|
||||
|
||||
@@ -1900,29 +1900,14 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
if (!elem_isarray) {
|
||||
elem_isarray = tinfoisarray(n.type_: *tinfo);
|
||||
};
|
||||
} else { if (base.kind == nkind.N_DOT
|
||||
|| (base.kind == nkind.N_UN && base.op == tkind.TK_STAR)) {
|
||||
// `s.ptr[i]` / struct-field index: stride is the
|
||||
// checker-stamped element tinfo's natural size, the
|
||||
// same idiom as the N_INDEX-base arm below (#60/#72).
|
||||
// cstage idx_eff(base->type)->sub->size (cmd/w6c/
|
||||
// cgen.c:3517-18). Signedness from the same element tinfo
|
||||
// so a signed-narrow field element sign-extends on load
|
||||
// (loadopsz keys on (signed,sz)); cstage's fldloadop reads
|
||||
// it from the element type — align ww up (#255).
|
||||
// N_UN deref base (`(*p)[i]`, #61 C): same stamped-tinfo
|
||||
// source — cstage reads base->type uniformly; without
|
||||
// this arm esz fell to the 8B default (wrong stride for
|
||||
// narrow elements once the deref base materializes).
|
||||
let dt: *tinfo = n.type_: *tinfo;
|
||||
if (dt != nil) { esz = dt.size: i32; signed_elem = typeissigned(dt); elemisstr = typeisstr(dt); elemisslice = typeisslice(dt); float_elem = typeisfloat(dt); f32_elem = typeisf32(dt); };
|
||||
elem_isarray = tinfoisarray(dt);
|
||||
} else { if (base.kind == nkind.N_INDEX) {
|
||||
// #60: chained `names[i][k]` — n.type_ is the checker-
|
||||
// stamped outer element tinfo (indexresult over the inner
|
||||
// index's value type). cstage reads base->type->sub->size
|
||||
// for esz (cmd/w6c/cgen.c:2070-2071). Drops the
|
||||
// indexvaluetnode walk.
|
||||
// indexvaluetnode walk. Kept as its OWN arm (it does not set
|
||||
// elemisstr/elemisslice) so the chained-index byte-id is
|
||||
// preserved verbatim; the catch-all below would re-stamp it.
|
||||
let et: *tinfo = n.type_: *tinfo;
|
||||
if (et != nil) {
|
||||
esz = et.size: i32;
|
||||
@@ -1931,7 +1916,29 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
f32_elem = typeisf32(et);
|
||||
elem_isarray = tinfoisarray(et);
|
||||
};
|
||||
};};};
|
||||
} else {
|
||||
// Every OTHER non-ident base — N_DOT (`s.arr[i]`), N_UN-deref
|
||||
// (`(*p)[i]`, #61), N_CAST (`(e:*[N]T)[i]`, #19old), N_CALL
|
||||
// (`f()[i]`), N_SLICE (`s[a:b][i]`), N_TYPEASSERT
|
||||
// (`(v as *[N]T)[i]`), … — derives esz/stride/load-width/
|
||||
// signedness from the checker-stamped index-RESULT tinfo
|
||||
// n.type_ (the element T: u32->4). cstage reads it UNIFORMLY
|
||||
// via idx_eff(base->type)->sub->size with NO node-kind gate
|
||||
// (cmd/w6c/cgen.c:3517-18); wwstage's prior node-kind whitelist
|
||||
// (DOT/UN/CAST only) silently left N_CALL/N_SLICE/N_TYPEASSERT
|
||||
// (and any future base kind) at the 8B default — wrong stride
|
||||
// AND full-word MOVQ load for narrow elements. One stamped-tinfo
|
||||
// read mirrors cstage and closes the class by construction
|
||||
// (#19old + its CALL/SLICE/TYPEASSERT residuals). esz via
|
||||
// dt.size (type table, rule-13). Signedness from the same tinfo
|
||||
// so a signed-narrow element sign-extends on load (loadopsz keys
|
||||
// on (signed,sz); cstage's fldloadop reads it from the element
|
||||
// type — align ww up, #255). The base ADDRESS materialization
|
||||
// below is unchanged; only the stride/load-width was wrong.
|
||||
let dt: *tinfo = n.type_: *tinfo;
|
||||
if (dt != nil) { esz = dt.size: i32; signed_elem = typeissigned(dt); elemisstr = typeisstr(dt); elemisslice = typeisslice(dt); float_elem = typeisfloat(dt); f32_elem = typeisf32(dt); };
|
||||
elem_isarray = tinfoisarray(dt);
|
||||
};};
|
||||
};
|
||||
// Tagged-union element: load slot words into (AX=tag, DX=val0,
|
||||
// CX=val1) matching the tagged-return ABI so call-arg / let /
|
||||
|
||||
@@ -23562,29 +23562,14 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
if (!elem_isarray) {
|
||||
elem_isarray = tinfoisarray(n.type_: *tinfo);
|
||||
};
|
||||
} else { if (base.kind == nkind.N_DOT
|
||||
|| (base.kind == nkind.N_UN && base.op == tkind.TK_STAR)) {
|
||||
// `s.ptr[i]` / struct-field index: stride is the
|
||||
// checker-stamped element tinfo's natural size, the
|
||||
// same idiom as the N_INDEX-base arm below (#60/#72).
|
||||
// cstage idx_eff(base->type)->sub->size (cmd/w6c/
|
||||
// cgen.c:3517-18). Signedness from the same element tinfo
|
||||
// so a signed-narrow field element sign-extends on load
|
||||
// (loadopsz keys on (signed,sz)); cstage's fldloadop reads
|
||||
// it from the element type — align ww up (#255).
|
||||
// N_UN deref base (`(*p)[i]`, #61 C): same stamped-tinfo
|
||||
// source — cstage reads base->type uniformly; without
|
||||
// this arm esz fell to the 8B default (wrong stride for
|
||||
// narrow elements once the deref base materializes).
|
||||
let dt: *tinfo = n.type_: *tinfo;
|
||||
if (dt != nil) { esz = dt.size: i32; signed_elem = typeissigned(dt); elemisstr = typeisstr(dt); elemisslice = typeisslice(dt); float_elem = typeisfloat(dt); f32_elem = typeisf32(dt); };
|
||||
elem_isarray = tinfoisarray(dt);
|
||||
} else { if (base.kind == nkind.N_INDEX) {
|
||||
// #60: chained `names[i][k]` — n.type_ is the checker-
|
||||
// stamped outer element tinfo (indexresult over the inner
|
||||
// index's value type). cstage reads base->type->sub->size
|
||||
// for esz (cmd/w6c/cgen.c:2070-2071). Drops the
|
||||
// indexvaluetnode walk.
|
||||
// indexvaluetnode walk. Kept as its OWN arm (it does not set
|
||||
// elemisstr/elemisslice) so the chained-index byte-id is
|
||||
// preserved verbatim; the catch-all below would re-stamp it.
|
||||
let et: *tinfo = n.type_: *tinfo;
|
||||
if (et != nil) {
|
||||
esz = et.size: i32;
|
||||
@@ -23593,7 +23578,29 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
f32_elem = typeisf32(et);
|
||||
elem_isarray = tinfoisarray(et);
|
||||
};
|
||||
};};};
|
||||
} else {
|
||||
// Every OTHER non-ident base — N_DOT (`s.arr[i]`), N_UN-deref
|
||||
// (`(*p)[i]`, #61), N_CAST (`(e:*[N]T)[i]`, #19old), N_CALL
|
||||
// (`f()[i]`), N_SLICE (`s[a:b][i]`), N_TYPEASSERT
|
||||
// (`(v as *[N]T)[i]`), … — derives esz/stride/load-width/
|
||||
// signedness from the checker-stamped index-RESULT tinfo
|
||||
// n.type_ (the element T: u32->4). cstage reads it UNIFORMLY
|
||||
// via idx_eff(base->type)->sub->size with NO node-kind gate
|
||||
// (cmd/w6c/cgen.c:3517-18); wwstage's prior node-kind whitelist
|
||||
// (DOT/UN/CAST only) silently left N_CALL/N_SLICE/N_TYPEASSERT
|
||||
// (and any future base kind) at the 8B default — wrong stride
|
||||
// AND full-word MOVQ load for narrow elements. One stamped-tinfo
|
||||
// read mirrors cstage and closes the class by construction
|
||||
// (#19old + its CALL/SLICE/TYPEASSERT residuals). esz via
|
||||
// dt.size (type table, rule-13). Signedness from the same tinfo
|
||||
// so a signed-narrow element sign-extends on load (loadopsz keys
|
||||
// on (signed,sz); cstage's fldloadop reads it from the element
|
||||
// type — align ww up, #255). The base ADDRESS materialization
|
||||
// below is unchanged; only the stride/load-width was wrong.
|
||||
let dt: *tinfo = n.type_: *tinfo;
|
||||
if (dt != nil) { esz = dt.size: i32; signed_elem = typeissigned(dt); elemisstr = typeisstr(dt); elemisslice = typeisslice(dt); float_elem = typeisfloat(dt); f32_elem = typeisf32(dt); };
|
||||
elem_isarray = tinfoisarray(dt);
|
||||
};};
|
||||
};
|
||||
// Tagged-union element: load slot words into (AX=tag, DX=val0,
|
||||
// CX=val1) matching the tagged-return ABI so call-arg / let /
|
||||
|
||||
Reference in New Issue
Block a user