w6c+selfhost: cgen N_DOT N_INDEX-lhs branch (closes #8)
cstage cmd/w6c/cgen.c gained the missing N_DOT N_INDEX-lhs branch. Covers both [N]*Struct and [N]Struct via fldloadop. wwstage already handled [N]*Struct since 7c75dd2; refactored to mirror cstage exactly and added [N]Struct. The spill workaround in dotchainresolve stays (Pike rule); task #14 retires it as a follow-up. Wwstage cgassign N_DOT(N_INDEX,...) silent store-drop discovered in scope, filed as task #16.
This commit is contained in:
@@ -4253,6 +4253,98 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
}
|
||||
}
|
||||
}
|
||||
/* `arr[i].field` — element-then-field through a `[N]*S` /
|
||||
* `[N]S` (and slice/`*[N]S`) base. One branch covers both
|
||||
* shapes: compute `&arr[i]` into BX, then either deref
|
||||
* (`*Struct` element) or move-to-AX (value `Struct` element),
|
||||
* so the leaf load is `(field.offset)(AX)` either way.
|
||||
* Bypasses cgindex deliberately — cgindex's final MOVQ
|
||||
* would truncate a value-struct element to 8 bytes. Mirrors
|
||||
* selfhost/cmd/wcc/cgenexpr.ww's cgdot N_INDEX-lhs branch. */
|
||||
if (n->lhs && n->lhs->kind == N_INDEX && n->lhs->lhs
|
||||
&& n->lhs->lhs->kind == N_IDENT) {
|
||||
Node *idxbase = n->lhs->lhs;
|
||||
Type *elemt = n->lhs->type;
|
||||
Type *elemu = (elemt && elemt->kind == TY_NAMED)
|
||||
? elemt->under : elemt;
|
||||
Type *struct_t = NULL;
|
||||
int viaptr = 0;
|
||||
if (elemu && elemu->kind == TY_PTR) {
|
||||
Type *inner = elemu->sub;
|
||||
if (inner && inner->kind == TY_NAMED)
|
||||
inner = inner->under;
|
||||
if (inner && inner->kind == TY_STRUCT) {
|
||||
struct_t = inner;
|
||||
viaptr = 1;
|
||||
}
|
||||
} else if (elemu && elemu->kind == TY_STRUCT) {
|
||||
struct_t = elemu;
|
||||
}
|
||||
if (struct_t) {
|
||||
Tfield *f = NULL;
|
||||
for (Tfield *fl = struct_t->fields; fl; fl = fl->next)
|
||||
if (strcmp(fl->name, n->str) == 0)
|
||||
{ f = fl; break; }
|
||||
Type *bt = idxbase->type;
|
||||
Type *bu = (bt && bt->kind == TY_NAMED)
|
||||
? bt->under : bt;
|
||||
int is_arr = bu && bu->kind == TY_ARRAY;
|
||||
int is_sl = bu && bu->kind == TY_SLICE;
|
||||
int is_ptr = bu && bu->kind == TY_PTR;
|
||||
int off = localfind(locals, idxbase->str);
|
||||
if (f != NULL && (is_arr || is_sl || is_ptr)
|
||||
&& off != 0) {
|
||||
int esz = (int)elemt->size;
|
||||
cgexpr(c, n->lhs->rhs, locals);
|
||||
if (esz > 1) {
|
||||
ins2(c, A_MOVQ, aimm(esz),
|
||||
areg(D_CX));
|
||||
ins2(c, A_IMULQ, areg(D_CX),
|
||||
areg(D_AX));
|
||||
}
|
||||
if (is_arr)
|
||||
ins2(c, A_LEAQ,
|
||||
amem(D_BP, off), areg(D_BX));
|
||||
else
|
||||
ins2(c, A_MOVQ,
|
||||
amem(D_BP, off), areg(D_BX));
|
||||
ins2(c, A_ADDQ, areg(D_AX), areg(D_BX));
|
||||
if (viaptr)
|
||||
ins2(c, A_MOVQ,
|
||||
amem(D_BX, 0), areg(D_AX));
|
||||
else
|
||||
ins2(c, A_MOVQ, areg(D_BX),
|
||||
areg(D_AX));
|
||||
int foff = (int)f->offset;
|
||||
Type *ft = f->type;
|
||||
Type *fu = (ft && ft->kind == TY_NAMED)
|
||||
? ft->under : ft;
|
||||
if (fu && fu->kind == TY_STR) {
|
||||
ins2(c, A_MOVQ,
|
||||
amem(D_AX, foff + 8),
|
||||
areg(D_BX));
|
||||
ins2(c, A_MOVQ,
|
||||
amem(D_AX, foff + 0),
|
||||
areg(D_AX));
|
||||
goto dot_done;
|
||||
}
|
||||
int g_isf32 = 0;
|
||||
if (fld_isfloat(ft, &g_isf32)) {
|
||||
int mov = g_isf32
|
||||
? A_MOVSS : A_MOVSD;
|
||||
ins2(c, mov,
|
||||
amem(D_AX, foff),
|
||||
areg(D_X0));
|
||||
goto dot_done;
|
||||
}
|
||||
int fsz = (int)(ft ? ft->size : 8);
|
||||
int op = fldloadop(ft, fsz);
|
||||
ins2(c, op, amem(D_AX, foff),
|
||||
areg(D_AX));
|
||||
goto dot_done;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Nested module-qualified field where the chain didn't fold to
|
||||
* a known shape (typical when w6c runs on a single file with
|
||||
* `use mod;` but no driver concatenation — the body's enum /
|
||||
|
||||
Reference in New Issue
Block a user