// f9_float_test — F9 argument widen/drain ABI (float), migrated from // test/wcc/949_f9_float_run.c (#5-C4, #30/#48/#49). The cgcall push/drain of a // CONCRETE arg widened into a tagged-union param slot, where a float is involved: // #30 — a float arg AFTER a widened (i64|void) arg under-drained by one GP word // (the f64 read the box's leftover payload). // #48 — the widened arg IS an f64 source: the float arm ate the TAG word into // X0 and the payload landed in DI as the tag. // #49 (#263) — a runtime f64 widened into (f64|void) whose arm reads the // payload: the widen-PUSH did PUSHQ AX while the f64 sat in X0. // All align wwstage UP to cstage's precomputed widen handling; T1 run + T2 // byte-id. Register-cursor invariant (rob): the values survive only if tag/ // payload land in the right GP regs AND the float in the right XMM. package f9_float_test; fn f(a: (i64 | void), b: f64) f64 = { return b; }; fn g(v: (i64 | f64)) i32 = { match (v) { case let n: i64 => return 1; case let d: f64 => return 2; }; return 9; }; type fv = (f64 | void); fn mk(x: f64) f64 = { return x + 1.5; }; fn take(v: fv) i32 = { match (v) { case let d: f64 => { if (d == 2.5) { return 0; }; return 1; }; case void => { return 2; }; }; return 3; }; @test fn widen_then_float() void = { let r: f64 = f(7, 1.5); assert(r == 1.5); }; @test fn float_source_widen() void = { let d: f64 = 3.5; assert(g(d) == 2); }; @test fn runtime_float_widen_payload() void = { let d: f64 = mk(1.0); assert(take(d) == 0); };