wcc: module-imported array indexed-load via cg_dotbase_addr (#128b)
Fix segfault-class memory corruption on `module.array[i]` indexed-read where both stages emitted MOVQ-not-LEAQ on the module-qualified base plus wrong stride. Extends the #135 cg_dotbase_addr/dotbaseaddr helper to handle the SK_USE module-ident-base case: when bt is NULL/ty_err and let_islet(base.str) resolves to TY_ARRAY, emit LEAQ base(SB),dst instead of MOVQ. Wwstage parallel via letvartnode/N_TARRAY check. Stride fix via let_var_type fallback in cgindex when n.lhs.kind==N_DOT. Use-site fix per #135 precedent (Option B); preserves cgdot's MOVQ semantics for the whole-array-assign defensive case (zero current consumers). Test 915 carries 3 module-u16 indexed-read rows (strconv.left_shift_table[0/2/4]) + 2 local-array controls; the strconv.left_shift_table[2]:u32 probe segfaulted (exit 139) pre-fix and exits cleanly post-fix. Broader width-variation rows (u8/u32/i32 module-imported) deferred as informational enhancement. Test 915 skips its inline cs==ww .s cmp on needs_import rows (line 217-222) since `ww build` only drives cstage; reviewer externally verified byte-id on /tmp/k128probe.combined.ww (driver-expanded form, no imports). Future enhancement: 915 could read the driver-emitted combined.ww and add a cmp leg there. Bootstrap NEUTRAL (zero current module.array[i] consumers; strconv decimal.ww uses IDENT-base from within package). 178/178 incl. 990-997 + combined_ww_fresh green. Sibling bugs #137 (chained N_DOT) / #141 (variadic-gather esz==2) / #142 (wwstage primsize-on-alias) properly deferred to backlog.
This commit is contained in:
@@ -15378,8 +15378,26 @@ fn dotbaseaddr(c: *cgen, base: *node, dstreg: str) bool = {
|
||||
let inner: *node = base.lhs;
|
||||
if (inner == nil) { return false; };
|
||||
if (inner.kind != nkind.N_IDENT) { return false; };
|
||||
// #128b: module-qualified `mod.arr` where arr is an imported
|
||||
// top-level `let X: [N]T`. The checker leaves SK_USE module-
|
||||
// idents without a localfindnode entry; detect via letvartnode
|
||||
// resolving to N_TARRAY and emit LEAQ X(SB). Without this, the
|
||||
// cgindex fallback's cgexpr(base) auto-MOVQs the symbol's first
|
||||
// 8 bytes as if it were a pointer-var — wrong shape (cstage
|
||||
// sister fix in cg_dotbase_addr).
|
||||
let lc: *local = localfindnode(c, inner.str);
|
||||
if (lc == nil) { return false; };
|
||||
if (lc == nil) {
|
||||
let gt: *node = letvartnode(c, base.str);
|
||||
if (gt != nil && gt.kind == nkind.N_TARRAY) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, base.str);
|
||||
emitline("(SB), ");
|
||||
emitline(dstreg);
|
||||
emitline("\n");
|
||||
return true;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
let bu: *tinfo = inner.type_: *tinfo;
|
||||
for (bu != nil && bu.kind == tykind.TY_NAMED) { bu = bu.under; };
|
||||
if (bu == nil) { return false; };
|
||||
|
||||
@@ -759,8 +759,26 @@ fn dotbaseaddr(c: *cgen, base: *node, dstreg: str) bool = {
|
||||
let inner: *node = base.lhs;
|
||||
if (inner == nil) { return false; };
|
||||
if (inner.kind != nkind.N_IDENT) { return false; };
|
||||
// #128b: module-qualified `mod.arr` where arr is an imported
|
||||
// top-level `let X: [N]T`. The checker leaves SK_USE module-
|
||||
// idents without a localfindnode entry; detect via letvartnode
|
||||
// resolving to N_TARRAY and emit LEAQ X(SB). Without this, the
|
||||
// cgindex fallback's cgexpr(base) auto-MOVQs the symbol's first
|
||||
// 8 bytes as if it were a pointer-var — wrong shape (cstage
|
||||
// sister fix in cg_dotbase_addr).
|
||||
let lc: *local = localfindnode(c, inner.str);
|
||||
if (lc == nil) { return false; };
|
||||
if (lc == nil) {
|
||||
let gt: *node = letvartnode(c, base.str);
|
||||
if (gt != nil && gt.kind == nkind.N_TARRAY) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, base.str);
|
||||
emitline("(SB), ");
|
||||
emitline(dstreg);
|
||||
emitline("\n");
|
||||
return true;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
let bu: *tinfo = inner.type_: *tinfo;
|
||||
for (bu != nil && bu.kind == tykind.TY_NAMED) { bu = bu.under; };
|
||||
if (bu == nil) { return false; };
|
||||
|
||||
@@ -15378,8 +15378,26 @@ fn dotbaseaddr(c: *cgen, base: *node, dstreg: str) bool = {
|
||||
let inner: *node = base.lhs;
|
||||
if (inner == nil) { return false; };
|
||||
if (inner.kind != nkind.N_IDENT) { return false; };
|
||||
// #128b: module-qualified `mod.arr` where arr is an imported
|
||||
// top-level `let X: [N]T`. The checker leaves SK_USE module-
|
||||
// idents without a localfindnode entry; detect via letvartnode
|
||||
// resolving to N_TARRAY and emit LEAQ X(SB). Without this, the
|
||||
// cgindex fallback's cgexpr(base) auto-MOVQs the symbol's first
|
||||
// 8 bytes as if it were a pointer-var — wrong shape (cstage
|
||||
// sister fix in cg_dotbase_addr).
|
||||
let lc: *local = localfindnode(c, inner.str);
|
||||
if (lc == nil) { return false; };
|
||||
if (lc == nil) {
|
||||
let gt: *node = letvartnode(c, base.str);
|
||||
if (gt != nil && gt.kind == nkind.N_TARRAY) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, base.str);
|
||||
emitline("(SB), ");
|
||||
emitline(dstreg);
|
||||
emitline("\n");
|
||||
return true;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
let bu: *tinfo = inner.type_: *tinfo;
|
||||
for (bu != nil && bu.kind == tykind.TY_NAMED) { bu = bu.under; };
|
||||
if (bu == nil) { return false; };
|
||||
|
||||
Reference in New Issue
Block a user