wcc/cgen: #8 def str-array element load — emit + pre-intern def-twin + ww load (both stages)

def C:[N]str; C[i] was loud (undefined main.C) both stages. Three folded
fixes, one commit (splitting would ship a bisect point where wwstage
silently returns an element address instead of .len):

P0: the str-array static-init emitter dropped its vestigial directive
=="DATAW" gate so a def table rides the same DATAW-header + DATAR-reloc
path as let. A def str/slice table lives in DATAW by w6a's A_DATAR-holder
constraint -- placement only; def immutability stays checker-enforced.

P1: let_pre_intern / letpreintern walked N_LET only, so a def str-array's
element string-literals were never interned (dangling _S_n). Extracted a
pre_intern_strarray SSoT helper, called for a def str-array arm too, both
stages. Scoped to str fixed arrays; def []T / def [N][]T stay loud (#270).

P2: wwstage cgenexpr lacked a defvartnode fallback in the indexed-element
classify, so a def str-array element load returned the element address
instead of the slice header -- a silent miscompile. One line, aligning
wwstage up to cstage (which was correct). C[1].len now = 3 both stages,
byte-identical.

byte-id 990-997 8/8; w6c/w6c_ww move. test/wcc/819 table-driven. The
def-global scalar str index sibling (def S:str; S[0]) stays task #14.
This commit is contained in:
2026-06-08 18:52:55 +09:00
parent 267e81b89e
commit 1aaa0a3670
7 changed files with 636 additions and 148 deletions

View File

@@ -1881,6 +1881,17 @@ fn cgindex(c: *cgen, n: *node) void = {
etn = idxelemtn(bl.tnode);
} else {
etn = idxelemtn(letvartnode(c, base.str));
// #8/GAP-B: a def-global str/slice-array base lives
// in c.defs, not c.lets — letvartnode misses it →
// etn nil → elem mis-classified scalar, dropping the
// 3-word slice-header load (returns element ADDR not
// .len; cstage's Type-based classify loads the full
// header, the proven let form). defvartnode is the
// def-side sister — same fallback as the base-address
// resolution at cgenexpr.ww:1762.
if (etn == nil) {
etn = idxelemtn(defvartnode(c, base.str));
};
};
// #60: an alias-NAMED base has no element tnode
// (idxelemtn sees the N_TNAME leaf, nil) — classify