ww: cgen trap batch (def-str field, chained-ptr write, scalar+str tuple ABI)

This commit is contained in:
2026-05-11 20:49:21 +09:00
parent 2ac15e4e99
commit c5f30f2fce
14 changed files with 1629 additions and 67 deletions

View File

@@ -806,6 +806,69 @@ static const struct row rows[] = {
" };\n"
" return acc;\n"
"};", 16 }, /* 3 + 3 + len(\"no newline\")=10 */
/* `(scalar, str)` tuple return: AX:DX:CX convention extends the
* tagged-union ABI. AX = scalar, DX = str.ptr, CX = str.len.
* Receive sites destructure off the same regs regardless of
* positional order. Without the fix, len was lost (only AX:DX
* returned), every receive shape gave garbage. */
{ "fn split() (i64, str) = { return 42, \"hello\"; };\n"
"fn main() i32 = {\n"
" let n, s = split();\n"
" return (n: i32) + (s.len: i32);\n"
"};", 47 },
{ "fn split() (str, i64) = { return \"hello\", 42; };\n"
"fn main() i32 = {\n"
" let s, n = split();\n"
" return (n: i32) + (s.len: i32);\n"
"};", 47 },
{ "fn split() (i64, str) = { return 42, \"hello\"; };\n"
"fn main() i32 = {\n"
" let t: (i64, str) = split();\n"
" return (t.0: i32) + (t.1.len: i32);\n"
"};", 47 },
/* Hare-style paren tuple-destructure with str element */
{ "fn split() (i64, str) = { return 42, \"hello\"; };\n"
"fn main() i32 = {\n"
" let (n, s) = split();\n"
" return (n: i32) + (s.len: i32);\n"
"};", 47 },
/* Chained field write through a pointer field: `r.sym.flag = v`
* where `r.sym: *T`. The cgen must evaluate the inner pointer,
* then store at *(ptr + field.offset). Without the fix, the
* single-level N_IDENT-base path doesn't fire (base is itself
* an N_DOT) and the assignment silently emits no instructions.
* Compound op + 1-byte field + 3-level chain all exercised. */
{ "type inner = struct { tag: u8, pad: u8, flag: i32 };\n"
"type outer = struct { sym: *inner };\n"
"fn main() i32 = {\n"
" let i: inner = inner { tag = 0u8, pad = 0u8, flag = 10 };\n"
" let r: outer = outer { sym = &i };\n"
" r.sym.flag += 32;\n"
" r.sym.tag = 5u8;\n"
" return r.sym.flag + (r.sym.tag: i32);\n"
"};", 47 },
{ "type leaf = struct { v: i32 };\n"
"type mid = struct { l: *leaf };\n"
"type top = struct { m: *mid };\n"
"fn main() i32 = {\n"
" let lf: leaf = leaf { v = 0 };\n"
" let md: mid = mid { l = &lf };\n"
" let tp: top = top { m = &md };\n"
" tp.m.l.v = 99;\n"
" return tp.m.l.v;\n"
"};", 99 },
/* `def NAME: str = \"lit\"` field access. The Sdef has no stack
* slot, so .len/.ptr must inline the literal length / strlit
* address; without the fix, .len reads BP+8 (return-address slot)
* as garbage. */
{ "def MSG: str = \"hello world\";\n"
"fn main() i32 = { return MSG.len: i32; };", 11 },
{ "use os;\n"
"def GREETING: str = \"hi\\n\";\n"
"fn main() i32 = {\n"
" os.write(1, GREETING.ptr, GREETING.len: u64);\n"
" return GREETING.len: i32;\n"
"};", 3 },
{ NULL, 0 }
};