w6c+selfhost: cgen *T-rooted chained N_DOT (closes #22)

Spine walker now accepts *T root at the last hop (cur->lhs->kind ==
N_IDENT, pu->kind == TY_PTR), substitutes pointee struct, emits
MOVQ off(BP), CX before offset arithmetic. Symmetric in N_DOT and
N_ASSIGN. Distinct gate from existing mid-chain *T-field branch
(cgen.c:4615) — no shadow.

Unblocks task #18 (bufio writer first-field embed). Pre-existing
*T-field mid-chain path unchanged.
This commit is contained in:
2026-05-14 02:44:57 +09:00
parent d2f4659305
commit d66aef382a
6 changed files with 659 additions and 127 deletions

View File

@@ -2364,10 +2364,11 @@ fn cgwidentaggedstore(c: *cgen, dst: *node, src: *node, slot_off: i32, slot_sz:
export fn dotchainresolve(c: *cgen, n: *node,
outrootname: *str, outrootoff: *i32, outtotaloff: *i32,
outleaffi: **fieldinfo, outslicedelta: *i32,
outisglobal: *bool) bool = {
outisglobal: *bool, outptrroot: *bool) bool = {
*outrootname = "";
*outrootoff = 0;
*outisglobal = false;
*outptrroot = false;
*outtotaloff = 0;
*outleaffi = nil;
*outslicedelta = -1;
@@ -2395,6 +2396,20 @@ export fn dotchainresolve(c: *cgen, n: *node,
rootstruct = lc.tnode.str;
*outrootoff = lc.off;
};
// `*T` root (param/local): dereference at emit time;
// pointee struct supplies the field layout. Callers
// that opt in via *outptrroot emit a MOVQ load of the
// slot before indexing.
if (lc.tnode.kind == nkind.N_TPTR) {
let pe: *node = lc.tnode.lhs;
if (pe != nil) {
if (pe.kind == nkind.N_TNAME) {
rootstruct = pe.str;
*outrootoff = lc.off;
*outptrroot = true;
};
};
};
};
};
if (rootstruct.len == 0) {