wcc: struct-param float fields via SSE arg regs (#165)
struct params were passed GP-only, so a struct{f64,f64} argument landed in
DI/SI instead of X0/X1 — value-correct for internal ww calls (the bits
round-trip) but not SysV register-class conformant. Add a per-eightbyte
classifier (struct_float_class) routing a qualifying struct's float eightbytes
through the SSE arg cursor, reusing #163's dual-cursor plumbing and #164's
field classification. A struct qualifies only when every eightbyte is
pure-integer or a lone f64 exactly filling it (and >=1 f64); anything else —
any f32, multiple floats per eightbyte, a straddling or aggregate field —
falls back to the unchanged GP path (f32 sub-eightbyte packing deferred #165b).
Both stages' predicates are alias-aware and identical in coverage.
Gate-blind and value-correct either way, so the discriminator is the callee's
receive instruction (MOVSD vs MOVQ), scoped per-function — covered by probe
946.
This commit is contained in:
@@ -180,6 +180,52 @@ fn cgfnparams(c: *cgen, params: *node) void = {
|
||||
p = p.next;
|
||||
continue;
|
||||
};
|
||||
let sfc: i32 = structfloatclass(c, p.lhs);
|
||||
if (sfc != 0) {
|
||||
// #165: float-bearing struct PARAM receive (param
|
||||
// twin of #163's tuple). Classify each SysV
|
||||
// eightbyte; a lone-f64 eightbyte reads its XMM
|
||||
// (X0..X7), a pure-INT eightbyte its INTEGER arg reg
|
||||
// (DI/SI/..), stored into the param slot at the
|
||||
// 8-byte eightbyte stride. Gated to qualifying
|
||||
// structs by structfloatclass — all-int + f32-packed
|
||||
// fall through to the GP struct arm below (byte-id /
|
||||
// #165b). Reg overflow loud-stops (rule 7).
|
||||
let off: i32 = localadd(c, nm, structparamsize(c, p.lhs), p.lhs);
|
||||
let nb: i32 = sfc & 15;
|
||||
let e: i32 = 0;
|
||||
for (e < nb) {
|
||||
let issse: bool = (sfc & (16 << e)) != 0;
|
||||
if (issse) {
|
||||
if (fidx >= 8) {
|
||||
let msg: str = "float struct param eightbyte overflows SSE arg regs (X0..X7); stitch out of scope, see #165\n";
|
||||
os.write(2, msg.ptr, msg.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
emitline("\tMOVSD\t");
|
||||
emitline(fargregname(fidx));
|
||||
emitline(", ");
|
||||
emitoff((off + e*8): i64);
|
||||
emitline("(BP)\n");
|
||||
fidx += 1;
|
||||
} else {
|
||||
if (idx >= 6) {
|
||||
let msg: str = "float struct param eightbyte overflows integer arg regs (DI/SI/DX/CX/R8/R9); stitch out of scope, see #165\n";
|
||||
os.write(2, msg.ptr, msg.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(argregname(idx));
|
||||
emitline(", ");
|
||||
emitoff((off + e*8): i64);
|
||||
emitline("(BP)\n");
|
||||
idx += 1;
|
||||
};
|
||||
e += 1;
|
||||
};
|
||||
p = p.next;
|
||||
continue;
|
||||
};
|
||||
if (istaggedtype(c, p.lhs)) {
|
||||
let slot: i32 = slotsize(c, p.lhs);
|
||||
let nw: i32 = slot / 8;
|
||||
|
||||
Reference in New Issue
Block a user