| author | |
| committer | |
| log | 86f4dfe5a8a7632b26de5f1d109fba369095b0f7 |
| tree | 8daa8addb868fe87fd3f69ed5408c098317a06ca |
| parent | dc18b8174ae6dacb3bc32fc842363159916bd657 |
@bitCast from integer NaN representation to float NaN resulted in
changed bits in float. This only happened with signaled NaN.
- added test for signaled NaN
- added tests for quiet NaN (for completeness)
closes #141983 files changed, 32 insertions(+), 4 deletions(-)
src/codegen/llvm.zig+13-4| ... | ... | @@ -3275,15 +3275,24 @@ pub const DeclGen = struct { |
| 3275 | 3275 | .Float => { |
| 3276 | 3276 | const llvm_ty = try dg.lowerType(tv.ty); |
| 3277 | 3277 | switch (tv.ty.floatBits(target)) { |
| 3278 | 16 => if (intrinsicsAllowed(tv.ty, target)) { | |
| 3279 | return llvm_ty.constReal(tv.val.toFloat(f16)); | |
| 3280 | } else { | |
| 3278 | 16 => { | |
| 3281 | 3279 | const repr = @bitCast(u16, tv.val.toFloat(f16)); |
| 3282 | 3280 | const llvm_i16 = dg.context.intType(16); |
| 3283 | 3281 | const int = llvm_i16.constInt(repr, .False); |
| 3284 | 3282 | return int.constBitCast(llvm_ty); |
| 3285 | 3283 | }, |
| 3286 | 32, 64 => return llvm_ty.constReal(tv.val.toFloat(f64)), | |
| 3284 | 32 => { | |
| 3285 | const repr = @bitCast(u32, tv.val.toFloat(f32)); | |
| 3286 | const llvm_i32 = dg.context.intType(32); | |
| 3287 | const int = llvm_i32.constInt(repr, .False); | |
| 3288 | return int.constBitCast(llvm_ty); | |
| 3289 | }, | |
| 3290 | 64 => { | |
| 3291 | const repr = @bitCast(u64, tv.val.toFloat(f64)); | |
| 3292 | const llvm_i64 = dg.context.intType(64); | |
| 3293 | const int = llvm_i64.constInt(repr, .False); | |
| 3294 | return int.constBitCast(llvm_ty); | |
| 3295 | }, | |
| 3287 | 3296 | 80 => { |
| 3288 | 3297 | const float = tv.val.toFloat(f80); |
| 3289 | 3298 | const repr = std.math.break_f80(float); |
test/behavior.zig+1| ... | ... | @@ -218,6 +218,7 @@ test { |
| 218 | 218 | { |
| 219 | 219 | _ = @import("behavior/bugs/13063.zig"); |
| 220 | 220 | _ = @import("behavior/bugs/11227.zig"); |
| 221 | _ = @import("behavior/bugs/14198.zig"); | |
| 221 | 222 | _ = @import("behavior/export.zig"); |
| 222 | 223 | } |
| 223 | 224 |
test/behavior/bugs/14198.zig created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | const std = @import("std"); | |
| 2 | const math = std.math; | |
| 3 | const mem = std.mem; | |
| 4 | const testing = std.testing; | |
| 5 | ||
| 6 | test "nan memory equality" { | |
| 7 | // signaled | |
| 8 | try testing.expect(mem.eql(u8, mem.asBytes(&math.nan_u16), mem.asBytes(&math.nan_f16))); | |
| 9 | try testing.expect(mem.eql(u8, mem.asBytes(&math.nan_u32), mem.asBytes(&math.nan_f32))); | |
| 10 | try testing.expect(mem.eql(u8, mem.asBytes(&math.nan_u64), mem.asBytes(&math.nan_f64))); | |
| 11 | try testing.expect(mem.eql(u8, mem.asBytes(&math.nan_u128), mem.asBytes(&math.nan_f128))); | |
| 12 | ||
| 13 | // quiet | |
| 14 | try testing.expect(mem.eql(u8, mem.asBytes(&math.qnan_u16), mem.asBytes(&math.qnan_f16))); | |
| 15 | try testing.expect(mem.eql(u8, mem.asBytes(&math.qnan_u32), mem.asBytes(&math.qnan_f32))); | |
| 16 | try testing.expect(mem.eql(u8, mem.asBytes(&math.qnan_u64), mem.asBytes(&math.qnan_f64))); | |
| 17 | try testing.expect(mem.eql(u8, mem.asBytes(&math.qnan_u128), mem.asBytes(&math.qnan_f128))); | |
| 18 | } |