Repository navigation
t27b: @bitCast between an integer and a float of one size, @intFromBool, and std.math.nan / isNan / isPositiveInf / isNegativeInf #7791
Description
Part of #7746 (t27b passes specs/numeric/gf16.t27), which is part of #6063 (t27b coverage), item C10 of #6488. This is the first PR of #7746's split.
What gf16.t27 needs
t27b refuses these in gf16.t27 today (t27b test --blockers, master 2781ae3):
ExprCall(@bitCast), 22 sites:const bits : u32 = @bitCast(value);reads an f32's bits, andconst out : f32 = @bitCast(out_bits);builds one. All 22 are f32 <-> u32.ExprCall(std.*), 7 sites:std.math.nan(f32)(3),std.math.isNan(2),std.math.isPositiveInf,std.math.isNegativeInf. (std.math.powis a later PR of t27b: specs/numeric/gf16.t27 after the type mismatch family -- @bitCast, f32 rounding and libm, std.math, @setEvalBranchQuota #7746.)ExprCall(@intFromBool), 3 sites:@as(u8, @intFromBool(is_fin)).
What the reference does
Measured on the t27c lab (zig 0.16.0, the x86_64 Debug backend t27c test-report uses):
@bitCastkeeps the bits exactly. A signalling NaN 0x7F800001 survives a bitcast, a call and a return. A u32 0xFFFFFFFF is the i32 -1.- Zig refuses a literal operand ("cannot @bitcast from 'comptime_int'"), two sizes ("@bitcast size mismatch"), and a call with no result type. It accepts a bool to a u1.
std.math.nan(f32)is 0x7FC00000, andstd.math.nan(f64)is 0x7FF8000000000000.-std.math.nan(f32)is 0xFFC00000.isNan(x)isx != x.isPositiveInf(x)isx == inf, andisNegativeInf(x)isx == -inf(std/math/isnan.zig, isinf.zig).@intFromBool(b)is a u1, 0 or 1.
Plan
@bitCastand@intFromBool. A new plan,specs/tri/t27b/bit_cast_plan.t27, throught27c gen-rust:- an int <-> float of one size goes through a frame slot: a store of the operand, then a load of the result type, with no new IR node;
- two integers of one size are a Cast with no trap site;
- a bool to a u1, and
@intFromBool, is a Widen; - a constant folds;
- the rest is refused by name, as Zig refuses it.
- The
std.mathcalls. They joinspecs/tri/t27b/libm_plan.t27. Their routines are t27 inspecs/tri/t27b/libm.t27, as@expand@logare.nannames its type, so its routine takes no argument. - A conformance spec in gf16's own shapes:
specs/tri/t27b/conformance/bit_cast.t27.
Acceptance criteria
t27b test --blockers specs/numeric/gf16.t27names noExprCall(@bitCast), noExprCall(@intFromBool)and no call tostd.math.nan,isNan,isPositiveInforisNegativeInf.- The conformance spec passes under
t27c test-reportwith 0 vacuous tests, and the same tests pass under t27b. - The lab corpus receipt compare gives IMPROVED_ONLY, EQUIVALENT or NEUTRAL.
User Scenarios
- Given a gf16.t27 spec using
@bitCastto convert between f32 and u32, when t27b compiles it, then the expression is accepted and the bit pattern is preserved exactly. - Given a gf16.t27 spec calling
std.math.nan(f32),std.math.isNan(x),std.math.isPositiveInf(x), orstd.math.isNegativeInf(x), when t27b compiles it, then the calls are resolved to t27 routines that match Zig's semantics. - Given a gf16.t27 spec using
@intFromBool(b)where b is a bool, when t27b compiles it, then the result is a u1 value 0 or 1 matching Zig's behavior.
Requirements
FR-001: The planner in specs/tri/t27b/bit_cast_plan.t27 MUST handle @bitCast between an integer and a float of identical size by emitting a store of the operand and a load of the result type through a frame slot with no new IR node.
FR-002: The planner in specs/tri/t27b/bit_cast_plan.t27 MUST handle @bitCast between two integers of identical size as a Cast with no trap site.
FR-003: The planner in specs/tri/t27b/bit_cast_plan.t27 MUST handle @bitCast from bool to u1 and @intFromBool as a Widen.
FR-004: The planner in specs/tri/t27b/bit_cast_plan.t27 MUST fold constant @bitCast and @intFromBool expressions at compile time.
FR-005: The planner in specs/tri/t27b/bit_cast_plan.t27 MUST refuse all other @bitCast cases by name, matching Zig's refusal semantics.
FR-006: The specs/tri/t27b/libm_plan.t27 planner MUST resolve std.math.nan, std.math.isNan, std.math.isPositiveInf, and std.math.isNegativeInf calls to t27 routines in specs/tri/t27b/libm.t27.
FR-007: The std.math.nan routine in specs/tri/t27b/libm.t27 MUST take no argument and return the canonical quiet NaN bit pattern for the target float type (0x7FC00000 for f32, 0x7FF8000000000000 for f64).
FR-008: The std.math.isNan routine in specs/tri/t27b/libm.t27 MUST implement the semantics x != x.
FR-009: The std.math.isPositiveInf routine in specs/tri/t27b/libm.t27 MUST implement the semantics x == inf.
FR-010: The std.math.isNegativeInf routine in specs/tri/t27b/libm.t27 MUST implement the semantics x == -inf.
FR-011: The conformance spec specs/tri/t27b/conformance/bit_cast.t27 MUST exercise all accepted @bitCast forms, @intFromBool, and the four std.math functions with values matching Zig's reference behavior.
Success Criteria
t27b test --blockers specs/numeric/gf16.t27exits 0 and names noExprCall(@bitCast), noExprCall(@intFromBool), and no call tostd.math.nan,isNan,isPositiveInf, orisNegativeInf.t27c test-report specs/tri/t27b/conformance/bit_cast.t27exits 0 with 0 vacuous tests.t27b test specs/tri/t27b/conformance/bit_cast.t27exits 0 with the same test count as t27c.- Lab corpus receipt compare yields IMPROVED_ONLY, EQUIVALENT, or NEUTRAL.
Boundary
- specs/numeric/gf16.t27
- specs/tri/t27b/bit_cast_plan.t27
- specs/tri/t27b/libm_plan.t27
- specs/tri/t27b/libm.t27
- specs/tri/t27b/conformance/bit_cast.t27
Activity
Merge master into t27b/gf16-bitcast (Closes #7791)
Merge master into t27b/gf16-bitcast (Closes #7791)
Merge master into t27b/gf16-bitcast (Closes #7791)
t27b: mount bit_cast_plan.rs on two lines, as the other plans are (Cl…
Merge master into t27b/gf16-bitcast (Closes #7791)
Merge master into t27b/gf16-bitcast (Closes #7791)
Merge master into t27b/gf16-bitcast (Closes #7791)
t27b: @bitcast between an integer and a float of one size, @intFromBo…