wcc_ww/cgen: c3 in-file peel sites — exprprimresolved base walk chases (B1); elemsizeofc alias-indexable leg (B3); B2 probe-cleared
F2a batch-2 c3, probe-decided per rob's spec. B1 (exprprimresolved N_DOT, was :2073/:2075/:2078): the hand-rolled NAMED->PTR->NAMED->STRUCT walk ran out at a 3-level alias base or a ptr-to-2-level base — the cast-source width stayed unknowable on wwstage only, so the #33 identity clamp was emitted where cstage skipped it (runtime-correct both, byte-id NO, gate-blind). cs twin castsrcprim is F1-chased at both hops (type_chase_named) -> ww-only align-up, no fuse. Probes: b1b_3lvl + b1b_ptr2lvl graduate 0/0 byte-id; 1/2-level controls held throughout (the 2-peel covered 2 levels by accident); the FIELD-u chase is asm-neutral (cs keeps a single peel there, sound via type_isint NAMED recursion + NAMED size carrying the underlying's — probe b1c_fld2lvl byte-id). 944 rows castprim_3lvl_base / castprim_ptr2lvl_base / castprim_2lvl_base_ctl. B2 (nullableptrtag variant scan :2719): PROBE-CLEARED, NO FIX. The 2-level ptr-alias nullable variant (b|void), the order-swapped (void|b) that defeats the return-0 fallback, AND 3-level all run 0/0 byte-id both stages — the constructible variant params never carry a 2+-level NAMED at this scan. cs twin nullable_ptr_tag (cgen.c:747) has the identical single peel: parity, both correct on every constructible shape. NOT nominal-sensitive (shape-keyed first-PTR scan, no name choice exists) — the spec's #209/#211 hold condition does not trip. The single-peel if stays, classified survivor. B3 (elemsizeofc): an alias-NAMED INDEXABLE (`type grid = [3]cell`) arrives as a bare N_TNAME — elemsizeof's name arm knows only str/prims and answered the 1-sentinel through the `direct != 8` short-circuit (#60 esz-1 family, outer-array leg). New N_TNAME leg answers from the chased stamped tinfo via idxeffti. #83 caller probes (rule: no unprobed caller row): - append leg: UNREACHABLE on ww — `let xs: nums = [];` rejected by the wwstage CHECKER ("let: not assignable") even at 1 level; cs accepts+runs. check.ww is batch-4 scope -> documented on #83. - alloc-empty leg: BOTH stages loud-reject the alias-typed binding hint ("cannot infer slice element type", check.ww:2547 + cs twin) — symmetric loud, alias-blind hint documented on #83. - arr[i].field= float leg: plain [3]cell runs 0/0 byte-id; the alias-named outer array LOUDS on ww at its own site (cgenexpr.ww:11033 assign-resolver float-field bound), cs runs — fails upstream of elemsizeofc, documented on #83. - subslice-of-alias-array call-arg probe: already 0/0 pre-change (the #60/#257 stamped-tinfo keying answers first) — the internal chase is presently LATENT defense-in-depth; ZERO callers enroll. Remaining elemsizeofc internal loops (eti/esub) fold to tichase. Byte-id: five-mains NEUTRAL vs the c2 build on identical inputs; cs==ww on the regenerated five; 944 138/138; test-unit 288 green. combined.ww regens ride along.
This commit is contained in:
@@ -17600,9 +17600,28 @@ fn elemsizeofc(c: *cgen, t: *node) i32 = {
|
||||
if (nk == nkind.N_TARRAY) { nest = t.lhs; };
|
||||
if (nest != nil && nest.kind == nkind.N_TARRAY) {
|
||||
let eti: *tinfo = nest.type_: *tinfo;
|
||||
for (eti != nil && eti.kind == tykind.TY_NAMED) { eti = eti.under; };
|
||||
eti = tichase(eti);
|
||||
if (eti != nil) { return eti.size: i32; };
|
||||
};
|
||||
// #83/B3: an alias-NAMED INDEXABLE (`type grid = [3]cell`) arrives
|
||||
// as a bare N_TNAME — elemsizeof's name arm knows only str + prims
|
||||
// and answers the 1-sentinel, so the `direct != 8` short-circuit
|
||||
// below returned 1 and every caller strode by one byte (the #60
|
||||
// esz-1 family, outer-array leg). Answer from the chased stamped
|
||||
// tinfo via idxeffti (which also drills an alias-of-`*[N]T`),
|
||||
// element chased like the #8 leg below. Non-indexable names
|
||||
// (struct/prim/str aliases) fall through to the old paths —
|
||||
// byte-id preserved there.
|
||||
if (nk == nkind.N_TNAME) {
|
||||
let eff: *tinfo = idxeffti(t.type_: *tinfo);
|
||||
if (eff != nil) {
|
||||
if (eff.kind == tykind.TY_ARRAY
|
||||
|| eff.kind == tykind.TY_SLICE) {
|
||||
let aes: *tinfo = tichase(eff.sub);
|
||||
if (aes != nil) { return aes.size: i32; };
|
||||
};
|
||||
};
|
||||
};
|
||||
let direct: i32 = elemsizeof(t);
|
||||
if (direct != 8) { return direct; };
|
||||
// #8: direct==8 is elemsizeof's "unresolved alias/aggregate" sentinel.
|
||||
@@ -17622,7 +17641,7 @@ fn elemsizeofc(c: *cgen, t: *node) i32 = {
|
||||
let ti: *tinfo = idxeffti(t.type_: *tinfo);
|
||||
if (ti != nil) {
|
||||
let esub: *tinfo = ti.sub;
|
||||
for (esub != nil && esub.kind == tykind.TY_NAMED) { esub = esub.under; };
|
||||
esub = tichase(esub);
|
||||
if (esub != nil) { return esub.size: i32; };
|
||||
};
|
||||
let elem: *node = idxelemtn(t);
|
||||
@@ -18137,17 +18156,25 @@ export fn exprprimresolved(c: *cgen, n: *node,
|
||||
// checker stamps them i32/*T at check.ww:1987-2004) and tuple
|
||||
// positionals, keeping them at sz=0 — asymmetry there breaks 995
|
||||
// byte-id (cgen.c:286-290). The field's own width/sign is the
|
||||
// N_DOT's stamped type_ (check.ww:2012). One TY_NAMED peel, then
|
||||
// typeisint ? size : 0; bool falls out because typeisint(bool) is
|
||||
// false — the same exclusion the old streq("bool") arm encoded.
|
||||
// N_DOT's stamped type_ (check.ww:2012). typeisint ? size : 0;
|
||||
// bool falls out because typeisint(bool) is false — the same
|
||||
// exclusion the old streq("bool") arm encoded.
|
||||
// B2-c3/B1: the base walk CHASES each hop (was a hand-rolled
|
||||
// 2-peel that ran out at a 3-level alias base or a ptr-to-
|
||||
// 2-level base — clamp kept on a knowable identity cast,
|
||||
// runtime-correct but cs!=ww asm). Aligns up to cstage
|
||||
// castsrcprim post-F1 (type_chase_named at both hops). The
|
||||
// field-u chase is asm-neutral: cs keeps its single peel
|
||||
// there, sound through type_isint's NAMED recursion + the
|
||||
// NAMED tinfo carrying its underlying's size (probe
|
||||
// b1c_fld2lvl byte-id).
|
||||
let bu: *tinfo = nil;
|
||||
if (n.lhs != nil) { bu = n.lhs.type_: *tinfo; };
|
||||
if (bu != nil && bu.kind == tykind.TY_NAMED) { bu = bu.under; };
|
||||
if (bu != nil && bu.kind == tykind.TY_PTR) { bu = bu.sub; };
|
||||
if (bu != nil && bu.kind == tykind.TY_NAMED) { bu = bu.under; };
|
||||
bu = tichase(bu);
|
||||
if (bu != nil && bu.kind == tykind.TY_PTR) { bu = tichase(bu.sub); };
|
||||
if (bu != nil && bu.kind == tykind.TY_STRUCT) {
|
||||
let u: *tinfo = n.type_: *tinfo;
|
||||
if (u != nil && u.kind == tykind.TY_NAMED) { u = u.under; };
|
||||
u = tichase(u);
|
||||
if (typeisint(u)) {
|
||||
*sz_out = u.size: i32;
|
||||
*unsigned_out = typeisunsigned(u);
|
||||
|
||||
@@ -1528,9 +1528,28 @@ fn elemsizeofc(c: *cgen, t: *node) i32 = {
|
||||
if (nk == nkind.N_TARRAY) { nest = t.lhs; };
|
||||
if (nest != nil && nest.kind == nkind.N_TARRAY) {
|
||||
let eti: *tinfo = nest.type_: *tinfo;
|
||||
for (eti != nil && eti.kind == tykind.TY_NAMED) { eti = eti.under; };
|
||||
eti = tichase(eti);
|
||||
if (eti != nil) { return eti.size: i32; };
|
||||
};
|
||||
// #83/B3: an alias-NAMED INDEXABLE (`type grid = [3]cell`) arrives
|
||||
// as a bare N_TNAME — elemsizeof's name arm knows only str + prims
|
||||
// and answers the 1-sentinel, so the `direct != 8` short-circuit
|
||||
// below returned 1 and every caller strode by one byte (the #60
|
||||
// esz-1 family, outer-array leg). Answer from the chased stamped
|
||||
// tinfo via idxeffti (which also drills an alias-of-`*[N]T`),
|
||||
// element chased like the #8 leg below. Non-indexable names
|
||||
// (struct/prim/str aliases) fall through to the old paths —
|
||||
// byte-id preserved there.
|
||||
if (nk == nkind.N_TNAME) {
|
||||
let eff: *tinfo = idxeffti(t.type_: *tinfo);
|
||||
if (eff != nil) {
|
||||
if (eff.kind == tykind.TY_ARRAY
|
||||
|| eff.kind == tykind.TY_SLICE) {
|
||||
let aes: *tinfo = tichase(eff.sub);
|
||||
if (aes != nil) { return aes.size: i32; };
|
||||
};
|
||||
};
|
||||
};
|
||||
let direct: i32 = elemsizeof(t);
|
||||
if (direct != 8) { return direct; };
|
||||
// #8: direct==8 is elemsizeof's "unresolved alias/aggregate" sentinel.
|
||||
@@ -1550,7 +1569,7 @@ fn elemsizeofc(c: *cgen, t: *node) i32 = {
|
||||
let ti: *tinfo = idxeffti(t.type_: *tinfo);
|
||||
if (ti != nil) {
|
||||
let esub: *tinfo = ti.sub;
|
||||
for (esub != nil && esub.kind == tykind.TY_NAMED) { esub = esub.under; };
|
||||
esub = tichase(esub);
|
||||
if (esub != nil) { return esub.size: i32; };
|
||||
};
|
||||
let elem: *node = idxelemtn(t);
|
||||
@@ -2065,17 +2084,25 @@ export fn exprprimresolved(c: *cgen, n: *node,
|
||||
// checker stamps them i32/*T at check.ww:1987-2004) and tuple
|
||||
// positionals, keeping them at sz=0 — asymmetry there breaks 995
|
||||
// byte-id (cgen.c:286-290). The field's own width/sign is the
|
||||
// N_DOT's stamped type_ (check.ww:2012). One TY_NAMED peel, then
|
||||
// typeisint ? size : 0; bool falls out because typeisint(bool) is
|
||||
// false — the same exclusion the old streq("bool") arm encoded.
|
||||
// N_DOT's stamped type_ (check.ww:2012). typeisint ? size : 0;
|
||||
// bool falls out because typeisint(bool) is false — the same
|
||||
// exclusion the old streq("bool") arm encoded.
|
||||
// B2-c3/B1: the base walk CHASES each hop (was a hand-rolled
|
||||
// 2-peel that ran out at a 3-level alias base or a ptr-to-
|
||||
// 2-level base — clamp kept on a knowable identity cast,
|
||||
// runtime-correct but cs!=ww asm). Aligns up to cstage
|
||||
// castsrcprim post-F1 (type_chase_named at both hops). The
|
||||
// field-u chase is asm-neutral: cs keeps its single peel
|
||||
// there, sound through type_isint's NAMED recursion + the
|
||||
// NAMED tinfo carrying its underlying's size (probe
|
||||
// b1c_fld2lvl byte-id).
|
||||
let bu: *tinfo = nil;
|
||||
if (n.lhs != nil) { bu = n.lhs.type_: *tinfo; };
|
||||
if (bu != nil && bu.kind == tykind.TY_NAMED) { bu = bu.under; };
|
||||
if (bu != nil && bu.kind == tykind.TY_PTR) { bu = bu.sub; };
|
||||
if (bu != nil && bu.kind == tykind.TY_NAMED) { bu = bu.under; };
|
||||
bu = tichase(bu);
|
||||
if (bu != nil && bu.kind == tykind.TY_PTR) { bu = tichase(bu.sub); };
|
||||
if (bu != nil && bu.kind == tykind.TY_STRUCT) {
|
||||
let u: *tinfo = n.type_: *tinfo;
|
||||
if (u != nil && u.kind == tykind.TY_NAMED) { u = u.under; };
|
||||
u = tichase(u);
|
||||
if (typeisint(u)) {
|
||||
*sz_out = u.size: i32;
|
||||
*unsigned_out = typeisunsigned(u);
|
||||
|
||||
@@ -17600,9 +17600,28 @@ fn elemsizeofc(c: *cgen, t: *node) i32 = {
|
||||
if (nk == nkind.N_TARRAY) { nest = t.lhs; };
|
||||
if (nest != nil && nest.kind == nkind.N_TARRAY) {
|
||||
let eti: *tinfo = nest.type_: *tinfo;
|
||||
for (eti != nil && eti.kind == tykind.TY_NAMED) { eti = eti.under; };
|
||||
eti = tichase(eti);
|
||||
if (eti != nil) { return eti.size: i32; };
|
||||
};
|
||||
// #83/B3: an alias-NAMED INDEXABLE (`type grid = [3]cell`) arrives
|
||||
// as a bare N_TNAME — elemsizeof's name arm knows only str + prims
|
||||
// and answers the 1-sentinel, so the `direct != 8` short-circuit
|
||||
// below returned 1 and every caller strode by one byte (the #60
|
||||
// esz-1 family, outer-array leg). Answer from the chased stamped
|
||||
// tinfo via idxeffti (which also drills an alias-of-`*[N]T`),
|
||||
// element chased like the #8 leg below. Non-indexable names
|
||||
// (struct/prim/str aliases) fall through to the old paths —
|
||||
// byte-id preserved there.
|
||||
if (nk == nkind.N_TNAME) {
|
||||
let eff: *tinfo = idxeffti(t.type_: *tinfo);
|
||||
if (eff != nil) {
|
||||
if (eff.kind == tykind.TY_ARRAY
|
||||
|| eff.kind == tykind.TY_SLICE) {
|
||||
let aes: *tinfo = tichase(eff.sub);
|
||||
if (aes != nil) { return aes.size: i32; };
|
||||
};
|
||||
};
|
||||
};
|
||||
let direct: i32 = elemsizeof(t);
|
||||
if (direct != 8) { return direct; };
|
||||
// #8: direct==8 is elemsizeof's "unresolved alias/aggregate" sentinel.
|
||||
@@ -17622,7 +17641,7 @@ fn elemsizeofc(c: *cgen, t: *node) i32 = {
|
||||
let ti: *tinfo = idxeffti(t.type_: *tinfo);
|
||||
if (ti != nil) {
|
||||
let esub: *tinfo = ti.sub;
|
||||
for (esub != nil && esub.kind == tykind.TY_NAMED) { esub = esub.under; };
|
||||
esub = tichase(esub);
|
||||
if (esub != nil) { return esub.size: i32; };
|
||||
};
|
||||
let elem: *node = idxelemtn(t);
|
||||
@@ -18137,17 +18156,25 @@ export fn exprprimresolved(c: *cgen, n: *node,
|
||||
// checker stamps them i32/*T at check.ww:1987-2004) and tuple
|
||||
// positionals, keeping them at sz=0 — asymmetry there breaks 995
|
||||
// byte-id (cgen.c:286-290). The field's own width/sign is the
|
||||
// N_DOT's stamped type_ (check.ww:2012). One TY_NAMED peel, then
|
||||
// typeisint ? size : 0; bool falls out because typeisint(bool) is
|
||||
// false — the same exclusion the old streq("bool") arm encoded.
|
||||
// N_DOT's stamped type_ (check.ww:2012). typeisint ? size : 0;
|
||||
// bool falls out because typeisint(bool) is false — the same
|
||||
// exclusion the old streq("bool") arm encoded.
|
||||
// B2-c3/B1: the base walk CHASES each hop (was a hand-rolled
|
||||
// 2-peel that ran out at a 3-level alias base or a ptr-to-
|
||||
// 2-level base — clamp kept on a knowable identity cast,
|
||||
// runtime-correct but cs!=ww asm). Aligns up to cstage
|
||||
// castsrcprim post-F1 (type_chase_named at both hops). The
|
||||
// field-u chase is asm-neutral: cs keeps its single peel
|
||||
// there, sound through type_isint's NAMED recursion + the
|
||||
// NAMED tinfo carrying its underlying's size (probe
|
||||
// b1c_fld2lvl byte-id).
|
||||
let bu: *tinfo = nil;
|
||||
if (n.lhs != nil) { bu = n.lhs.type_: *tinfo; };
|
||||
if (bu != nil && bu.kind == tykind.TY_NAMED) { bu = bu.under; };
|
||||
if (bu != nil && bu.kind == tykind.TY_PTR) { bu = bu.sub; };
|
||||
if (bu != nil && bu.kind == tykind.TY_NAMED) { bu = bu.under; };
|
||||
bu = tichase(bu);
|
||||
if (bu != nil && bu.kind == tykind.TY_PTR) { bu = tichase(bu.sub); };
|
||||
if (bu != nil && bu.kind == tykind.TY_STRUCT) {
|
||||
let u: *tinfo = n.type_: *tinfo;
|
||||
if (u != nil && u.kind == tykind.TY_NAMED) { u = u.under; };
|
||||
u = tichase(u);
|
||||
if (typeisint(u)) {
|
||||
*sz_out = u.size: i32;
|
||||
*unsigned_out = typeisunsigned(u);
|
||||
|
||||
@@ -753,6 +753,50 @@ static const struct row rows[] = {
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
/* ---- F2a batch-2 c3/B1: exprprimresolved's N_DOT base walk was
|
||||
* a hand-rolled 2-peel — a 3-level alias base (or ptr-to-2-level)
|
||||
* left the cast-source width unknowable on wwstage only, so the
|
||||
* #33 identity clamp stayed emitted where cstage (castsrcprim,
|
||||
* F1-chased) skipped it: runtime-correct both, byte-id NO.
|
||||
* Graduated by the tichase walk; 1/2-level controls held all
|
||||
* along (the 2-peel covered them by accident). */
|
||||
{ "castprim_3lvl_base",
|
||||
"package main;\n"
|
||||
"type s1 = struct { f: u32 };\n"
|
||||
"type s2 = s1;\n"
|
||||
"type s3 = s2;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let x: s3;\n"
|
||||
" x.f = 70000;\n"
|
||||
" let y: u64 = (x.f: u32): u64;\n"
|
||||
" if (y != 70000) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
{ "castprim_ptr2lvl_base",
|
||||
"package main;\n"
|
||||
"type s1 = struct { f: u32 };\n"
|
||||
"type s2 = s1;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let x: s2;\n"
|
||||
" x.f = 70000;\n"
|
||||
" let p: *s2 = &x;\n"
|
||||
" let y: u64 = (p.f: u32): u64;\n"
|
||||
" if (y != 70000) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
/* 2-level control (was already byte-id pre-c3; pins the accident
|
||||
* out of existence). */
|
||||
{ "castprim_2lvl_base_ctl",
|
||||
"package main;\n"
|
||||
"type s1 = struct { f: u32 };\n"
|
||||
"type s2 = s1;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let x: s2;\n"
|
||||
" x.f = 70000;\n"
|
||||
" let y: u64 = (x.f: u32): u64;\n"
|
||||
" if (y != 70000) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
/* ---- task #71 (rob probe-ruled F1 enrollment): nested fields
|
||||
* whose TYPES are aliases. The chained-dot store/read/addr-of
|
||||
* walks single-peeled each hop, aborted on the alias, and fell
|
||||
|
||||
Reference in New Issue
Block a user