w6c+selfhost: cgen N_DOT slice-field through *T root in call args (closes #29)

This commit is contained in:
2026-05-14 23:29:35 +09:00
parent 9706513e59
commit 6402d8deb7
7 changed files with 857 additions and 24 deletions

View File

@@ -4487,6 +4487,28 @@ cgexpr(Cg *c, Node *n, Local *locals)
areg(D_BX));
goto dot_done;
}
if (fu && fu->kind == TY_SLICE) {
/* Slice leaf: load all three header
* words into (AX=ptr, BX=len, CX=cap)
* so the value follows the canonical
* slice-rhs convention. base_reg may
* be CX (global / `*T` root); load
* .cap LAST so the base survives the
* earlier reads. */
ins2(c, A_MOVQ,
amem(base_reg,
base_disp + total_off + 0),
areg(D_AX));
ins2(c, A_MOVQ,
amem(base_reg,
base_disp + total_off + 8),
areg(D_BX));
ins2(c, A_MOVQ,
amem(base_reg,
base_disp + total_off + 16),
areg(D_CX));
goto dot_done;
}
int g_isf32 = 0;
if (fld_isfloat(leaf_type, &g_isf32)) {
int mov = g_isf32 ? A_MOVSS : A_MOVSD;
@@ -4658,6 +4680,22 @@ cgexpr(Cg *c, Node *n, Local *locals)
areg(D_BX));
break;
}
/* slice field: load (ptr, len, cap) into (AX, BX, CX)
* so the value flows through the slice-rhs convention.
* base_reg may be CX for globals; load .cap LAST so
* the base survives the earlier reads. */
if (str_fu && str_fu->kind == TY_SLICE) {
ins2(c, A_MOVQ,
amem(base_reg, base_disp + (int)f->offset + 0),
areg(D_AX));
ins2(c, A_MOVQ,
amem(base_reg, base_disp + (int)f->offset + 8),
areg(D_BX));
ins2(c, A_MOVQ,
amem(base_reg, base_disp + (int)f->offset + 16),
areg(D_CX));
break;
}
/* f64/f32 field: route through X0 (MOVSD/MOVSS).
* Loading via MOVQ AX would put the bits in the
* integer reg, and any downstream consumer that
@@ -4722,6 +4760,22 @@ cgexpr(Cg *c, Node *n, Local *locals)
ins2(c, A_MOVQ, areg(D_CX), areg(D_BX));
break;
}
/* slice field through *struct: load (ptr, len,
* cap) into (AX, BX, CX). BX holds the *struct
* pointer, so load .len LAST — the earlier loads
* still index off the original base. */
if (str_fu && str_fu->kind == TY_SLICE) {
ins2(c, A_MOVQ,
amem(D_BX, (int)f->offset + 0),
areg(D_AX));
ins2(c, A_MOVQ,
amem(D_BX, (int)f->offset + 16),
areg(D_CX));
ins2(c, A_MOVQ,
amem(D_BX, (int)f->offset + 8),
areg(D_BX));
break;
}
/* f64/f32 field via *struct: load into X0.
* BX already holds the struct pointer from
* the MOVQ amem(D_BP,off) above. */
@@ -4772,6 +4826,21 @@ cgexpr(Cg *c, Node *n, Local *locals)
areg(D_AX));
goto dot_done;
}
/* slice field: load (ptr, len, cap) into
* (AX, BX, CX). AX is the *struct base, so
* load .ptr (which targets AX) LAST. */
if (fu && fu->kind == TY_SLICE) {
ins2(c, A_MOVQ,
amem(D_AX, (int)f->offset + 8),
areg(D_BX));
ins2(c, A_MOVQ,
amem(D_AX, (int)f->offset + 16),
areg(D_CX));
ins2(c, A_MOVQ,
amem(D_AX, (int)f->offset + 0),
areg(D_AX));
goto dot_done;
}
/* f64/f32 chained field: read into X0. */
int g_isf32 = 0;
if (fld_isfloat(ft, &g_isf32)) {