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:
2026-05-14 03:18:49 +09:00
parent 79c758c046
commit eb0602d070
5 changed files with 221 additions and 0 deletions

View File

@@ -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) {