w6c: tagged-union fields on struct globals — LEAQ-based read+write

Field write extends the existing TY_TAGGED branch with an is_global
arm: LEAQ name(SB),CX after cgexpr (no AX/BX clobber), then MOVQ
into slot+foff+0 (tag) and slot+foff+8 (value, plus +16 for str-
typed variants).

Field read now treats tagged fields specially — load AX=tag,
DX=val0, CX=val1 (when union >16B), mirroring the tagged-return
ABI that let-init and match dispatch already expect. Previously
the scalar-load path read 8B into AX and left DX/CX with junk,
which silently broke local tagged-field reads too.
This commit is contained in:
2026-05-12 13:29:25 +09:00
parent 6f04713601
commit 328a53de5b
2 changed files with 105 additions and 4 deletions

View File

@@ -232,6 +232,61 @@ static const struct fixture fixtures[] = {
"};\n",
11,
},
{
"struct-tagged-field-i64",
/* Tagged-union field on a struct global. Write goes
* LEAQ name(SB),CX + MOVQ to slot+foff+8 (value) and
* slot+foff+0 (tag). Read pulls AX=tag, DX=val0,
* CX=val1 from those same slots and match dispatches. */
"type tok = (i64 | str | void);\n"
"type ent = struct { id: i32, t: tok };\n"
"let e: ent;\n"
"fn main() i32 = {\n"
"\te.t = 42i64: tok;\n"
"\tlet v: tok = e.t;\n"
"\tmatch (v) {\n"
"\tcase let n: i64 => return n: i32;\n"
"\tcase let s: str => return 1;\n"
"\tcase void => return 2;\n"
"\t};\n"
"\treturn 0;\n"
"};\n",
42,
},
{
"struct-tagged-field-str",
"type tok = (i64 | str | void);\n"
"type ent = struct { id: i32, t: tok };\n"
"let e: ent;\n"
"fn main() i32 = {\n"
"\te.t = \"hello\";\n"
"\tlet v: tok = e.t;\n"
"\tmatch (v) {\n"
"\tcase let n: i64 => return 1;\n"
"\tcase let s: str => return s.len: i32;\n"
"\tcase void => return 2;\n"
"\t};\n"
"\treturn 0;\n"
"};\n",
5,
},
{
"struct-tagged-field-void",
"type tok = (i64 | str | void);\n"
"type ent = struct { id: i32, t: tok };\n"
"let e: ent;\n"
"fn main() i32 = {\n"
"\te.t = void;\n"
"\tlet v: tok = e.t;\n"
"\tmatch (v) {\n"
"\tcase let n: i64 => return 1;\n"
"\tcase let s: str => return 2;\n"
"\tcase void => return 7;\n"
"\t};\n"
"\treturn 0;\n"
"};\n",
7,
},
{
"struct-narrow-field",
/* u8 field on a struct global. Read uses MOVZBQ, store