cgen: B6-c5 reads/len/globals family single peels fold into type_chase_named — 8 lines, B6 territory closed
The exact B6-c5 set (rob b6 spec §2, numbering at4cac1cb): :3820 (fn-symbol load u), :7201 (#235 len() tuple-elem bu), :7807 (type_default let-init region u), :7900 (append su, str→[]u8 region), :9944 (`is` source u — the #37 memread predicate feed; the >32B cap test now keys the CHASED size, mirroring ww's taggedmemread, per the EYES condition — kb6_memread 40B-union byte-NEUTRALITY is the regression net, held), :10224 (module-qualified value ref tu), :10750/:10873 (tagged-union field loads, direct + through-ptr tag_fu/ptag_fu). Raw `->under` in cgen.c 17→9 — the remaining 9 are EXACTLY the designed whitelist survivors (:731 nullable_ptr_tag + :813/:814 + :834/:835 cg_variant_match peel-ok-#218, #95's fold) and B7's 4 emitter/intern lines (:14356 :14574 :14788 :15088). B6's 49 granted lines are fully retired; grep-verified. FLIP: kb6_tfread (tagged-union field load direct + through-ptr over alias struct, was both-correct divergent NO(4)) → 0/0 BYTE-ID; cs converged onto ww's UNCHANGED asm (#263 polarity, cmp-proven) and the alias shape equals the plain shape (kb6_tfread_p, same hash — ken's c5 pre-test). kb6_len / kb6_gref / kb6_memread latent byte-NEUTRAL as predicted. TRAIN INVARIANT (held c1..tip): cs-only; w6c_ww/ww_ww bit-identical to the4cac1cbbaselines (b6bddc8eb5c3ed8e805e50371d4b7017 / 4e9ca8741f19e1f68219ff799a5e5a14) at all five boundaries. cs movers c4→c5 bounded to exactly {kb6_tfread}; rest of corpus + five mains byte-NEUTRAL; kw1_101/fill2/tuparg_c/xampdef/amplen1 detectors unmoved across the whole train; 989 ratchet zero flips. 944_alias_cgen_b6_run final table: 18→22 rows, 49→61 checks (tfread_2lvl flip + len_2lvl/gref_2lvl controls + memread_40b cap- watch pin). All 944-family suites green; sizelint 0.
This commit is contained in:
@@ -3817,7 +3817,7 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
* str-typed `def`s expand to (ptr, len) of the literal,
|
||||
* other globals (def constants) load by value (MOVQ). */
|
||||
Type *t = n->type;
|
||||
Type *u = (t && t->kind == TY_NAMED) ? t->under : t;
|
||||
Type *u = type_chase_named(t);
|
||||
if (u && u->kind == TY_FN) {
|
||||
/* Take the address of a function. Apply
|
||||
* @symbol resolution so taking the address
|
||||
@@ -7187,8 +7187,7 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
* slice arm above and the tuple-field-offset walk
|
||||
* (cgen.c N_DOT TY_TUPLE). */
|
||||
Type *bt = a->lhs->type;
|
||||
Type *bu = (bt && bt->kind == TY_NAMED)
|
||||
? bt->under : bt;
|
||||
Type *bu = type_chase_named(bt);
|
||||
if (bu && bu->kind == TY_TUPLE) {
|
||||
int idx = 0;
|
||||
for (const char *q = a->str; *q; q++)
|
||||
@@ -7794,7 +7793,7 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
* with `!` / `?` to consume the union. */
|
||||
Node *v = n->list;
|
||||
Type *t = v->type;
|
||||
Type *u = (t && t->kind == TY_NAMED) ? t->under : t;
|
||||
Type *u = type_chase_named(t);
|
||||
Type *def = type_default(t);
|
||||
int sz = def ? (int)def->size : 8;
|
||||
if (sz == 0) sz = 8;
|
||||
@@ -7887,7 +7886,7 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
* in a counted loop over items. */
|
||||
Node *sn = n->list;
|
||||
Type *st = sn->type;
|
||||
Type *su = (st && st->kind == TY_NAMED) ? st->under : st;
|
||||
Type *su = type_chase_named(st);
|
||||
int esz = (su && su->sub) ? (int)su->sub->size : 1;
|
||||
Type *esub = su ? su->sub : NULL;
|
||||
int sn_off = (sn->kind == N_IDENT)
|
||||
@@ -9920,7 +9919,7 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
if (cg_tagged_memread(tl))
|
||||
ins2(c, A_MOVQ, amem(D_AX, 0), areg(D_AX));
|
||||
Type *u = tl ? tl->type : NULL;
|
||||
if (u && u->kind == TY_NAMED) u = u->under;
|
||||
u = type_chase_named(u);
|
||||
Type *vt = n->rhs ? n->rhs->type : NULL;
|
||||
char *ne = mklabel(c, "is_ne");
|
||||
char *done = mklabel(c, "is_done");
|
||||
@@ -10200,7 +10199,7 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
if (n->lhs && n->lhs->kind == N_IDENT
|
||||
&& (bt == NULL || bt == ty_err)) {
|
||||
Type *t = n->type;
|
||||
Type *tu = (t && t->kind == TY_NAMED) ? t->under : t;
|
||||
Type *tu = type_chase_named(t);
|
||||
if (tu && tu->kind == TY_FN) {
|
||||
/* `mod.fn` address-of via N_DOT — pass the
|
||||
* module bareword as the disambiguation hint. */
|
||||
@@ -10725,8 +10724,7 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
* / match dispatch shapes just work. The val2
|
||||
* word fires for slice-variant tagged-unions
|
||||
* (slot = 8 tag + 24 slice header = 32B). */
|
||||
Type *tag_fu = (f->type && f->type->kind == TY_NAMED)
|
||||
? f->type->under : f->type;
|
||||
Type *tag_fu = type_chase_named(f->type);
|
||||
if (tag_fu && tag_fu->kind == TY_TAGGED) {
|
||||
int fo = base_disp + (int)f->offset;
|
||||
/* #37: >32B box — ADDRESS in AX (the
|
||||
@@ -10848,8 +10846,7 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
* regardless of pointer rooting. Pre-#28 fell
|
||||
* through to fldloadop and dropped the
|
||||
* payload words. */
|
||||
Type *ptag_fu = (f->type && f->type->kind == TY_NAMED)
|
||||
? f->type->under : f->type;
|
||||
Type *ptag_fu = type_chase_named(f->type);
|
||||
if (ptag_fu && ptag_fu->kind == TY_TAGGED) {
|
||||
int fo = (int)f->offset;
|
||||
/* #37: >32B box — ADDRESS in
|
||||
|
||||
@@ -100,6 +100,23 @@
|
||||
* | ALIAS-INDEPENDENT (documented bound);|
|
||||
* | :9819's chase is loud-preserving |
|
||||
* | ONLY — twin texts, shared experr | err/err
|
||||
* ---- c5 (reads/len/globals: :3820 :7201 :7807 :7900 :9944 ----
|
||||
* :10224 :10750 :10873, numbering at 4cac1cb) ------------
|
||||
* tfread_2lvl | kb6_tfread: tagged-union field load |
|
||||
* | direct + through-ptr over alias |
|
||||
* | struct — was both-correct divergent; |
|
||||
* | the :10750/:10873 tag_fu chases FLIP |
|
||||
* | it (cs → ww's unchanged asm, #263 |
|
||||
* | polarity; alias == plain shape) | 0/0
|
||||
* len_2lvl | kb6_len: str+array len over 2-lvl |
|
||||
* | alias — latent control | 0/0
|
||||
* gref_2lvl | kb6_gref: alias scalar global value- |
|
||||
* | ref — latent control | 0/0
|
||||
* memread_40b | kb6_memread: 40B union, the :9944 |
|
||||
* | #37 cap-watch row — the `is` chase |
|
||||
* | keys the cap test on the CHASED size |
|
||||
* | (mirrors ww taggedmemread); byte- |
|
||||
* | NEUTRALITY here is the regression net| 0/0
|
||||
*
|
||||
* K_RUN rows build+run BOTH drivers (cs exit==cswant, ww exit==wwwant)
|
||||
* and assert cstage/wwstage asm byte-id. K_BUILDERR rows must FAIL
|
||||
@@ -415,6 +432,63 @@ static const struct row rows[] = {
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_BUILDERR,
|
||||
"#38b: `?`/`!` on an sret-class call result unwired", NULL },
|
||||
/* ---- c5: reads/len/globals family */
|
||||
{ "tfread_2lvl",
|
||||
"package main;\n"
|
||||
"type u0 = (void | i64);\n"
|
||||
"type u = u0;\n"
|
||||
"type st0 = struct { f: u, n: i64 };\n"
|
||||
"type st = st0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let s: st;\n"
|
||||
" s.f = 42i64;\n"
|
||||
" s.n = 3;\n"
|
||||
" if (!(s.f is i64)) { return 1; };\n"
|
||||
" let p: *st = &s;\n"
|
||||
" if (!(p.f is i64)) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
{ "len_2lvl",
|
||||
"package main;\n"
|
||||
"type ms0 = str;\n"
|
||||
"type ms = ms0;\n"
|
||||
"type ar0 = [4]i64;\n"
|
||||
"type ar = ar0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: ms = \"hello\";\n"
|
||||
" if (len(a) != 5) { return 1; };\n"
|
||||
" let xs: ar = [1, 2, 3, 4];\n"
|
||||
" if (len(xs) != 4) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
{ "gref_2lvl",
|
||||
"package main;\n"
|
||||
"type my64 = i64;\n"
|
||||
"type my64b = my64;\n"
|
||||
"let G: my64b = 7;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (G != 7) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
/* :9944 #37 cap-watch: the `is` site's >32B mem-read predicate
|
||||
* must key the CHASED size — byte-neutrality of this 40B-union
|
||||
* row across the c5 chase is the regression net. */
|
||||
{ "memread_40b",
|
||||
"package main;\n"
|
||||
"type big = struct { a: i64, b: i64, c: i64, d: i64, e: i64 };\n"
|
||||
"type m0 = (void | big);\n"
|
||||
"type m = m0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let s: big;\n"
|
||||
" s.a = 1; s.b = 2; s.c = 3; s.d = 4; s.e = 55;\n"
|
||||
" let v: m = s;\n"
|
||||
" if (!(v is big)) { return 1; };\n"
|
||||
" match (v) {\n"
|
||||
" case let w: big => { if (w.e != 55) { return 2; }; };\n"
|
||||
" case void => { return 3; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
};
|
||||
|
||||
static int
|
||||
|
||||
Reference in New Issue
Block a user