selfhost: retire dotchain bundle workaround (closes #17)
dotchain struct + bundle pre-declares retired. dotchainresolve now takes 6 direct out-params; per-iter locals declared inline. Bootstrap ww2==ww3==ww4 byte-identical — end-to-end validation of session's N_DOT / N_INDEX / TK_AMP / fldloadop fixes. i64 widths retained on out-params via task #19 workaround (i32 deref- stores leave caller slot upper 4B stale, MOVQ reads zero-extend to garbage). Documented in selfhost/CLAUDE.md active-workarounds.
This commit is contained in:
@@ -1575,81 +1575,88 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
// Placed BEFORE the .ptr/.len fast paths so the chain wins.
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_DOT) {
|
||||
let r: dotchain;
|
||||
let pok: bool = dotchainresolve(c, n, &r);
|
||||
let rootname: str = "";
|
||||
let rootoff: i64 = 0i64;
|
||||
let totaloff: i64 = 0i64;
|
||||
let leaffi: *fieldinfo = nil;
|
||||
let slicedelta: i64 = -1i64;
|
||||
let isglobal: bool = false;
|
||||
let pok: bool = dotchainresolve(c, n,
|
||||
&rootname, &rootoff, &totaloff,
|
||||
&leaffi, &slicedelta, &isglobal);
|
||||
if (pok) {
|
||||
if (r.slicedelta >= 0i64) {
|
||||
if (r.isglobal) {
|
||||
if (slicedelta >= 0i64) {
|
||||
if (isglobal) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, r.rootname);
|
||||
emitsymname(c, rootname);
|
||||
emitline("(SB), CX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg(r.totaloff + r.slicedelta, "CX");
|
||||
emitdispreg(totaloff + slicedelta, "CX");
|
||||
emitline(", AX\n");
|
||||
} else {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff(r.rootoff + r.totaloff + r.slicedelta);
|
||||
emitoff(rootoff + totaloff + slicedelta);
|
||||
emitline("(BP), AX\n");
|
||||
};
|
||||
return;
|
||||
};
|
||||
if (isstrtype(c, r.leaffi.tnode)) {
|
||||
if (r.isglobal) {
|
||||
if (isstrtype(c, leaffi.tnode)) {
|
||||
if (isglobal) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, r.rootname);
|
||||
emitsymname(c, rootname);
|
||||
emitline("(SB), CX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg(r.totaloff + 0i64, "CX");
|
||||
emitdispreg(totaloff, "CX");
|
||||
emitline(", AX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg(r.totaloff + 8i64, "CX");
|
||||
emitdispreg(totaloff + 8i64, "CX");
|
||||
emitline(", BX\n");
|
||||
} else {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff(r.rootoff + r.totaloff);
|
||||
emitoff(rootoff + totaloff);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff(r.rootoff + r.totaloff + 8i64);
|
||||
emitoff(rootoff + totaloff + 8i64);
|
||||
emitline("(BP), BX\n");
|
||||
};
|
||||
return;
|
||||
};
|
||||
if (isfloattype(c, r.leaffi.tnode)) {
|
||||
if (isfloattype(c, leaffi.tnode)) {
|
||||
let mov: str = "MOVSD";
|
||||
if (isf32type(c, r.leaffi.tnode)) { mov = "MOVSS"; };
|
||||
if (r.isglobal) {
|
||||
if (isf32type(c, leaffi.tnode)) { mov = "MOVSS"; };
|
||||
if (isglobal) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, r.rootname);
|
||||
emitsymname(c, rootname);
|
||||
emitline("(SB), CX\n");
|
||||
emitline("\t");
|
||||
emitline(mov);
|
||||
emitline("\t");
|
||||
emitdispreg(r.totaloff, "CX");
|
||||
emitdispreg(totaloff, "CX");
|
||||
emitline(", X0\n");
|
||||
} else {
|
||||
emitline("\t");
|
||||
emitline(mov);
|
||||
emitline("\t");
|
||||
emitoff(r.rootoff + r.totaloff);
|
||||
emitoff(rootoff + totaloff);
|
||||
emitline("(BP), X0\n");
|
||||
};
|
||||
return;
|
||||
};
|
||||
let lop: str = fieldloadop(c, r.leaffi);
|
||||
if (r.isglobal) {
|
||||
let lop: str = fieldloadop(c, leaffi);
|
||||
if (isglobal) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, r.rootname);
|
||||
emitsymname(c, rootname);
|
||||
emitline("(SB), CX\n");
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\t");
|
||||
emitdispreg(r.totaloff, "CX");
|
||||
emitdispreg(totaloff, "CX");
|
||||
emitline(", AX\n");
|
||||
} else {
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\t");
|
||||
emitoff(r.rootoff + r.totaloff);
|
||||
emitoff(rootoff + totaloff);
|
||||
emitline("(BP), AX\n");
|
||||
};
|
||||
return;
|
||||
@@ -1925,21 +1932,28 @@ fn cgun(c: *cgen, n: *node) void = {
|
||||
// nsteps ≥ 2 (matches the read path's gate).
|
||||
if (opnd.lhs != nil) {
|
||||
if (opnd.lhs.kind == nkind.N_DOT) {
|
||||
let r: dotchain;
|
||||
let pok: bool = dotchainresolve(c, opnd, &r);
|
||||
let rootname: str = "";
|
||||
let rootoff: i64 = 0i64;
|
||||
let totaloff: i64 = 0i64;
|
||||
let leaffi: *fieldinfo = nil;
|
||||
let slicedelta: i64 = -1i64;
|
||||
let isglobal: bool = false;
|
||||
let pok: bool = dotchainresolve(c, opnd,
|
||||
&rootname, &rootoff, &totaloff,
|
||||
&leaffi, &slicedelta, &isglobal);
|
||||
if (pok) {
|
||||
let extra: i64 = 0i64;
|
||||
if (r.slicedelta >= 0i64) { extra = r.slicedelta; };
|
||||
if (r.isglobal) {
|
||||
if (slicedelta >= 0i64) { extra = slicedelta; };
|
||||
if (isglobal) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, r.rootname);
|
||||
emitsymname(c, rootname);
|
||||
emitline("(SB), CX\n");
|
||||
emitline("\tLEAQ\t");
|
||||
emitdispreg(r.totaloff + extra, "CX");
|
||||
emitdispreg(totaloff + extra, "CX");
|
||||
emitline(", AX\n");
|
||||
} else {
|
||||
emitline("\tLEAQ\t");
|
||||
emitoff(r.rootoff + r.totaloff + extra);
|
||||
emitoff(rootoff + totaloff + extra);
|
||||
emitline("(BP), AX\n");
|
||||
};
|
||||
return;
|
||||
@@ -3870,85 +3884,92 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
if (lhs.kind == nkind.N_DOT && lhs.lhs != nil
|
||||
&& lhs.lhs.kind == nkind.N_DOT
|
||||
&& n.op == tkind.TK_ASSIGN) {
|
||||
let r: dotchain;
|
||||
let yok: bool = dotchainresolve(c, lhs, &r);
|
||||
let rootname: str = "";
|
||||
let rootoff: i64 = 0i64;
|
||||
let totaloff: i64 = 0i64;
|
||||
let leaffi: *fieldinfo = nil;
|
||||
let slicedelta: i64 = -1i64;
|
||||
let isglobal: bool = false;
|
||||
let yok: bool = dotchainresolve(c, lhs,
|
||||
&rootname, &rootoff, &totaloff,
|
||||
&leaffi, &slicedelta, &isglobal);
|
||||
if (yok) {
|
||||
if (r.slicedelta >= 0i64) {
|
||||
if (slicedelta >= 0i64) {
|
||||
cgexpr(c, n.rhs);
|
||||
if (r.isglobal) {
|
||||
if (isglobal) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, r.rootname);
|
||||
emitsymname(c, rootname);
|
||||
emitline("(SB), CX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitdispreg(r.totaloff + r.slicedelta, "CX");
|
||||
emitdispreg(totaloff + slicedelta, "CX");
|
||||
emitline("\n");
|
||||
} else {
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff(r.rootoff + r.totaloff + r.slicedelta);
|
||||
emitoff(rootoff + totaloff + slicedelta);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
return;
|
||||
};
|
||||
if (isstrtype(c, r.leaffi.tnode)) {
|
||||
if (isstrtype(c, leaffi.tnode)) {
|
||||
cgexpr(c, n.rhs);
|
||||
if (r.isglobal) {
|
||||
if (isglobal) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, r.rootname);
|
||||
emitsymname(c, rootname);
|
||||
emitline("(SB), CX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitdispreg(r.totaloff + 0i64, "CX");
|
||||
emitdispreg(totaloff, "CX");
|
||||
emitline("\n");
|
||||
emitline("\tMOVQ\tBX, ");
|
||||
emitdispreg(r.totaloff + 8i64, "CX");
|
||||
emitdispreg(totaloff + 8i64, "CX");
|
||||
emitline("\n");
|
||||
} else {
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff(r.rootoff + r.totaloff);
|
||||
emitoff(rootoff + totaloff);
|
||||
emitline("(BP)\n");
|
||||
emitline("\tMOVQ\tBX, ");
|
||||
emitoff(r.rootoff + r.totaloff + 8i64);
|
||||
emitoff(rootoff + totaloff + 8i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
return;
|
||||
};
|
||||
if (isfloattype(c, r.leaffi.tnode)) {
|
||||
if (isfloattype(c, leaffi.tnode)) {
|
||||
let mov: str = "MOVSD";
|
||||
if (isf32type(c, r.leaffi.tnode)) { mov = "MOVSS"; };
|
||||
if (isf32type(c, leaffi.tnode)) { mov = "MOVSS"; };
|
||||
cgexpr(c, n.rhs);
|
||||
if (r.isglobal) {
|
||||
if (isglobal) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, r.rootname);
|
||||
emitsymname(c, rootname);
|
||||
emitline("(SB), CX\n");
|
||||
emitline("\t");
|
||||
emitline(mov);
|
||||
emitline("\tX0, ");
|
||||
emitdispreg(r.totaloff, "CX");
|
||||
emitdispreg(totaloff, "CX");
|
||||
emitline("\n");
|
||||
} else {
|
||||
emitline("\t");
|
||||
emitline(mov);
|
||||
emitline("\tX0, ");
|
||||
emitoff(r.rootoff + r.totaloff);
|
||||
emitoff(rootoff + totaloff);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
return;
|
||||
};
|
||||
let sop: str = fieldstoreop(c, r.leaffi);
|
||||
let sop: str = fieldstoreop(c, leaffi);
|
||||
cgexpr(c, n.rhs);
|
||||
if (r.isglobal) {
|
||||
if (isglobal) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, r.rootname);
|
||||
emitsymname(c, rootname);
|
||||
emitline("(SB), CX\n");
|
||||
emitline("\t");
|
||||
emitline(sop);
|
||||
emitline("\tAX, ");
|
||||
emitdispreg(r.totaloff, "CX");
|
||||
emitdispreg(totaloff, "CX");
|
||||
emitline("\n");
|
||||
} else {
|
||||
emitline("\t");
|
||||
emitline(sop);
|
||||
emitline("\tAX, ");
|
||||
emitoff(r.rootoff + r.totaloff);
|
||||
emitoff(rootoff + totaloff);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user