cgen: route aggregate field-to-field assignment through the aggregate copier
The direct-field assignment arms enumerate CALL, STRUCTLIT, and local IDENT producers; an addressable N_DOT/N_INDEX/deref rhs fell through to the scalar tail, so a 16-byte struct field copied only its first word. Resolve both places through the existing address funnels and use the tail-aware aggregate copier. Both stages.
This commit is contained in:
@@ -8719,6 +8719,48 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
||||
};
|
||||
};
|
||||
};
|
||||
// A plain aggregate field-to-field assignment is a memory copy, not
|
||||
// a scalar expression/store. The direct-field arms below enumerate
|
||||
// CALL, STRUCTLIT and local IDENT producers; an addressable DOT/INDEX/
|
||||
// deref rhs fell through, so a 16-byte time.instant copied one word.
|
||||
// Resolve both places through the existing address funnels and use the
|
||||
// canonical tail-aware aggregate copier. Calls/literals/unwraps and
|
||||
// tagged/str/slice fields remain on their specialized ABI paths.
|
||||
if (lhs != nil && n.rhs != nil && n.op == syntax.tkind.TK_ASSIGN) {
|
||||
if (lhs.kind == syntax.nkind.N_DOT && lhs.lhs != nil
|
||||
&& (lhs.lhs.kind == syntax.nkind.N_IDENT
|
||||
|| lhs.lhs.kind == syntax.nkind.N_DOT
|
||||
|| (lhs.lhs.kind == syntax.nkind.N_UN
|
||||
&& lhs.lhs.op == syntax.tkind.TK_STAR))) {
|
||||
let au: *syntax.tinfo = lhs.type_: *syntax.tinfo;
|
||||
au = tichase(au);
|
||||
let memrhs: bool = n.rhs.kind == syntax.nkind.N_IDENT
|
||||
|| n.rhs.kind == syntax.nkind.N_DOT
|
||||
|| n.rhs.kind == syntax.nkind.N_INDEX
|
||||
|| (n.rhs.kind == syntax.nkind.N_UN
|
||||
&& n.rhs.op == syntax.tkind.TK_STAR);
|
||||
if (au != nil && memrhs) {
|
||||
if (au.kind == syntax.tykind.TY_STRUCT
|
||||
|| au.kind == syntax.tykind.TY_ARRAY
|
||||
|| au.kind == syntax.tykind.TY_TUPLE) {
|
||||
if (!cgplaceaddr(c, lhs, "BX")) {
|
||||
let md: str = "aggregate field destination unresolved\n";
|
||||
os.write(2, md.ptr, md.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
emitline("\tPUSHQ\tBX\n");
|
||||
if (!aggargsrcaddr(c, n.rhs, "SI")) {
|
||||
let ms: str = "aggregate field source unresolved\n";
|
||||
os.write(2, ms.ptr, ms.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
emitline("\tPOPQ\tBX\n");
|
||||
aggcopy(c, au.size: i32);
|
||||
return;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
// #21: a COMPOUND op on a whole tagged-union IDENT (`g OP= v`
|
||||
// with g:(int|bool)) is nonsense — the ident load-combine-store
|
||||
// tail below reads and writes one word of the {payload,tag} box,
|
||||
|
||||
Reference in New Issue
Block a user