// f32arg_test — f32 function-argument spill width, migrated from // test/wcc/907_f32arg_run.c (#5-C4, #143). Passing an f32 as a function argument // must spill through the stack at f32 width (MOVSS, 4-byte), not MOVSD (8-byte). // cstage lowered the arg-push/pop with a hardcoded MOVSD; wwstage already split // f32/f64 via exprfloatkind. The bug was a pure cs!=ww byte-id break (the callee // reads its f32 param via MOVSS regardless), so T2 byte-id is the primary net; // the T1 cstage run also asserts the end-to-end XMM round-trip value. package f32arg_test; fn takef32(x: f32) f32 = { return x; }; fn id(x: f32) f32 = { return x; }; fn add3(a: f32, b: f32, c: f32) f32 = { return a + b + c; }; fn mix(a: f32, b: f64, c: f32) f64 = { return a: f64 + b + c: f64; }; fn ten(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32, g: f32, h: f32, i: f32, j: f32) f32 = { return a + b + c + d + e + f + g + h + i + j; }; @test fn single_var() void = { let a: f32 = 2.5f32; let r: f32 = takef32(a); assert(r: i32 == 2); }; @test fn literal_arg() void = { let r: f32 = id(3.0f32); assert(r: i32 == 3); }; @test fn multi_f32() void = { let x: f32 = 1.5f32; let y: f32 = 2.5f32; let z: f32 = 4.0f32; let r: f32 = add3(x, y, z); assert(r: i32 == 8); }; // f32 + f64 MIX: the f64 arg stays MOVSD, the f32 args MOVSS, per-arg agree. @test fn mixed_f32_f64() void = { let p: f32 = 1.5f32; let q: f64 = 10.0; let s: f32 = 0.5f32; let r: f64 = mix(p, q, s); assert(r: i32 == 12); }; // STACK-passed f32: 8 ride X0..X7, args 9+10 stay on the stack (fpidx >= 8). @test fn stack_passed() void = { let v: f32 = 1.0f32; let r: f32 = ten(v, v, v, v, v, v, v, v, v, v); assert(r: i32 == 10); };