diff --git a/cmd/w6c/cgen.c b/cmd/w6c/cgen.c index 6ebd322c..f1896fbd 100644 --- a/cmd/w6c/cgen.c +++ b/cmd/w6c/cgen.c @@ -8398,8 +8398,7 @@ cgexpr(Cg *c, Node *n, Local *locals) * its declared parameter type — needed to detect implicit * widening of a concrete variant into a tagged-union slot. */ Type *callee_t = n->lhs ? n->lhs->type : NULL; - Type *cu = (callee_t && callee_t->kind == TY_NAMED) ? - callee_t->under : callee_t; + Type *cu = type_chase_named(callee_t); Tparam *callee_params = (cu && cu->kind == TY_FN) ? cu->params : NULL; /* Hare-style variadic last param: gather N tail args into a @@ -8431,8 +8430,7 @@ cgexpr(Cg *c, Node *n, Local *locals) argcount = nfixed + 1; } else { Type *vst = var_p->type; - Type *vsu = (vst && vst->kind == TY_NAMED) - ? vst->under : vst; + Type *vsu = type_chase_named(vst); Type *velem = (vsu && vsu->kind == TY_SLICE) ? vsu->sub : NULL; int esz = (velem && velem->size) @@ -8557,10 +8555,8 @@ cgexpr(Cg *c, Node *n, Local *locals) Type *at = args[i] ? args[i]->type : NULL; int psz = tagged_arg_size(p->type); if (psz > 0) { - Type *pu = (p->type && p->type->kind == TY_NAMED) - ? p->type->under : p->type; - Type *au = (at && at->kind == TY_NAMED) - ? at->under : at; + Type *pu = type_chase_named(p->type); + Type *au = type_chase_named(at); int same = (pu == au) || type_eq(p->type, at); if (!same) { widen[i] = 1; @@ -8573,10 +8569,8 @@ cgexpr(Cg *c, Node *n, Local *locals) int msz = tagged_memarg_size(p->type); if (msz > 0) { memarg[i] = msz; - Type *pu = (p->type && p->type->kind == TY_NAMED) - ? p->type->under : p->type; - Type *au = (at && at->kind == TY_NAMED) - ? at->under : at; + Type *pu = type_chase_named(p->type); + Type *au = type_chase_named(at); int same = (pu == au) || type_eq(p->type, at); if (!same) { widen[i] = 1; @@ -8824,9 +8818,7 @@ cgexpr(Cg *c, Node *n, Local *locals) * ≤16B struct with any float field; the wwstage * tinfo mirror uses the same predicate). */ { - Type *st = args[i]->type; - if (st && st->kind == TY_NAMED) - st = st->under; + Type *st = type_chase_named(args[i]->type); if (st && st->kind == TY_STRUCT && st->size <= 16) { int f32; @@ -8929,9 +8921,7 @@ cgexpr(Cg *c, Node *n, Local *locals) * pre-fix it fell to the scalar single-PUSHQ default * and silently skewed every later arg register. */ if (tuparg_push == NULL) { - Type *targ = args[i]->type; - if (targ && targ->kind == TY_NAMED) - targ = targ->under; + Type *targ = type_chase_named(args[i]->type); if (targ && targ->kind == TY_TUPLE) fatal("#32: tuple arg from unsupported " "source shape %d (call/ident/" diff --git a/test/wcc/944_alias_cgen_b6_run.c b/test/wcc/944_alias_cgen_b6_run.c index 95b87d59..12e7948f 100644 --- a/test/wcc/944_alias_cgen_b6_run.c +++ b/test/wcc/944_alias_cgen_b6_run.c @@ -29,6 +29,32 @@ * | reassign — latent control | 0/0 * dassign_2lvl | kb6_dassign: (*p).f= over alias ptr | * | — latent control | 0/0 + * ---- c2 (call-arg: :8402 :8435 :8561/:8563/:8577/:8579 -------- + * + LOUD-PRESERVING :8829 :8934) ------------------------ + * fsarg0_loud_ctl | kb6_fsarg0: PLAIN float-struct from | + * | a non-ident source — #271/#165 loud | + * | BOTH stages (control, twin texts) | err/err + * fsarg2_bound | kb6_fsarg2: 1-alias-level respell — | + * | pre-c2 the :8829 single-peel let | + * | the alias DODGE the fatal; cs GP- | + * | passed by self-consistent luck. | + * | DESIGNED NARROWING: cs now louds | + * | with the pinned #271/#165 text | + * | ("widen what the gate SEES, never | + * | what it ACCEPTS"). ww's loud is its | + * | own alias-return bound (#272/#277 | + * | class, experr_ww) — per-stage texts | err/err + * fsarg_ident_ctl | kb6_fsarg: IDENT-source alias twin | + * | — ident domain out of the :8829 | + * | gate, latent control | 0/0 + * sarg_2lvl | kb6_sarg: >16B alias struct arg — | + * | latent (B5 helper chases carry the | + * | type layer) | 0/0 + * strarg_2lvl | kb6_strarg: alias str arg — latent | 0/0 + * (:8934 tuple loud is WATCH-ONLY: alias spellings are | + * checker-blocked upstream (#86/#99) — the pin is the b5 | + * suite's tuparg_cast_bound99 two-key cells, which must | + * not move.) | * * 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 @@ -131,6 +157,78 @@ static const struct row rows[] = { " if (x.b != 9) { return 1; };\n" " return 0;\n" "};\n", 0, 0, K_RUN, NULL, NULL }, + /* ---- c2: call-arg family */ + { "fsarg0_loud_ctl", + "package main;\n" + "type fs0 = struct { x: f64 };\n" + "fn mk() fs0 = {\n" + " let s: fs0; s.x = 2.5;\n" + " return s;\n" + "};\n" + "fn g(p: fs0) f64 = { return p.x; };\n" + "export fn main() i32 = {\n" + " if (g(mk()) != 2.5) { return 1; };\n" + " return 0;\n" + "};\n", 0, 0, K_BUILDERR, + "#271/#165: float-bearing struct arg from a non-ident source", + NULL }, + /* DESIGNED ACCEPTANCE NARROWING (B6-c2): pre-c2 cs accepted and + * GP-passed this float struct correct-by-self-consistent-luck + * (caller+callee agreed on the wrong transport) — the :8829 + * single peel let a 1-level alias dodge the rule-7 fatal. The + * chase widens what the gate SEES; the loud stays loud for the + * shapes it guards. ww's cell was ALREADY loud at its own + * alias-return bound (#272/#276/#277 class) — different site, + * per-stage experr. */ + { "fsarg2_bound", + "package main;\n" + "type fs0 = struct { x: f64 };\n" + "type fs = fs0;\n" + "fn mk() fs = {\n" + " let s: fs; s.x = 2.5;\n" + " return s;\n" + "};\n" + "fn g(p: fs) f64 = { return p.x; };\n" + "export fn main() i32 = {\n" + " if (g(mk()) != 2.5) { return 1; };\n" + " return 0;\n" + "};\n", 0, 0, K_BUILDERR, + "#271/#165: float-bearing struct arg from a non-ident source", + "#272/#276/#277: aggregate return reaches scalar default" }, + { "fsarg_ident_ctl", + "package main;\n" + "type fs0 = struct { x: f64 };\n" + "type fs = fs0;\n" + "fn mk() fs0 = {\n" + " let s: fs0; s.x = 2.5;\n" + " return s;\n" + "};\n" + "fn g(p: fs) f64 = { return p.x; };\n" + "export fn main() i32 = {\n" + " let v: fs = mk();\n" + " if (g(v) != 2.5) { return 1; };\n" + " return 0;\n" + "};\n", 0, 0, K_RUN, NULL, NULL }, + { "sarg_2lvl", + "package main;\n" + "type big0 = struct { a: i64, b: i64, c: i64 };\n" + "type big = big0;\n" + "fn g(p: big) i64 = { return p.a + p.c; };\n" + "export fn main() i32 = {\n" + " let s: big; s.a = 4; s.b = 5; s.c = 9;\n" + " if (g(s) != 13) { return 1; };\n" + " return 0;\n" + "};\n", 0, 0, K_RUN, NULL, NULL }, + { "strarg_2lvl", + "package main;\n" + "type ms0 = str;\n" + "type ms = ms0;\n" + "fn g(s: ms) i64 = { return len(s): i64; };\n" + "export fn main() i32 = {\n" + " let a: ms = \"hello\";\n" + " if (g(a) != 5) { return 1; };\n" + " return 0;\n" + "};\n", 0, 0, K_RUN, NULL, NULL }, }; static int