w6c+wwstage: &aggregate-array-element addressing + store/copy (#270-1)
The array-of-struct element store/copy family — one primitive (&(array element) for an AGGREGATE element, used as address, never deref/truncate) across three consumers. Both stages were symmetric-broken; converge on the runtime-correct full-address/full-copy (#263). (1a) `a[i].m[j] = v` (a:[N]struct) segfaulted: the `arr[i].field` arm computed &a[i] then DEREF'd it (loaded the struct's first 8 bytes as a value) for an `[N]T`-typed field → garbage base. Now an array-typed field of an array element leaves the field ADDRESS (the #135 read-side, applied to the array-element base). cgen.c arm + cgenexpr.ww cgdot N_INDEX-lhs branch. (1b) `a[i] = aggregateval` truncated the copy to an 8B MOVQ. New aggregate (struct/array/tuple >8B) element-store branch word-copies the element from the rhs source address (ident / N_DOT field / `*p` deref) — the WRITE-twin of the #268 let-init loop. cgen.c N_INDEX store + cgenexpr.ww cgassign. (3a) `let c = x.arr[i]` (N_DOT base) / `let c = a[i][j]` (nested) dropped the copy: the #268 let-init N_INDEX source-addr arm was N_IDENT-base- gated. Now computes &base[idx] via cg_dotbase_addr (N_DOT field) or the &abase[bidx] spine (nested N_IDENT-array base). cgen.c N_LET + cgenstmt.ww cglet. 949 rows: elemfield_store, elem_struct_store, elem_arr_store, letcopy_{dot,nest}_prim, letcopy_subarr (byteid=1); letcopy_{dot,nest}_ struct (byteid=0 — run-correct, byte-id blocked by the orthogonal value-nested-struct frame divergence #254). All 94 pass; test-unit 241 green.
This commit is contained in:
@@ -1057,6 +1057,107 @@ static const struct row rows[] = {
|
||||
" a[1][1] = 88;\n"
|
||||
" return (a[1][1] - a[0][1]): i32;\n"
|
||||
"};\n", 48, 1 },
|
||||
/* #270-1a: `a[i].m[j] = v` — array-of-struct element field, then
|
||||
* index INTO that field. The `arr[i].field` read/write arm computed
|
||||
* &a[i] then DEREF'd it (loaded the struct's first 8 bytes as a
|
||||
* value) for an `[N]T`-typed field → garbage base → SEGFAULT on the
|
||||
* outer store. Fix: an array-typed field of an array element leaves
|
||||
* the field ADDRESS (the #135 read-side, applied to the array-element
|
||||
* base). Multiple cells written then read back; byteid=1. */
|
||||
{ "elemfield_store",
|
||||
"package main;\n"
|
||||
"type inner = struct { m: [4]u32 };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: [3]inner;\n"
|
||||
" a[0].m[1] = 5u32;\n"
|
||||
" a[2].m[3] = 7u32;\n"
|
||||
" a[2].m[0] = 9u32;\n"
|
||||
" return (a[0].m[1] + a[2].m[3] + a[2].m[0]): i32;\n"
|
||||
"};\n", 21, 1 },
|
||||
/* #270-1b: `a[i] = aggregateval` — whole-element STORE. The scalar
|
||||
* store path copied only the first 8 bytes (fldstoreop MOVQ). Fix:
|
||||
* an aggregate (struct/array >8B) element store word-copies the
|
||||
* element from the rhs source address (WRITE-twin of the #268
|
||||
* let-init loop). Struct element + array element, full readback;
|
||||
* byteid=1. */
|
||||
/* 16B struct (slot == natural) keeps byteid=1: a struct whose
|
||||
* natural size is NOT an 8-multiple trips the orthogonal
|
||||
* elemsizeofc slot-vs-natural array-stride divergence (cstage strides
|
||||
* by sub->size, wwstage by slotsize) — see letcopy_dot_struct. */
|
||||
{ "elem_struct_store",
|
||||
"package main;\n"
|
||||
"type inner = struct { a: u32, b: u32, c: u32, d: u32 };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let arr: [3]inner;\n"
|
||||
" let v: inner; v.a=10u32; v.b=20u32; v.c=30u32; v.d=40u32;\n"
|
||||
" arr[2] = v;\n"
|
||||
" return (arr[2].a + arr[2].b + arr[2].c + arr[2].d): i32;\n"
|
||||
"};\n", 100, 1 },
|
||||
{ "elem_arr_store",
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let arr: [2][4]u32;\n"
|
||||
" let s: [4]u32; s[0]=1u32; s[1]=2u32; s[2]=3u32; s[3]=4u32;\n"
|
||||
" arr[1] = s;\n"
|
||||
" return (arr[1][0]+arr[1][1]+arr[1][2]+arr[1][3]): i32;\n"
|
||||
"};\n", 10, 1 },
|
||||
/* #270-3a: aggregate let-init COPY whose index base is an N_DOT
|
||||
* array-field (`x.arr[i]`) or a nested N_INDEX (`a[i][j]`) — the
|
||||
* let-init N_INDEX source-addr arm was N_IDENT-base-gated (#268
|
||||
* residual), so both fell to the 8B truncation. Fix computes
|
||||
* &base[idx] via cg_dotbase_addr (N_DOT) / the &abase[bidx] spine
|
||||
* (nested). Primitive-element rows are byteid=1; the value-struct
|
||||
* rows below run-correct but trip the orthogonal value-nested-struct
|
||||
* frame divergence (#254), so byteid=0 (same carve-out as chain_val_*
|
||||
* above). */
|
||||
{ "letcopy_dot_prim",
|
||||
"package main;\n"
|
||||
"type box = struct { arr: [2][4]u32 };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let s: [4]u32; s[0]=1u32; s[1]=2u32; s[2]=3u32; s[3]=4u32;\n"
|
||||
" let x: box;\n"
|
||||
" x.arr[1] = s;\n"
|
||||
" let c: [4]u32 = x.arr[1];\n"
|
||||
" return (c[0]+c[1]+c[2]+c[3]): i32;\n"
|
||||
"};\n", 10, 1 },
|
||||
{ "letcopy_nest_prim",
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: [2][2][4]u32;\n"
|
||||
" let s: [4]u32; s[0]=2u32; s[1]=4u32; s[2]=6u32; s[3]=8u32;\n"
|
||||
" a[1][0] = s;\n"
|
||||
" let c: [4]u32 = a[1][0];\n"
|
||||
" return (c[0]+c[1]+c[2]+c[3]): i32;\n"
|
||||
"};\n", 20, 1 },
|
||||
{ "letcopy_subarr",
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: [2][3]u32;\n"
|
||||
" a[1][0] = 5u32; a[1][1] = 6u32; a[1][2] = 7u32;\n"
|
||||
" let c: [3]u32 = a[1];\n"
|
||||
" return (c[0] + c[1] + c[2]): i32;\n"
|
||||
"};\n", 18, 1 },
|
||||
{ "letcopy_dot_struct",
|
||||
"package main;\n"
|
||||
"type inner = struct { a: u32, b: u32, c: u32 };\n"
|
||||
"type box = struct { arr: [3]inner };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let x: box;\n"
|
||||
" let v: inner; v.a = 10u32; v.b = 20u32; v.c = 30u32;\n"
|
||||
" x.arr[1] = v;\n"
|
||||
" let c: inner = x.arr[1];\n"
|
||||
" return (c.a + c.b + c.c): i32;\n"
|
||||
"};\n", 60, 0 },
|
||||
{ "letcopy_nest_struct",
|
||||
"package main;\n"
|
||||
"type inner = struct { a: u32, b: u32, c: u32 };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: [2][2]inner;\n"
|
||||
" let v: inner; v.a = 11u32; v.b = 22u32; v.c = 33u32;\n"
|
||||
" a[1][0] = v;\n"
|
||||
" let c: inner = a[1][0];\n"
|
||||
" return (c.a + c.b + c.c): i32;\n"
|
||||
"};\n", 66, 0 },
|
||||
{ NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user