selfhost: alias-aware istaggedtype for nested-union match
`type error = !(invalid | overflow)` miscompiled — istaggedtype only matched N_TTAGGED directly, so an `e: error` param spilled as 8B scalar and the match's slot+8 read trailed into saved BP. Mirror isstrtype's alias+bang unwrap; add resolvetagged() for is/as/match sites that need the inner N_TTAGGED. Frame scan counts via slotsize so wwstage stays byte-identical to cstage. Unblocks lib/strconv.strerror.
This commit is contained in:
@@ -142,7 +142,7 @@ fn cgreturn(c: *cgen, n: *node) void = {
|
||||
// For other variants, cgexpr leaves AX, shuffle DX←AX.
|
||||
// Nullable folded `(*T | void)`: just one word; AX is
|
||||
// already the pointer (or 0). No shuffle, no tag.
|
||||
if (istaggedtype(c.fnret)) {
|
||||
if (istaggedtype(c, c.fnret)) {
|
||||
// Forwarding a fallible call: `return f();` where f
|
||||
// also returns a tagged union. The result is already
|
||||
// in (AX=tag, DX=v0, CX=v1) — no shuffle, no tag.
|
||||
@@ -158,7 +158,7 @@ fn cgreturn(c: *cgen, n: *node) void = {
|
||||
if (callee.kind == nkind.N_DOT) { calleename = callee.str; };
|
||||
if (calleename.len > 0) {
|
||||
let rt: *node = fnretlookup(c, calleename);
|
||||
if (istaggedtype(rt)) { forwardtagged = true; };
|
||||
if (istaggedtype(c, rt)) { forwardtagged = true; };
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -199,7 +199,7 @@ fn cgreturn(c: *cgen, n: *node) void = {
|
||||
// Bare `return;` from a tagged-union-returning fn is
|
||||
// the void variant: emit its tag. Payload is undefined
|
||||
// (void has size 0). Otherwise zero AX for determinism.
|
||||
if (istaggedtype(c.fnret)) {
|
||||
if (istaggedtype(c, c.fnret)) {
|
||||
if (isnullabletype(c.fnret)) {
|
||||
// null = void variant; AX = 0.
|
||||
emitline("\tMOVQ\t$0, AX\n");
|
||||
@@ -253,7 +253,7 @@ fn cglet(c: *cgen, n: *node) void = {
|
||||
// just spill all three.
|
||||
// - Otherwise rhs is a bare variant value: pack tag +
|
||||
// value(s).
|
||||
if (istaggedtype(tn)) {
|
||||
if (istaggedtype(c, tn)) {
|
||||
let nullable: bool = isnullabletype(tn);
|
||||
let rhsreturnstagged: bool = false;
|
||||
if (rhs.kind == nkind.N_CALL) {
|
||||
@@ -265,7 +265,7 @@ fn cglet(c: *cgen, n: *node) void = {
|
||||
if (callee.kind == nkind.N_DOT) { calleename = callee.str; };
|
||||
if (calleename.len > 0) {
|
||||
let rt: *node = fnretlookup(c, calleename);
|
||||
if (istaggedtype(rt)) { rhsreturnstagged = true; };
|
||||
if (istaggedtype(c, rt)) { rhsreturnstagged = true; };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user