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:
@@ -6977,6 +6977,18 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
ins2(c, A_MOVQ, amem(D_BP, off), areg(D_BX));
|
||||
}
|
||||
ins2(c, A_ADDQ, areg(D_AX), areg(D_BX));
|
||||
/* #156 (PREREQ-1 read-half): element is itself an array
|
||||
* ([N][M]T → element [M]T). This index yields the sub-
|
||||
* array's ADDRESS, not a loaded value — the outer index
|
||||
* adds its own offset and only the final scalar element
|
||||
* dereferences. Sister of #135 (N_DOT-base-on-[N]T-field
|
||||
* needs ADDRESS). BX holds base+idx*esz; move it to AX (the
|
||||
* value-result reg). Gated on TY_ARRAY element so 1D arrays
|
||||
* are byte-identical (no 2D consumer pre-#156). */
|
||||
if (esubu && esubu->kind == TY_ARRAY) {
|
||||
ins2(c, A_MOVQ, areg(D_BX), areg(D_AX));
|
||||
break;
|
||||
}
|
||||
/* str/slice element: load the full (ptr, len, cap) header
|
||||
* into (AX, BX, CX) — both are 24B since #1, so the cap
|
||||
* word must survive. Kind-gate on type_isstr||type_isslice,
|
||||
@@ -7045,6 +7057,11 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
cgexpr(c, n->lhs, locals);
|
||||
ins1(c, A_POPQ, areg(D_BX));
|
||||
ins2(c, A_ADDQ, areg(D_BX), areg(D_AX));
|
||||
/* #156 (PREREQ-1 read-half): array element → AX already holds
|
||||
* &elem (base+idx*esz); a nested index adds its offset and
|
||||
* dereferences. See the N_IDENT arm above. */
|
||||
if (esubu && esubu->kind == TY_ARRAY)
|
||||
break;
|
||||
/* str/slice element via fallback base: load the full (ptr, len,
|
||||
* cap) header into (AX, BX, CX). Kind-gate on type_isstr||
|
||||
* type_isslice, never size==24 (see Site A). Base is AX. */
|
||||
@@ -8914,6 +8931,46 @@ emit_array_lit_bytes(FILE *out, Cg *c, Type *t, Node *rhs, int emit_phase)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* #129 A.3 capstone (PREREQ-1, #156): nested-array element [M]T
|
||||
* inside [N][M]T. Mirror of the TY_STRUCT-element arm above and of
|
||||
* the TY_ARRAY-field-in-struct arm in emit_struct_lit_bytes — recurse
|
||||
* into emit_array_lit_bytes per element; recursion bottoms out at
|
||||
* scalar (int/float) elements. esz = etype->size gives the per-
|
||||
* element stride (rule 13, no manual stride math). The `...` repeat
|
||||
* marker with nested-array elements is rejected loud (rule 7): no
|
||||
* consumer needs it (powers_of_ten is fully enumerated) and the
|
||||
* scalar-repeat byte-fill cannot reduce a nested N_ARRLIT. */
|
||||
if (eu && eu->kind == TY_ARRAY) {
|
||||
int idx = 0;
|
||||
for (Node *e = rhs->list; e && idx < alen; e = e->next) {
|
||||
if (e->kind == N_FIELD && e->str
|
||||
&& strcmp(e->str, "...") == 0)
|
||||
fatal("emit_array_lit_bytes: '...' repeat with "
|
||||
"nested-array elements unsupported "
|
||||
"(#129 A.3, rule 7)");
|
||||
Node *ev = e;
|
||||
while (ev && ev->kind == N_CAST) ev = ev->lhs;
|
||||
if (ev == NULL || ev->kind != N_ARRLIT) return 0;
|
||||
if (!emit_array_lit_bytes(out, c, etype, ev, 0))
|
||||
return 0;
|
||||
idx++;
|
||||
}
|
||||
if (!emit_phase) return 1;
|
||||
idx = 0;
|
||||
for (Node *e = rhs->list; e && idx < alen; e = e->next) {
|
||||
Node *ev = e;
|
||||
while (ev && ev->kind == N_CAST) ev = ev->lhs;
|
||||
emit_array_lit_bytes(out, c, etype, ev, 1);
|
||||
idx++;
|
||||
}
|
||||
while (idx < alen) {
|
||||
for (int b = 0; b < esz; b++)
|
||||
emit_data_byte(out, 0);
|
||||
idx++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (type_isfloat(etype)) {
|
||||
int isf32 = type_isf32(etype);
|
||||
/* Validate: every element must be N_FLOATLIT (after N_CAST
|
||||
|
||||
Reference in New Issue
Block a user