w6c+selfhost: float globals — DATAW + LEAQ-indirect MOVSS/MOVSD
f32 → 4B slot, f64 → 8B. C cgen bakes the FLOATLIT bit pattern into DATAW directly; selfhost emits zero-init only (its parser doesn't lex N_FLOATLIT yet). Read/write goes LEAQ name(SB),CX + MOVSS/MOVSD since w6a has no D_EXTERN operand form for SSE moves.
This commit is contained in:
@@ -398,8 +398,8 @@ struct LetVar {
|
||||
static LetVar *letvars;
|
||||
|
||||
/* Slot size for a top-level `let` of type t, or 0 if the type isn't
|
||||
* supported as a writable global yet. Floats (MOVSS/SD) and tagged
|
||||
* unions are deferred. enums route through their storage type.
|
||||
* supported as a writable global yet. Tagged unions are deferred.
|
||||
* enums route through their storage type.
|
||||
* Keep this tight — extending it requires the matching load/store
|
||||
* code below. */
|
||||
static int
|
||||
@@ -415,6 +415,10 @@ let_emit_size(Type *t)
|
||||
case TY_INT: case TY_UINT: case TY_UINTPTR:
|
||||
case TY_PTR:
|
||||
return 8;
|
||||
case TY_F32:
|
||||
return 4; /* MOVSS loads/stores 4B via LEAQ+indir. */
|
||||
case TY_F64:
|
||||
return 8; /* MOVSD loads/stores 8B via LEAQ+indir. */
|
||||
case TY_STR:
|
||||
return 16; /* {ptr, len}; literal-strlit init NYI. */
|
||||
case TY_SLICE:
|
||||
@@ -459,6 +463,17 @@ let_isstruct(Type *t)
|
||||
return u && u->kind == TY_STRUCT;
|
||||
}
|
||||
|
||||
/* Is the unwrapped type a float (f32 or f64)? Float globals flow
|
||||
* through X0 — load/store goes LEAQ name(SB),CX → MOVSS/MOVSD via the
|
||||
* indirect, since the asm has no D_EXTERN form for SSE moves yet. */
|
||||
static int
|
||||
let_isfloat(Type *t)
|
||||
{
|
||||
if (t == NULL) return 0;
|
||||
Type *u = (t->kind == TY_NAMED) ? t->under : t;
|
||||
return u && (u->kind == TY_F32 || u->kind == TY_F64);
|
||||
}
|
||||
|
||||
/* Returns the unwrapped Type — handy when we need to walk struct
|
||||
* fields. NULL if t is NULL or unresolved. */
|
||||
static Type *
|
||||
@@ -815,6 +830,15 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
ins2(c, A_MOVQ, amem(D_CX, 16), areg(D_CX));
|
||||
goto ident_done;
|
||||
}
|
||||
if (let_islet(n->str) && let_isfloat(n->type)) {
|
||||
/* Top-level float global: same LEAQ-indirect
|
||||
* shape as str/slice, since MOVSS/MOVSD have
|
||||
* no D_EXTERN operand form in w6a. */
|
||||
int op = type_isf32(n->type) ? A_MOVSS : A_MOVSD;
|
||||
ins2(c, A_LEAQ, masym(c, n->str), areg(D_CX));
|
||||
ins2(c, op, amem(D_CX, 0), areg(D_X0));
|
||||
goto ident_done;
|
||||
}
|
||||
ins2(c, A_MOVQ, masym(c, n->str), areg(D_AX));
|
||||
}
|
||||
ident_done:
|
||||
@@ -1363,13 +1387,17 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
}
|
||||
}
|
||||
}
|
||||
/* float assignment to a local */
|
||||
/* float assignment to a local or top-level global. Globals
|
||||
* route through LEAQ+indirect (no D_EXTERN SSE in w6a). */
|
||||
if (n->lhs && n->lhs->kind == N_IDENT && node_isfloat(n)) {
|
||||
cgexpr(c, n->rhs, locals); /* X0 */
|
||||
int op = op_for(n, A_MOVSD, A_MOVSS);
|
||||
int off = localfind(locals, n->lhs->str);
|
||||
if (off != 0) {
|
||||
int op = op_for(n, A_MOVSD, A_MOVSS);
|
||||
ins2(c, op, areg(D_X0), amem(D_BP, off));
|
||||
} else if (let_islet(n->lhs->str)) {
|
||||
ins2(c, A_LEAQ, masym(c, n->lhs->str), areg(D_CX));
|
||||
ins2(c, op, areg(D_X0), amem(D_CX, 0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -3745,6 +3773,31 @@ emit_lets(Cg *c, FILE *out, Node *file)
|
||||
if (d->str == NULL || d->str[0] == '\0') continue;
|
||||
int sz = let_emit_size(d->type);
|
||||
if (sz == 0) continue;
|
||||
if (let_isfloat(d->type)) {
|
||||
/* sz is 4 (f32) or 8 (f64). FLOATLIT init or zero. */
|
||||
int isf32 = type_isf32(d->type);
|
||||
u64 v = 0;
|
||||
if (d->rhs != NULL) {
|
||||
Node *r = d->rhs;
|
||||
while (r != NULL && r->kind == N_CAST) r = r->lhs;
|
||||
if (r == NULL) continue;
|
||||
if (r->kind != N_FLOATLIT) continue;
|
||||
if (isf32) {
|
||||
union { float f; u32 u; } x;
|
||||
x.f = (float)r->fval;
|
||||
v = (u64)x.u;
|
||||
} else {
|
||||
union { double d; u64 u; } x;
|
||||
x.d = r->fval;
|
||||
v = x.u;
|
||||
}
|
||||
}
|
||||
fprintf(out, "DATAW %s(SB),\"", mod_mangle(c, d->str));
|
||||
for (int i = 0; i < sz; i++)
|
||||
emit_data_byte(out, (u8)((v >> (i * 8)) & 0xff));
|
||||
fputs("\"\n", out);
|
||||
continue;
|
||||
}
|
||||
if (sz == 8) {
|
||||
u64 v = 0;
|
||||
if (d->rhs != NULL) {
|
||||
|
||||
Reference in New Issue
Block a user