Files
ww/test/lang/f64cgen_test.ww
Hojun-Cho 60dec4a6bf test: migrate Fam11 float value tests to @test, keep ABI-conformance pins (#5-C4)
fold-2 chunk C4 (drew's Fam8-13 plan): 13 float value-row C drivers re-homed.
11 migrate to test/lang/*_test.ww @test row-tables (exact IEEE-bit asserts);
1 float-overflow reject row -> a runww //ww:error carrier. 956_tuprecv_f64
slims to a w6c_ww asserttyped pin (20 value rows -> @test; the stamp dimension
can't be a value/byte-id @test) -- mutation-proven non-vacuous (break #121
stamp -> RED 6/6 -> restore -> GREEN) + an in-test vacuity self-check.
946_structparam/structret stay whole: their SSE register-class .s-grep (SysV
ABI conformance, #165/#171a) is the genuine defect-guard, not @test-expressible.
Float was the predicted SSE-cursor byte-id hotspot -- zero fresh cs!=ww
surfaced; 951_f64cgen (cstage-only before) byte-ids clean. LANGBYTEID floor
82->93; test count 384->374 (10 deleted drivers; 956 + the 2 946 kept).
2026-06-24 03:25:47 +09:00

144 lines
3.8 KiB
Plaintext

// f64cgen_test — f64/f32 deref-load + NaN relop, migrated from
// test/wcc/951_f64cgen_run.c (#5-C4, #96 + #97). Two GATE-BLIND f64 codegen
// bugs (both stages byte-identical before+after the fix, so byte-id never
// catches a reintroduction — the T1 cstage run is the live net):
// #96 — f64/f32 deref-load must MOVSD/MOVSS into X0, not MOVQ into AX.
// #97 — f64/f32 compare must consult PF (parity) for IEEE-754 NaN: with a NaN
// operand `!=` is true, the other five relops false.
// The C driver was cstage-ONLY (no byte-id leg — ww_ww run was broken #95);
// this migration ADDS the T2 cs==ww byte-id assertion for the first time.
package f64cgen_test;
fn deref(p: *f64) f64 = { return *p; };
fn zero() f64 = { return 0.0; };
fn one() f64 = { return 1.0; };
fn z() f64 = { return 0.0; };
fn z32() f32 = { return 0.0; };
fn one32() f32 = { return 1.0; };
fn tobits(f: f64) u64 = { return *((&f): *u64); };
fn frombits(b: u64) f64 = { return *((&b): *f64); };
// #96 deref-load: dirty X0 with junk before the call so X0-retention can't mask
// a broken return load; `*px` must reach X0 for the MULSD.
@test fn deref_basic() void = {
let x: f64 = 7.5;
let y: f64 = 1.25;
let px: *f64 = &x;
let junk: f64 = y * 2.0;
assert(junk == 2.5);
let r: f64 = deref(px);
assert(r == 7.5);
let q: f64 = *px * 2.0;
assert(q == 15.0);
};
// #96 value propagation through an f64-returning fn then truncated to i32.
@test fn deref_valueprop() void = {
let x: f64 = 42.0;
let r: f64 = deref(&x);
assert(r: i32 == 42);
};
@test fn arith_deref() void = {
let x: f64 = 7.5;
let p: *f64 = &x;
let q: f64 = *p * 2.0;
assert(q: i32 == 15);
};
// #96 f64frombits round-trip: reinterpret a u64 bit pattern as f64.
@test fn frombits_roundtrip() void = {
let bits: u64 = 0x4045000000000000u64;
let f: f64 = *((&bits): *f64);
assert(f: i32 == 42);
};
// #96 copysign(5.0, -1.0) == -5.0 built from tobits/frombits reinterprets.
@test fn copysign() void = {
let x: f64 = 5.0;
let y: f64 = -1.0;
let mag: u64 = tobits(x) & 0x7fffffffffffffffu64;
let sgn: u64 = tobits(y) & 0x8000000000000000u64;
let r: f64 = frombits(mag | sgn);
assert(!(r > 0.0));
assert(r < -4.5);
assert(r > -5.5);
};
// #97 full NaN relop sweep (f64, UCOMISD). Runtime NaN via 0.0/0.0 through
// opaque fns so the checker can't const-fold it.
@test fn nan_sweep() void = {
let z: f64 = zero();
let nan: f64 = z / z;
let x: f64 = one();
assert(nan != nan);
assert(!(nan == nan));
assert(!(nan == x));
assert(!(nan < x));
assert(!(nan <= x));
assert(!(nan > x));
assert(!(nan >= x));
assert(nan != x);
assert(!(x != x));
assert(x == x);
assert(x < 2.0);
assert(x <= 1.0);
assert(2.0 > x);
assert(1.0 >= x);
assert(!(x > 2.0));
};
// #97 value propagation: of the 6 relops against NaN, exactly one (`!=`) is true.
@test fn nan_count() void = {
let nan: f64 = z() / z();
let x: f64 = 1.0;
let n: i32 = 0;
if (nan == x) { n += 1; };
if (nan != x) { n += 1; };
if (nan < x) { n += 1; };
if (nan <= x) { n += 1; };
if (nan > x) { n += 1; };
if (nan >= x) { n += 1; };
assert(n == 1);
};
// #97 f32 path (UCOMISS): NaN unordered rules, plus ordered f64 relops correct.
@test fn f32_nan_ordered() void = {
let z: f32 = z32();
let nan: f32 = z / z;
let x: f32 = one32();
assert(nan != nan);
assert(!(nan == nan));
assert(!(nan < x));
assert(!(nan >= x));
let a: f64 = 2.0;
let b: f64 = 3.0;
assert(a < b);
assert(!(a > b));
assert(a <= a);
assert(b >= a);
assert(a == 2.0);
assert(!(a != 2.0));
assert(!(b < a));
assert(b > a);
};
// #97 `>`/`>=` left-bare arm with runtime-built operands (JA/JAE template
// unchanged by the fix — guards the untouched arm).
@test fn gt_only() void = {
let a: f64 = z() + 2.0;
let b: f64 = z() + 3.0;
assert(b > a);
assert(!(a > b));
assert(b >= a);
assert(a >= a);
};