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:
@@ -867,6 +867,14 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
// from the SAME tinfo esz reads — never a fresh node-stamp (#121).
|
||||
let float_elem: bool = false;
|
||||
let f32_elem: bool = false;
|
||||
// #156 (PREREQ-1 read-half): element is itself an array ([N][M]T →
|
||||
// element [M]T) → leave the sub-array's ADDRESS in the result reg
|
||||
// instead of dereferencing; the outer index adds its offset and the
|
||||
// final scalar element dereferences. Sister of #135. Mirrors cstage
|
||||
// esubu->kind == TY_ARRAY. Node-based (elemisarrayc) for ident bases,
|
||||
// n.type_ tinfo-based for N_DOT/N_INDEX bases — same source split as
|
||||
// esz above.
|
||||
let elem_isarray: bool = false;
|
||||
// #1/Phase 3: str and slice are both 24B (and a >16B struct is
|
||||
// 24B+ too), so the header branches below MUST gate on KIND
|
||||
// (elemisstr/elemisslice, mirroring cstage's elem_is_str||
|
||||
@@ -894,6 +902,7 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
signed_elem = elemissignedc(c, baselocal.tnode);
|
||||
float_elem = elemisfloatc(c, baselocal.tnode);
|
||||
f32_elem = elemisf32c(c, baselocal.tnode);
|
||||
elem_isarray = elemisarrayc(c, baselocal.tnode);
|
||||
} else {
|
||||
let tn: *node = letvartnode(c, bn);
|
||||
// #129 A.3: array-typed defs now have DATA storage;
|
||||
@@ -910,6 +919,7 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
signed_elem = elemissignedc(c, tn);
|
||||
float_elem = elemisfloatc(c, tn);
|
||||
f32_elem = elemisf32c(c, tn);
|
||||
elem_isarray = elemisarrayc(c, tn);
|
||||
};
|
||||
if (tn.kind == nkind.N_TPTR) {
|
||||
isglobalptr = true;
|
||||
@@ -918,6 +928,7 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
signed_elem = elemissignedc(c, tn);
|
||||
float_elem = elemisfloatc(c, tn);
|
||||
f32_elem = elemisf32c(c, tn);
|
||||
elem_isarray = elemisarrayc(c, tn);
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -930,6 +941,7 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
// stays unset, as before.
|
||||
let dt: *tinfo = n.type_: *tinfo;
|
||||
if (dt != nil) { esz = dt.size: i32; elemisstr = typeisstr(dt); elemisslice = typeisslice(dt); float_elem = typeisfloat(dt); f32_elem = typeisf32(dt); };
|
||||
elem_isarray = tinfoisarray(dt);
|
||||
} else { if (base.kind == nkind.N_INDEX) {
|
||||
// #60: chained `names[i][k]` — n.type_ is the checker-
|
||||
// stamped outer element tinfo (indexresult over the inner
|
||||
@@ -942,6 +954,7 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
signed_elem = typeissigned(et);
|
||||
float_elem = typeisfloat(et);
|
||||
f32_elem = typeisf32(et);
|
||||
elem_isarray = tinfoisarray(et);
|
||||
};
|
||||
};};};
|
||||
};
|
||||
@@ -1002,6 +1015,12 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
emitline("(SB), BX\n");
|
||||
};
|
||||
emitline("\tADDQ\tAX, BX\n");
|
||||
// #156: array element ([N][M]T) → leave the sub-array ADDRESS
|
||||
// in AX (BX holds base+idx*esz); nested index dereferences.
|
||||
if (elem_isarray) {
|
||||
emitline("\tMOVQ\tBX, AX\n");
|
||||
return;
|
||||
};
|
||||
if (elem_tagged) {
|
||||
if (elem_slot_sz > 24) {
|
||||
emitline("\tMOVQ\t24(BX), R8\n");
|
||||
@@ -1055,6 +1074,12 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
emitline("(BP), BX\n");
|
||||
};
|
||||
emitline("\tADDQ\tAX, BX\n");
|
||||
// #156: array element ([N][M]T) → leave the sub-array ADDRESS
|
||||
// in AX (BX holds base+idx*esz); nested index dereferences.
|
||||
if (elem_isarray) {
|
||||
emitline("\tMOVQ\tBX, AX\n");
|
||||
return;
|
||||
};
|
||||
if (elem_tagged) {
|
||||
if (elem_slot_sz > 24) {
|
||||
emitline("\tMOVQ\t24(BX), R8\n");
|
||||
@@ -1099,6 +1124,11 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
};
|
||||
emitline("\tPOPQ\tBX\n");
|
||||
emitline("\tADDQ\tBX, AX\n");
|
||||
// #156: array element ([N][M]T) → AX already holds &elem
|
||||
// (base+idx*esz); a nested index dereferences. See ident arms.
|
||||
if (elem_isarray) {
|
||||
return;
|
||||
};
|
||||
if (elem_tagged) {
|
||||
// AX holds the element address. Copy to BX (loading slot+0
|
||||
// into AX clobbers it), then read slot words.
|
||||
|
||||
Reference in New Issue
Block a user