w6c+selfhost: cgen N_DOT slice-field through *T root in call args (closes #29)
This commit is contained in:
@@ -1202,6 +1202,21 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
emitdispreg(fi.foff: i64, "BX");
|
||||
emitline(", AX\n");
|
||||
emitline("\tMOVQ\tCX, BX\n");
|
||||
} else { if (isslicetype(c, fi.tnode)) {
|
||||
// slice field via *struct: load
|
||||
// (ptr, len, cap) into (AX, BX, CX).
|
||||
// BX holds the *struct pointer, so
|
||||
// load .len LAST so the earlier
|
||||
// reads still index off the base.
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg(fi.foff: i64, "BX");
|
||||
emitline(", AX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg((fi.foff + 16): i64, "BX");
|
||||
emitline(", CX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg((fi.foff + 8): i64, "BX");
|
||||
emitline(", BX\n");
|
||||
} else { if (isfloattype(c, fi.tnode)) {
|
||||
// f64/f32 via *struct: route through X0.
|
||||
// MOVQ into AX leaves the SSE reg stale
|
||||
@@ -1222,7 +1237,7 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
emitline("\t");
|
||||
emitdispreg(fi.foff: i64, "BX");
|
||||
emitline(", AX\n");
|
||||
}; };
|
||||
}; }; };
|
||||
return;
|
||||
};
|
||||
fi = fi.finext;
|
||||
@@ -1248,6 +1263,19 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((lc.off + fi.foff + 8): i64);
|
||||
emitline("(BP), BX\n");
|
||||
} else { if (isslicetype(c, fi.tnode)) {
|
||||
// slice field: load (ptr, len, cap)
|
||||
// into (AX, BX, CX). Base is BP so
|
||||
// no aliasing — order doesn't matter.
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((lc.off + fi.foff): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((lc.off + fi.foff + 8): i64);
|
||||
emitline("(BP), BX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((lc.off + fi.foff + 16): i64);
|
||||
emitline("(BP), CX\n");
|
||||
} else { if (isfloattype(c, fi.tnode)) {
|
||||
// f64/f32 field: route through X0.
|
||||
let mov: str = "MOVSD";
|
||||
@@ -1264,7 +1292,7 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
emitline("\t");
|
||||
emitoff((lc.off + fi.foff): i64);
|
||||
emitline("(BP), AX\n");
|
||||
}; };
|
||||
}; }; };
|
||||
return;
|
||||
};
|
||||
fi = fi.finext;
|
||||
@@ -1673,6 +1701,45 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
};
|
||||
return;
|
||||
};
|
||||
if (isslicetype(c, leaffi.tnode)) {
|
||||
// Slice leaf: load all three header words into
|
||||
// (AX=ptr, BX=len, CX=cap). For the viacx path
|
||||
// (global or `*T` root) CX is the base; load
|
||||
// .cap LAST so the base survives the earlier
|
||||
// reads. For BP-rooted locals the registers
|
||||
// don't alias so order is free.
|
||||
if (viacx) {
|
||||
if (ptrroot) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff(rootoff: i64);
|
||||
emitline("(BP), CX\n");
|
||||
} else {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, rootname);
|
||||
emitline("(SB), CX\n");
|
||||
};
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg(totaloff: i64, "CX");
|
||||
emitline(", AX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg((totaloff + 8): i64, "CX");
|
||||
emitline(", BX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg((totaloff + 16): i64, "CX");
|
||||
emitline(", CX\n");
|
||||
} else {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((rootoff + totaloff): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((rootoff + totaloff + 8): i64);
|
||||
emitline("(BP), BX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((rootoff + totaloff + 16): i64);
|
||||
emitline("(BP), CX\n");
|
||||
};
|
||||
return;
|
||||
};
|
||||
if (isfloattype(c, leaffi.tnode)) {
|
||||
let mov: str = "MOVSD";
|
||||
if (isf32type(c, leaffi.tnode)) { mov = "MOVSS"; };
|
||||
@@ -1767,6 +1834,22 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
emitline(", AX\n");
|
||||
return;
|
||||
};
|
||||
// slice field: load (ptr, len, cap)
|
||||
// into (AX, BX, CX). AX is the *struct
|
||||
// base, so load .ptr (which targets
|
||||
// AX) LAST.
|
||||
if (isslicetype(c, fi.tnode)) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg((fi.foff + 8): i64, "AX");
|
||||
emitline(", BX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg((fi.foff + 16): i64, "AX");
|
||||
emitline(", CX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg(fi.foff: i64, "AX");
|
||||
emitline(", AX\n");
|
||||
return;
|
||||
};
|
||||
// f64/f32 chained field: route through X0.
|
||||
if (isfloattype(c, fi.tnode)) {
|
||||
let mov: str = "MOVSD";
|
||||
|
||||
Reference in New Issue
Block a user