w6c+selfhost: cgen N_ASSIGN TY_SLICE field branch (closes #24)
Parallel to the existing TY_STR branch at cgen.c:1939. Stores AX/BX/CX at field+0/+8/+16 across three sub-shapes (via_ptr, is_global, direct local) — DX as addr scratch where needed so CX (cap) survives. Symmetric in wwstage cgassign. Surfaces tasks #25 (whole-struct rhs) and #26 (whole-tagged rhs) in the same locus class.
This commit is contained in:
@@ -1952,6 +1952,32 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* slice-typed field: rhs cgexpr leaves (AX=ptr,
|
||||
* BX=len, CX=cap); store all three at
|
||||
* field+0/+8/+16. Address scratch must dodge CX
|
||||
* (holds cap), so via_ptr/is_global stage the
|
||||
* struct base in DX. Without this branch the
|
||||
* generic store_op below writes only AX, silently
|
||||
* dropping .len and .cap. */
|
||||
if (n->op == TK_ASSIGN && str_fu && str_fu->kind == TY_SLICE) {
|
||||
cgexpr(c, n->rhs, locals);
|
||||
if (via_ptr) {
|
||||
ins2(c, A_MOVQ, amem(D_BP, boff), areg(D_DX));
|
||||
ins2(c, A_MOVQ, areg(D_AX), amem(D_DX, foff + 0));
|
||||
ins2(c, A_MOVQ, areg(D_BX), amem(D_DX, foff + 8));
|
||||
ins2(c, A_MOVQ, areg(D_CX), amem(D_DX, foff + 16));
|
||||
} else if (is_global) {
|
||||
ins2(c, A_LEAQ, masym(c, base->str), areg(D_DX));
|
||||
ins2(c, A_MOVQ, areg(D_AX), amem(D_DX, foff + 0));
|
||||
ins2(c, A_MOVQ, areg(D_BX), amem(D_DX, foff + 8));
|
||||
ins2(c, A_MOVQ, areg(D_CX), amem(D_DX, foff + 16));
|
||||
} else {
|
||||
ins2(c, A_MOVQ, areg(D_AX), amem(D_BP, boff + foff + 0));
|
||||
ins2(c, A_MOVQ, areg(D_BX), amem(D_BP, boff + foff + 8));
|
||||
ins2(c, A_MOVQ, areg(D_CX), amem(D_BP, boff + foff + 16));
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* compound: load current value into BX */
|
||||
if (n->op != TK_ASSIGN) {
|
||||
if (via_ptr) {
|
||||
|
||||
Reference in New Issue
Block a user