cgen: B5-c3 #89 cgreturn return-position widen — rt/vu chase, trace-first
Trace at the c2 tip (rebuilt binaries, #80-c4 form): ret_widen's mk()
emitted `MOVQ -16(BP),AX / MOVQ AX,DX / MOVQ $0,CX` — the scalar
shuffle arm, payload word 1 ZEROED (s.b/e.aux dropped, cs silent
exit 1). Deciding predicate: the vu single peel left an alias struct
source TY_NAMED → isstruct false → scalar arm. The rt single peel was
the succ half: a 2-LEVEL alias return type stayed NAMED → the whole
tagged-return block was skipped → no tag synthesis at any return
(kb5_succ's three paired return-position insertions). Fix = the three
granted peels (bare-return rt, value-return rt, vu) →
type_chase_named; the route predicates (istagged/isstruct/istuple/
passthrough) key on the chased vu. Raw `->under` in cgen.c 62→59.
#89 CLOSES.
TRAIN INVARIANT holds: cs-only; _ww binaries bit-identical to the
bcd948d baseline md5s. cs movers vs the c2 tip bounded to EXACTLY the
return-route family: ret_widen, kb4_xret, kna_ret_errunion, kb5_succ.
Zero ww movers; detectors pinned (kb4_xampdef stays 139/139 #94;
def93/x93/l2_local stay cs-SEGV — c4's targets; fill/tuparg/v2
families unchanged).
Graduations (cs1/ww0 BYTE-DIVERGE → 0/0 BYTE-ID): g89_ret_widen (the
banked spelling), g89_ret_errunion (the live e.aux truncation seed),
and succ_2lvl flips K_RUN_NOID → K_RUN exactly as C1-CORR-1 predicted
(pins-follow-the-layer). g89_ret_named_ctl (bare NAMED control) held
0/0 byte-id throughout.
944_alias_cgen_b5_run 25→28 rows (75 checks); 944 family green;
sizelint 0.
This commit is contained in:
@@ -12243,8 +12243,7 @@ cgstmt(Cg *c, Node *n, Local **locals, int *frame)
|
|||||||
* is producing the void variant. Emit its tag; the payload is
|
* is producing the void variant. Emit its tag; the payload is
|
||||||
* undefined (void has size 0). */
|
* undefined (void has size 0). */
|
||||||
if (n->lhs == NULL && cg_ret_type) {
|
if (n->lhs == NULL && cg_ret_type) {
|
||||||
Type *rt = cg_ret_type;
|
Type *rt = type_chase_named(cg_ret_type);
|
||||||
if (rt->kind == TY_NAMED) rt = rt->under;
|
|
||||||
if (rt && rt->kind == TY_TAGGED) {
|
if (rt && rt->kind == TY_TAGGED) {
|
||||||
/* #38b: an sret-classified tagged return (slot
|
/* #38b: an sret-classified tagged return (slot
|
||||||
* > the AX/DX/CX/R8 cursor) writes the void-
|
* > the AX/DX/CX/R8 cursor) writes the void-
|
||||||
@@ -12283,12 +12282,18 @@ cgstmt(Cg *c, Node *n, Local **locals, int *frame)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (n->lhs && cg_ret_type) {
|
if (n->lhs && cg_ret_type) {
|
||||||
Type *rt = cg_ret_type;
|
/* #89: the single peel left a 2-level alias return
|
||||||
if (rt->kind == TY_NAMED) rt = rt->under;
|
* type NAMED (rt — the whole tagged block skipped, no
|
||||||
|
* tag synthesis) and an alias struct source NAMED (vu
|
||||||
|
* — isstruct missed, the scalar arm shuffled word0
|
||||||
|
* into DX and ZEROED the rest of the payload). Both
|
||||||
|
* silent; ww routes via rhsstructpayload→
|
||||||
|
* structlookupchain since B2-c2 and is the runtime-
|
||||||
|
* correct reference. */
|
||||||
|
Type *rt = type_chase_named(cg_ret_type);
|
||||||
if (rt && rt->kind == TY_TAGGED) {
|
if (rt && rt->kind == TY_TAGGED) {
|
||||||
Type *vt = n->lhs->type;
|
Type *vt = n->lhs->type;
|
||||||
Type *vu = (vt && vt->kind == TY_NAMED)
|
Type *vu = type_chase_named(vt);
|
||||||
? vt->under : vt;
|
|
||||||
int istagged = vu && vu->kind == TY_TAGGED;
|
int istagged = vu && vu->kind == TY_TAGGED;
|
||||||
/* #263: passthrough forwards the source's AX/DX/CX
|
/* #263: passthrough forwards the source's AX/DX/CX
|
||||||
* unchanged — correct ONLY when the source already
|
* unchanged — correct ONLY when the source already
|
||||||
|
|||||||
@@ -32,12 +32,10 @@
|
|||||||
* | cgexpr INLINE set (B6), NOT the |
|
* | cgexpr INLINE set (B6), NOT the |
|
||||||
* | :2456 funnel (C1-CORR-2, corrects |
|
* | :2456 funnel (C1-CORR-2, corrects |
|
||||||
* | rob R2) — byte-id waived until B6 | 0/0
|
* | rob R2) — byte-id waived until B6 | 0/0
|
||||||
* succ_bound_c3 | kb5_succ: `?`-success remap over |
|
* succ_2lvl | kb5_succ: `?`-success remap over |
|
||||||
* | 2-lvl alias result — both-correct |
|
* | 2-lvl alias result — was divergent |
|
||||||
* | divergent at RETURN positions only |
|
* | at RETURN positions only (C1-CORR-1)|
|
||||||
* | (:12278/:12318/:12322 family, |
|
* | — GRADUATED at c3 with the rt chase | 0/0
|
||||||
* | C1-CORR-1) — joins c3's graduation |
|
|
||||||
* | set; byte-id waived until c3 | 0/0
|
|
||||||
* null_2lvl | kb5_null: nullable fold + deref |
|
* null_2lvl | kb5_null: nullable fold + deref |
|
||||||
* | (type_isnullable/nullable_ptr_tag) |
|
* | (type_isnullable/nullable_ptr_tag) |
|
||||||
* | — divergence flip | 0/0
|
* | — divergence flip | 0/0
|
||||||
@@ -92,6 +90,15 @@
|
|||||||
* | fatal gave way to the #129 A.2 |
|
* | fatal gave way to the #129 A.2 |
|
||||||
* | foldability loud — now fill0-class |
|
* | foldability loud — now fill0-class |
|
||||||
* | both-loud (twin texts) | err/err
|
* | both-loud (twin texts) | err/err
|
||||||
|
* ---- c3 (#89: cgreturn return-position widen rt/vu chase) ------
|
||||||
|
* g89_ret_widen | alias-struct return into union — |
|
||||||
|
* | was cs word0-to-DX + CX zeroed |
|
||||||
|
* | (payload dropped, silent exit 1) | 0/0
|
||||||
|
* g89_ret_errunion | 1-LVL alias error-union return — |
|
||||||
|
* | cs MOVQ AX,DX dropped e.aux (the |
|
||||||
|
* | live-truncation seed) | 0/0
|
||||||
|
* g89_ret_named_ctl | bare NAMED struct return control — |
|
||||||
|
* | held 0/0 byte-id throughout | 0/0
|
||||||
*
|
*
|
||||||
* K_RUN rows build+run BOTH drivers (cs exit==cswant, ww exit==wwwant)
|
* K_RUN rows build+run BOTH drivers (cs exit==cswant, ww exit==wwwant)
|
||||||
* and assert cstage/wwstage asm byte-id. K_RUN_NOID asserts both run
|
* and assert cstage/wwstage asm byte-id. K_RUN_NOID asserts both run
|
||||||
@@ -270,11 +277,11 @@ static const struct row rows[] = {
|
|||||||
" };\n"
|
" };\n"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"};\n", 0, 0, K_RUN_NOID, NULL }, /* byte-id: B6 */
|
"};\n", 0, 0, K_RUN_NOID, NULL }, /* byte-id: B6 */
|
||||||
/* C1-CORR-1: the residual divergence is exactly three paired
|
/* C1-CORR-1 → GRADUATED at c3: the residual divergence was
|
||||||
* return-position tag syntheses — the cgreturn return-route
|
* exactly three paired return-position tag syntheses — the
|
||||||
* family (:12278/:12318/:12322). Joins c3's graduation set
|
* cgreturn return-route family; the c3 rt chase closed it
|
||||||
* (pins-follow-the-layer); flips to K_RUN there. */
|
* (pins-follow-the-layer, ken c1-boundary addendum). */
|
||||||
{ "succ_bound_c3",
|
{ "succ_2lvl",
|
||||||
"package main;\n"
|
"package main;\n"
|
||||||
"type e0 = !i64;\n"
|
"type e0 = !i64;\n"
|
||||||
"type r0 = (i64 | e0);\n"
|
"type r0 = (i64 | e0);\n"
|
||||||
@@ -293,7 +300,7 @@ static const struct row rows[] = {
|
|||||||
" case e0 => { return 2; };\n"
|
" case e0 => { return 2; };\n"
|
||||||
" };\n"
|
" };\n"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"};\n", 0, 0, K_RUN_NOID, NULL }, /* byte-id: c3 */
|
"};\n", 0, 0, K_RUN, NULL }, /* graduated: #89 (B5-c3) */
|
||||||
{ "null_2lvl",
|
{ "null_2lvl",
|
||||||
"package main;\n"
|
"package main;\n"
|
||||||
"type np0 = (*i64 | void);\n"
|
"type np0 = (*i64 | void);\n"
|
||||||
@@ -555,6 +562,62 @@ static const struct row rows[] = {
|
|||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"};\n", 0, 0, K_BUILDERR,
|
"};\n", 0, 0, K_BUILDERR,
|
||||||
"#129 A.2 scope" },
|
"#129 A.2 scope" },
|
||||||
|
/* ---- c3: #89 — the cgreturn rt/vu single peels left a 2-level
|
||||||
|
* alias RETURN TYPE un-tagged (no tag synthesis at all, the succ
|
||||||
|
* shape) and an alias-struct SOURCE un-structed (the scalar arm
|
||||||
|
* shuffled word0 into DX and ZEROED the rest — s.b/e.aux
|
||||||
|
* dropped, cs silent exit 1, ww runtime-correct since B2-c2). */
|
||||||
|
{ "g89_ret_widen",
|
||||||
|
"package main;\n"
|
||||||
|
"type base = struct { a: size, b: size };\n"
|
||||||
|
"type ali = base;\n"
|
||||||
|
"fn mk() (void | ali) = {\n"
|
||||||
|
" let x: ali;\n"
|
||||||
|
" x.a = 4; x.b = 9;\n"
|
||||||
|
" return x;\n"
|
||||||
|
"};\n"
|
||||||
|
"export fn main() i32 = {\n"
|
||||||
|
" match (mk()) {\n"
|
||||||
|
" case let s: ali => { if (s.b != 9) { return 1; }; };\n"
|
||||||
|
" case void => { return 2; };\n"
|
||||||
|
" };\n"
|
||||||
|
" return 0;\n"
|
||||||
|
"};\n", 0, 0, K_RUN, NULL },
|
||||||
|
{ "g89_ret_errunion",
|
||||||
|
"package main;\n"
|
||||||
|
"type failure = struct { code: i32, aux: size };\n"
|
||||||
|
"type myerr = failure;\n"
|
||||||
|
"fn work(bad: bool) (i32 | myerr) = {\n"
|
||||||
|
" if (bad) {\n"
|
||||||
|
" let e: myerr;\n"
|
||||||
|
" e.code = 7; e.aux = 99;\n"
|
||||||
|
" return e;\n"
|
||||||
|
" };\n"
|
||||||
|
" return 42;\n"
|
||||||
|
"};\n"
|
||||||
|
"export fn main() i32 = {\n"
|
||||||
|
" match (work(true)) {\n"
|
||||||
|
" case let e: myerr => { if (e.aux != 99) { return 1; }; };\n"
|
||||||
|
" case i32 => { return 2; };\n"
|
||||||
|
" };\n"
|
||||||
|
" return 0;\n"
|
||||||
|
"};\n", 0, 0, K_RUN, NULL },
|
||||||
|
{ "g89_ret_named_ctl",
|
||||||
|
"package main;\n"
|
||||||
|
"type base = struct { a: size, b: size };\n"
|
||||||
|
"fn make() (void | base) = {\n"
|
||||||
|
" let x: base;\n"
|
||||||
|
" x.a = 4; x.b = 9;\n"
|
||||||
|
" return x;\n"
|
||||||
|
"};\n"
|
||||||
|
"export fn main() i32 = {\n"
|
||||||
|
" let v = make();\n"
|
||||||
|
" match (v) {\n"
|
||||||
|
" case let s: base => { if (s.b != 9) { return 1; }; };\n"
|
||||||
|
" case void => { return 2; };\n"
|
||||||
|
" };\n"
|
||||||
|
" return 0;\n"
|
||||||
|
"};\n", 0, 0, K_RUN, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|||||||
Reference in New Issue
Block a user