w6c+selfhost: cgen N_DOT N_INDEX-lhs branch (closes #8)

cstage cmd/w6c/cgen.c gained the missing N_DOT N_INDEX-lhs branch.
Covers both [N]*Struct and [N]Struct via fldloadop. wwstage already
handled [N]*Struct since 7c75dd2; refactored to mirror cstage exactly
and added [N]Struct. The spill workaround in dotchainresolve stays
(Pike rule); task #14 retires it as a follow-up.

Wwstage cgassign N_DOT(N_INDEX,...) silent store-drop discovered in
scope, filed as task #16.
This commit is contained in:
2026-05-13 23:45:35 +09:00
parent d053560b80
commit 9ef9bef340
7 changed files with 592 additions and 148 deletions

View File

@@ -2414,11 +2414,14 @@ export fn dotchainresolve(c: *cgen, n: *node, out: *dotchain) bool = {
for (i >= 0) {
let csi: *structinfo = structlookup(c, curstruct);
if (csi == nil) { return false; };
// Materialise the *node first; wwstage's cgen mis-emits the
// chained shape `stk[i].str` directly (task #8 — loses BX
// between the index load and the field deref), so always
// spill to an intermediate local before reading the str
// field. The cstage emits the same pattern for byte-identity.
// Spill `stk[i]` to a *node local before reading its `.str`.
// Task #8 closed the cgen bug behind this — cstage's N_DOT
// had no N_INDEX-lhs branch and fell through, returning the
// (AX, BX) cgindex shape as if it were the field. The fix
// lives in cmd/w6c/cgen.c N_DOT and the mirror in this
// module's cgenexpr.ww cgdot. The spill stays for now (Pike
// rule — workaround retirement is task #14), so cstage
// compiling this source emits byte-identical asm to wwstage.
stepnd = stk[i];
if (stepnd == nil) { return false; };
stepnm = stepnd.str;