diff --git a/cmd/w6c/cgen.c b/cmd/w6c/cgen.c index 739402c2..7a6ad59c 100644 --- a/cmd/w6c/cgen.c +++ b/cmd/w6c/cgen.c @@ -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 diff --git a/test/wcc/944_alias_cgen_b6_run.c b/test/wcc/944_alias_cgen_b6_run.c index 4485e85a..0a166db5 100644 --- a/test/wcc/944_alias_cgen_b6_run.c +++ b/test/wcc/944_alias_cgen_b6_run.c @@ -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