ww: cgen trap batch (def-str field, chained-ptr write, scalar+str tuple ABI)
This commit is contained in:
@@ -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 }
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user