wcc: f32 array-element store from X0 (#122)
Float array-element stores (array-literal init, [v...] repeat-fill, and arr[i]=v) now route from X0 via MOVSS/MOVSD in both stages; the AX path stored the raw double low-bits, garbage for f32 (f64 worked by accident). A clobbering call-index (a[geti()]=v) loses the X0 value — deferred to #125.
This commit is contained in:
@@ -18444,6 +18444,24 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
emitline("\tMOVQ\tCX, 16(BX)\n");
|
||||
return;
|
||||
};
|
||||
// float element → store FROM X0 (MOVSS/MOVSD): cgexpr
|
||||
// left the value in X0. X0 survives the index/base
|
||||
// eval only for literal/local-var indices; a call-
|
||||
// index (a[geti()]=v) clobbers X0 and loses the value
|
||||
// — this path does not spill X0 across the eval,
|
||||
// unlike the *p=v float deref store. Deferred to #125.
|
||||
// For f32 the #104 CVTSD2SS narrowing only touches X0,
|
||||
// so the AX store below would write raw double low-
|
||||
// bits, garbage for f32 (#122, mirrors cstage cgen.c
|
||||
// arr[i]= float store).
|
||||
if (isfloattype(c, elemtn)) {
|
||||
let fmov: str = "MOVSD";
|
||||
if (isf32type(c, elemtn)) { fmov = "MOVSS"; };
|
||||
emitline("\t");
|
||||
emitline(fmov);
|
||||
emitline("\tX0, (BX)\n");
|
||||
return;
|
||||
};
|
||||
let isop: str = tnodestoreop(c, elemtn, esz);
|
||||
emitline("\t");
|
||||
emitline(isop);
|
||||
@@ -21435,6 +21453,14 @@ fn cglet(c: *cgen, n: *node) void = {
|
||||
};
|
||||
};
|
||||
let mop: str = tnodestoreop(c, elemn, esz);
|
||||
// float element → store FROM X0 (MOVSS/MOVSD): cgexpr
|
||||
// leaves a float in X0 and for f32 the #104 CVTSD2SS
|
||||
// narrowing only touches X0; the AX store (mop) would
|
||||
// write the raw double low-bits, garbage for f32 (#122,
|
||||
// mirrors cstage cgen.c:6889 arr-lit float store).
|
||||
let isfloatel: bool = isfloattype(c, elemn);
|
||||
let fmov: str = "MOVSD";
|
||||
if (isf32type(c, elemn)) { fmov = "MOVSS"; };
|
||||
let idx: i32 = 0;
|
||||
let repeat: bool = false;
|
||||
let e: *node = rhs.list;
|
||||
@@ -21457,13 +21483,19 @@ fn cglet(c: *cgen, n: *node) void = {
|
||||
emitline("\tMOVQ\tBX, ");
|
||||
emitoff((off + idx * esz + 8): i64);
|
||||
emitline("(BP)\n");
|
||||
} else { if (isfloatel) {
|
||||
emitline("\t");
|
||||
emitline(fmov);
|
||||
emitline("\tX0, ");
|
||||
emitoff((off + idx * esz): i64);
|
||||
emitline("(BP)\n");
|
||||
} else {
|
||||
emitline("\t");
|
||||
emitline(mop);
|
||||
emitline("\tAX, ");
|
||||
emitoff((off + idx * esz): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
}; };
|
||||
idx += 1;
|
||||
e = e.next;
|
||||
};
|
||||
@@ -21489,13 +21521,19 @@ fn cglet(c: *cgen, n: *node) void = {
|
||||
emitline("\tMOVQ\tBX, ");
|
||||
emitoff((off + idx * esz + 8): i64);
|
||||
emitline("(BP)\n");
|
||||
} else { if (isfloatel) {
|
||||
emitline("\t");
|
||||
emitline(fmov);
|
||||
emitline("\tX0, ");
|
||||
emitoff((off + idx * esz): i64);
|
||||
emitline("(BP)\n");
|
||||
} else {
|
||||
emitline("\t");
|
||||
emitline(mop);
|
||||
emitline("\tAX, ");
|
||||
emitoff((off + idx * esz): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
}; };
|
||||
idx += 1;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4206,6 +4206,24 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
emitline("\tMOVQ\tCX, 16(BX)\n");
|
||||
return;
|
||||
};
|
||||
// float element → store FROM X0 (MOVSS/MOVSD): cgexpr
|
||||
// left the value in X0. X0 survives the index/base
|
||||
// eval only for literal/local-var indices; a call-
|
||||
// index (a[geti()]=v) clobbers X0 and loses the value
|
||||
// — this path does not spill X0 across the eval,
|
||||
// unlike the *p=v float deref store. Deferred to #125.
|
||||
// For f32 the #104 CVTSD2SS narrowing only touches X0,
|
||||
// so the AX store below would write raw double low-
|
||||
// bits, garbage for f32 (#122, mirrors cstage cgen.c
|
||||
// arr[i]= float store).
|
||||
if (isfloattype(c, elemtn)) {
|
||||
let fmov: str = "MOVSD";
|
||||
if (isf32type(c, elemtn)) { fmov = "MOVSS"; };
|
||||
emitline("\t");
|
||||
emitline(fmov);
|
||||
emitline("\tX0, (BX)\n");
|
||||
return;
|
||||
};
|
||||
let isop: str = tnodestoreop(c, elemtn, esz);
|
||||
emitline("\t");
|
||||
emitline(isop);
|
||||
|
||||
@@ -962,6 +962,14 @@ fn cglet(c: *cgen, n: *node) void = {
|
||||
};
|
||||
};
|
||||
let mop: str = tnodestoreop(c, elemn, esz);
|
||||
// float element → store FROM X0 (MOVSS/MOVSD): cgexpr
|
||||
// leaves a float in X0 and for f32 the #104 CVTSD2SS
|
||||
// narrowing only touches X0; the AX store (mop) would
|
||||
// write the raw double low-bits, garbage for f32 (#122,
|
||||
// mirrors cstage cgen.c:6889 arr-lit float store).
|
||||
let isfloatel: bool = isfloattype(c, elemn);
|
||||
let fmov: str = "MOVSD";
|
||||
if (isf32type(c, elemn)) { fmov = "MOVSS"; };
|
||||
let idx: i32 = 0;
|
||||
let repeat: bool = false;
|
||||
let e: *node = rhs.list;
|
||||
@@ -984,13 +992,19 @@ fn cglet(c: *cgen, n: *node) void = {
|
||||
emitline("\tMOVQ\tBX, ");
|
||||
emitoff((off + idx * esz + 8): i64);
|
||||
emitline("(BP)\n");
|
||||
} else { if (isfloatel) {
|
||||
emitline("\t");
|
||||
emitline(fmov);
|
||||
emitline("\tX0, ");
|
||||
emitoff((off + idx * esz): i64);
|
||||
emitline("(BP)\n");
|
||||
} else {
|
||||
emitline("\t");
|
||||
emitline(mop);
|
||||
emitline("\tAX, ");
|
||||
emitoff((off + idx * esz): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
}; };
|
||||
idx += 1;
|
||||
e = e.next;
|
||||
};
|
||||
@@ -1016,13 +1030,19 @@ fn cglet(c: *cgen, n: *node) void = {
|
||||
emitline("\tMOVQ\tBX, ");
|
||||
emitoff((off + idx * esz + 8): i64);
|
||||
emitline("(BP)\n");
|
||||
} else { if (isfloatel) {
|
||||
emitline("\t");
|
||||
emitline(fmov);
|
||||
emitline("\tX0, ");
|
||||
emitoff((off + idx * esz): i64);
|
||||
emitline("(BP)\n");
|
||||
} else {
|
||||
emitline("\t");
|
||||
emitline(mop);
|
||||
emitline("\tAX, ");
|
||||
emitoff((off + idx * esz): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
}; };
|
||||
idx += 1;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -18444,6 +18444,24 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
emitline("\tMOVQ\tCX, 16(BX)\n");
|
||||
return;
|
||||
};
|
||||
// float element → store FROM X0 (MOVSS/MOVSD): cgexpr
|
||||
// left the value in X0. X0 survives the index/base
|
||||
// eval only for literal/local-var indices; a call-
|
||||
// index (a[geti()]=v) clobbers X0 and loses the value
|
||||
// — this path does not spill X0 across the eval,
|
||||
// unlike the *p=v float deref store. Deferred to #125.
|
||||
// For f32 the #104 CVTSD2SS narrowing only touches X0,
|
||||
// so the AX store below would write raw double low-
|
||||
// bits, garbage for f32 (#122, mirrors cstage cgen.c
|
||||
// arr[i]= float store).
|
||||
if (isfloattype(c, elemtn)) {
|
||||
let fmov: str = "MOVSD";
|
||||
if (isf32type(c, elemtn)) { fmov = "MOVSS"; };
|
||||
emitline("\t");
|
||||
emitline(fmov);
|
||||
emitline("\tX0, (BX)\n");
|
||||
return;
|
||||
};
|
||||
let isop: str = tnodestoreop(c, elemtn, esz);
|
||||
emitline("\t");
|
||||
emitline(isop);
|
||||
@@ -21435,6 +21453,14 @@ fn cglet(c: *cgen, n: *node) void = {
|
||||
};
|
||||
};
|
||||
let mop: str = tnodestoreop(c, elemn, esz);
|
||||
// float element → store FROM X0 (MOVSS/MOVSD): cgexpr
|
||||
// leaves a float in X0 and for f32 the #104 CVTSD2SS
|
||||
// narrowing only touches X0; the AX store (mop) would
|
||||
// write the raw double low-bits, garbage for f32 (#122,
|
||||
// mirrors cstage cgen.c:6889 arr-lit float store).
|
||||
let isfloatel: bool = isfloattype(c, elemn);
|
||||
let fmov: str = "MOVSD";
|
||||
if (isf32type(c, elemn)) { fmov = "MOVSS"; };
|
||||
let idx: i32 = 0;
|
||||
let repeat: bool = false;
|
||||
let e: *node = rhs.list;
|
||||
@@ -21457,13 +21483,19 @@ fn cglet(c: *cgen, n: *node) void = {
|
||||
emitline("\tMOVQ\tBX, ");
|
||||
emitoff((off + idx * esz + 8): i64);
|
||||
emitline("(BP)\n");
|
||||
} else { if (isfloatel) {
|
||||
emitline("\t");
|
||||
emitline(fmov);
|
||||
emitline("\tX0, ");
|
||||
emitoff((off + idx * esz): i64);
|
||||
emitline("(BP)\n");
|
||||
} else {
|
||||
emitline("\t");
|
||||
emitline(mop);
|
||||
emitline("\tAX, ");
|
||||
emitoff((off + idx * esz): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
}; };
|
||||
idx += 1;
|
||||
e = e.next;
|
||||
};
|
||||
@@ -21489,13 +21521,19 @@ fn cglet(c: *cgen, n: *node) void = {
|
||||
emitline("\tMOVQ\tBX, ");
|
||||
emitoff((off + idx * esz + 8): i64);
|
||||
emitline("(BP)\n");
|
||||
} else { if (isfloatel) {
|
||||
emitline("\t");
|
||||
emitline(fmov);
|
||||
emitline("\tX0, ");
|
||||
emitoff((off + idx * esz): i64);
|
||||
emitline("(BP)\n");
|
||||
} else {
|
||||
emitline("\t");
|
||||
emitline(mop);
|
||||
emitline("\tAX, ");
|
||||
emitoff((off + idx * esz): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
}; };
|
||||
idx += 1;
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user