w6c+selfhost: cgen N_ASSIGN TY_STRUCT field branch (closes #25)
Parallel to TY_STR/TY_SLICE branches at cgen.c:1939/1962. Word-copy from src slot to field+k*8 via AX, MOVL/MOVB ragged tail. N_IDENT rhs only — struct-call-result and struct-literal rhs are different code paths, filed as task #27. Symmetric in N_ASSIGN field case AND spine-walker terminal; mirrored in wwstage cgassign four sub-shapes (*struct base, direct local, global, spine terminal).
This commit is contained in:
@@ -1978,6 +1978,43 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* struct-typed field, struct-ident rhs: cgexpr cannot
|
||||
* materialise a whole struct value in registers, so
|
||||
* word-copy from the rhs slot directly to the dest
|
||||
* field. Other rhs shapes (struct-returning call,
|
||||
* struct literal) stay broken at the cgexpr level —
|
||||
* tracked as #27. */
|
||||
if (n->op == TK_ASSIGN && str_fu
|
||||
&& str_fu->kind == TY_STRUCT
|
||||
&& n->rhs && n->rhs->kind == N_IDENT
|
||||
&& localfind(locals, n->rhs->str) != 0) {
|
||||
int soff = localfind(locals, n->rhs->str);
|
||||
int ssz = (int)str_fu->size;
|
||||
if (via_ptr)
|
||||
ins2(c, A_MOVQ, amem(D_BP, boff), areg(D_BX));
|
||||
else if (is_global)
|
||||
ins2(c, A_LEAQ, masym(c, base->str), areg(D_BX));
|
||||
int k = 0;
|
||||
while (k + 8 <= ssz) {
|
||||
ins2(c, A_MOVQ, amem(D_BP, soff + k), areg(D_AX));
|
||||
if (via_ptr || is_global)
|
||||
ins2(c, A_MOVQ, areg(D_AX), amem(D_BX, foff + k));
|
||||
else
|
||||
ins2(c, A_MOVQ, areg(D_AX), amem(D_BP, boff + foff + k));
|
||||
k += 8;
|
||||
}
|
||||
if (k < ssz) {
|
||||
int tail = ssz - k;
|
||||
int lop = (tail == 4) ? A_MOVL
|
||||
: (tail == 1 ? A_MOVB : A_MOVQ);
|
||||
ins2(c, lop, amem(D_BP, soff + k), areg(D_AX));
|
||||
if (via_ptr || is_global)
|
||||
ins2(c, lop, areg(D_AX), amem(D_BX, foff + k));
|
||||
else
|
||||
ins2(c, lop, areg(D_AX), amem(D_BP, boff + foff + k));
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* compound: load current value into BX */
|
||||
if (n->op != TK_ASSIGN) {
|
||||
if (via_ptr) {
|
||||
@@ -2557,6 +2594,53 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* TY_STRUCT terminal: word-copy the rhs slot onto
|
||||
* base+total_off. Only N_IDENT rhs is wired —
|
||||
* other shapes route through #27. */
|
||||
if (fu && fu->kind == TY_STRUCT
|
||||
&& n->rhs && n->rhs->kind == N_IDENT
|
||||
&& localfind(locals, n->rhs->str) != 0) {
|
||||
int soff = localfind(locals, n->rhs->str);
|
||||
int ssz = fsz;
|
||||
if (via_cx) {
|
||||
if (ptr_root)
|
||||
ins2(c, A_MOVQ,
|
||||
amem(D_BP, base_disp),
|
||||
areg(D_CX));
|
||||
else
|
||||
ins2(c, A_LEAQ,
|
||||
masym(c, cur->str),
|
||||
areg(D_CX));
|
||||
}
|
||||
int k = 0;
|
||||
while (k + 8 <= ssz) {
|
||||
ins2(c, A_MOVQ,
|
||||
amem(D_BP, soff + k),
|
||||
areg(D_AX));
|
||||
if (via_cx)
|
||||
ins2(c, A_MOVQ, areg(D_AX),
|
||||
amem(D_CX, total_off + k));
|
||||
else
|
||||
ins2(c, A_MOVQ, areg(D_AX),
|
||||
amem(D_BP, base_disp + total_off + k));
|
||||
k += 8;
|
||||
}
|
||||
if (k < ssz) {
|
||||
int tail = ssz - k;
|
||||
int lop = (tail == 4) ? A_MOVL
|
||||
: (tail == 1 ? A_MOVB : A_MOVQ);
|
||||
ins2(c, lop,
|
||||
amem(D_BP, soff + k),
|
||||
areg(D_AX));
|
||||
if (via_cx)
|
||||
ins2(c, lop, areg(D_AX),
|
||||
amem(D_CX, total_off + k));
|
||||
else
|
||||
ins2(c, lop, areg(D_AX),
|
||||
amem(D_BP, base_disp + total_off + k));
|
||||
}
|
||||
break;
|
||||
}
|
||||
int sf32 = 0;
|
||||
if (fld_isfloat(leaf_type, &sf32)) {
|
||||
int mov = sf32 ? A_MOVSS : A_MOVSD;
|
||||
|
||||
Reference in New Issue
Block a user