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:
2026-05-13 04:23:31 +09:00
parent e16634baec
commit 6e7c9e0df4
9 changed files with 893 additions and 59 deletions

View File

@@ -470,6 +470,24 @@ static const struct row rows[] = {
" };\n"
" return 0;\n"
"};", 40 },
/* named alias over `!(A | B)`: param spill must size to the
* flattened union (8B tag + 8B payload), not 8B-scalar. Pinned
* the cstage/wwstage divergence where wwstage's istaggedtype
* was alias-blind and the slot+8 read trailed into saved BP. */
{ "type invalid = !i32;\n"
"type overflow = !void;\n"
"type error = !(invalid | overflow);\n"
"fn errcode(e: error) i32 = {\n"
" match (e) {\n"
" case let v: invalid => return v: i32;\n"
" case let v: overflow => return 99;\n"
" };\n"
" return 0;\n"
"};\n"
"fn main() i32 = {\n"
" let e: error = 7: invalid;\n"
" return errcode(e);\n"
"};", 7 },
/* str-typed variant payload: let-init with a string literal,
* match-binding loads ptr+len from the slot */
{ "fn main() i32 = {\n"