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:
@@ -5257,6 +5257,39 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
fatal("array-literal store at assignment "
|
||||
"unwired (task #32)");
|
||||
}
|
||||
/* A plain aggregate field-to-field assignment is a memory copy,
|
||||
* not a scalar expression/store. The legacy direct-field arms
|
||||
* below enumerate CALL, STRUCTLIT, and local IDENT producers; an
|
||||
* addressable N_DOT/N_INDEX/deref rhs fell through, so a 16-byte
|
||||
* time.instant copied only its first word. Resolve both places
|
||||
* through the existing generic address funnels and use the single
|
||||
* tail-aware aggregate copier. Calls/literals/unwraps stay on their
|
||||
* specialized ABI paths, and tagged/str/slice fields are excluded by
|
||||
* the destination type gate. */
|
||||
if (n->op == TK_ASSIGN && n->lhs
|
||||
&& n->lhs->kind == N_DOT && n->lhs->lhs
|
||||
&& (n->lhs->lhs->kind == N_IDENT
|
||||
|| n->lhs->lhs->kind == N_DOT
|
||||
|| (n->lhs->lhs->kind == N_UN
|
||||
&& n->lhs->lhs->op == TK_STAR))
|
||||
&& n->rhs) {
|
||||
Type *au = type_chase_named(n->lhs->type);
|
||||
int memrhs = n->rhs->kind == N_IDENT
|
||||
|| n->rhs->kind == N_DOT
|
||||
|| n->rhs->kind == N_INDEX
|
||||
|| (n->rhs->kind == N_UN && n->rhs->op == TK_STAR);
|
||||
if (au && (au->kind == TY_STRUCT || au->kind == TY_ARRAY
|
||||
|| au->kind == TY_TUPLE) && memrhs) {
|
||||
if (!cgplaceaddr(c, n->lhs, D_BX, locals))
|
||||
fatal("aggregate field destination unresolved");
|
||||
ins1(c, A_PUSHQ, areg(D_BX));
|
||||
if (!aggarg_srcaddr(c, n->rhs, D_SI, locals))
|
||||
fatal("aggregate field source unresolved");
|
||||
ins1(c, A_POPQ, areg(D_BX));
|
||||
cg_aggcopy(c, (int)au->size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* #16: a single-dot aggregate-field unwrap store whose base
|
||||
* is a module-GLOBAL value-struct (`g.f = mk()!`) or a
|
||||
* CHAINED struct field (`o.m.f = mk()!`). The #12 single-dot
|
||||
|
||||
Reference in New Issue
Block a user