wcc: 2D array [N][M]T static-init + double-index read (#156, A.3 capstone)
Close A.3's deferred shape-14 (nested array). (a) emit_array_lit_bytes gains a TY_ARRAY-element arm (mechanical clone of the TY_STRUCT-element arm — recurses; esz=etype->size, rule-13; ...-nested loud-reject). (b) double-index read tbl[i][j]: when the indexed element is TY_ARRAY, leave the sub-array ADDRESS in AX instead of dereferencing (sister of #135's N_DOT-base fix, on the N_INDEX path) — new elemisarrayc/tinfoisarray helpers, both stages. Storage + read = one 2D-end-to-end concern (A.2/A.3 storage+LOAD precedent). Unblocks strconv fold-4's powers_of_ten[596][2]u64 (direct double-index access). Bootstrap-NEUTRAL (new arms gate on TY_ARRAY-element; 1D consumers byte-identical, 990-997 green). Test 919 +2D rows + 3D + ...-nested-reject. Deferred siblings: #155 (sub-array bind / whole- aggregate copy), #160 (global-struct-field index base).
This commit is contained in:
@@ -819,6 +819,43 @@ fn elemisf32c(c: *cgen, t: *node) bool = {
|
||||
return typeisf32(ti.sub);
|
||||
};
|
||||
|
||||
// elemisarrayc — given an indexable type-AST (`*T` / `[]T` / `[N]T`), is
|
||||
// its element itself an array (`[N][M]T` → element `[M]T`)? cgindex then
|
||||
// leaves the sub-array's ADDRESS in the result reg rather than
|
||||
// dereferencing — a nested index adds its offset and only the final
|
||||
// scalar element dereferences (#156, sister of #135 N_DOT-base-on-
|
||||
// array-field). Node-based with the `*[N]T` drill-through, mirroring
|
||||
// elemsizeof (:920-948) so elem-is-array aligns with the esz this same
|
||||
// tnode feeds. cstage twin: idx_eff(bt)->sub unwrapped == TY_ARRAY
|
||||
// (cmd/w6c/cgen.c). `c` kept for signature symmetry with elemisfloatc.
|
||||
fn elemisarrayc(c: *cgen, t: *node) bool = {
|
||||
if (t == nil) { return false; };
|
||||
let k: nkind = t.kind;
|
||||
let elem: *node = nil;
|
||||
if (k == nkind.N_TPTR) { elem = t.lhs; };
|
||||
if (k == nkind.N_TSLICE) { elem = t.lhs; };
|
||||
if (k == nkind.N_TARRAY) { elem = t.lhs; };
|
||||
if (elem == nil) { return false; };
|
||||
if (k == nkind.N_TPTR) {
|
||||
if (elem.kind == nkind.N_TARRAY) {
|
||||
if (elem.lhs != nil) { elem = elem.lhs; };
|
||||
};
|
||||
};
|
||||
return elem.kind == nkind.N_TARRAY;
|
||||
};
|
||||
|
||||
// tinfoisarray — TY_ARRAY (NAMED-aware), the tinfo-keyed companion to
|
||||
// elemisarrayc for cgindex's N_DOT/N_INDEX base branches, where the
|
||||
// element type comes from n.type_ (stamped tinfo) not a tnode. Same
|
||||
// role as typeisslice/typeisstr in lib/ww/typ.ww; kept cgen-local to
|
||||
// avoid widening the frontend surface for one #156 read-half check.
|
||||
fn tinfoisarray(t: *tinfo) bool = {
|
||||
let u: *tinfo = t;
|
||||
for (u != nil && u.kind == tykind.TY_NAMED) { u = u.under; };
|
||||
if (u == nil) { return false; };
|
||||
return u.kind == tykind.TY_ARRAY;
|
||||
};
|
||||
|
||||
// fieldissignedc — does this field/element type-AST need sign-
|
||||
// extension on a sub-word load? One-liner via typeissigned (cstage
|
||||
// cgen.c:240 `fld_issigned` SSoT). t.type_ is stamped at check.ww
|
||||
@@ -943,6 +980,12 @@ fn elemsizeof(t: *node) i32 = {
|
||||
if (elem == nil) { return 1; };
|
||||
// `*[N]T`: drill through the pointer into the array's element so
|
||||
// indexing scales by T's width, not the whole-array byte size.
|
||||
// FOOTGUN (#156): this drill ALSO fires for a bare 2D `[N][M]T`
|
||||
// (elem = the inner `[M]T`), so elemsizeof of a 2D array bottoms
|
||||
// out at the SCALAR T size, NOT the `[M]T` sub-array stride. 2D
|
||||
// double-index (cgindex) needs the sub-array stride — call
|
||||
// elemsizeofc, the 2D-correct entry, which recovers slotsize([M]T)
|
||||
// when elemsizeof returns 8. Never call elemsizeof for a 2D stride.
|
||||
if (elem.kind == nkind.N_TARRAY) {
|
||||
if (elem.lhs != nil) { elem = elem.lhs; };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user