| author | |
| committer | |
| log | 89c98e200166aa3e4f5b41859f450d1307216191 |
| tree | 7f251a8a0d46414bc63d011bbf805180f4fdba53 |
| parent | b4ffb402c082605c4b324e88120306fc8fb3cf32 |
| signature |
This is a follow-up to PR #30053 / commit 484cc15366.
The code previously did not handle `c_longdouble`, whose size depends on
the target. A `floatSignificandBits` helper function and a smoke test
were added.
Also added the missing max int value to the exhaustive `f16` test cases.5 files changed, 68 insertions(+), 61 deletions(-)
src/Sema.zig+1-9| ... | ... | @@ -27774,15 +27774,7 @@ fn coerceExtra( |
| 27774 | 27774 | } |
| 27775 | 27775 | const int_info = inst_ty.intInfo(zcu); |
| 27776 | 27776 | const int_precision = int_info.bits - @intFromBool(int_info.signedness == .signed); |
| 27777 | const float_precision: u8 = switch (dest_ty.toIntern()) { | |
| 27778 | .f16_type => 11, | |
| 27779 | .f32_type => 24, | |
| 27780 | .f64_type => 53, | |
| 27781 | .f80_type => 64, | |
| 27782 | .f128_type => 113, | |
| 27783 | else => unreachable, | |
| 27784 | }; | |
| 27785 | if (int_precision <= float_precision) { | |
| 27777 | if (int_precision <= dest_ty.floatSignificandBits(target)) { | |
| 27786 | 27778 | try sema.requireRuntimeBlock(block, inst_src, null); |
| 27787 | 27779 | return block.addTyOp(.float_from_int, dest_ty, inst); |
| 27788 | 27780 | } |
src/Type.zig+12| ... | ... | @@ -1936,6 +1936,18 @@ pub fn floatBits(ty: Type, target: *const Target) u16 { |
| 1936 | 1936 | }; |
| 1937 | 1937 | } |
| 1938 | 1938 | |
| 1939 | /// Asserts the type is a fixed-size float or comptime_float. | |
| 1940 | pub fn floatSignificandBits(ty: Type, target: *const Target) u16 { | |
| 1941 | return switch (ty.floatBits(target)) { | |
| 1942 | 16 => 11, | |
| 1943 | 32 => 24, | |
| 1944 | 64 => 53, | |
| 1945 | 80 => 64, | |
| 1946 | 128 => 113, | |
| 1947 | else => unreachable, | |
| 1948 | }; | |
| 1949 | } | |
| 1950 | ||
| 1939 | 1951 | /// Asserts the type is a function or a function pointer. |
| 1940 | 1952 | pub fn fnReturnType(ty: Type, zcu: *const Zcu) Type { |
| 1941 | 1953 | return Type.fromInterned(zcu.intern_pool.funcTypeReturnType(ty.toIntern())); |
test/behavior/cast.zig+3| ... | ... | @@ -175,6 +175,7 @@ test "type coercion from int to float" { |
| 175 | 175 | var int: Int = std.math.minInt(Int); |
| 176 | 176 | while (int < std.math.maxInt(Int)) : (int += 1) |
| 177 | 177 | try value(Float, int); |
| 178 | try value(Float, int); // max | |
| 178 | 179 | } |
| 179 | 180 | |
| 180 | 181 | // Check that the min and max values of the integer type can safely be |
| ... | ... | @@ -202,6 +203,8 @@ test "type coercion from int to float" { |
| 202 | 203 | try check.edgeValues(f128, u113); |
| 203 | 204 | try check.edgeValues(f128, i114); |
| 204 | 205 | |
| 206 | try check.value(c_longdouble, @as(u1, 0)); // Smoke test - size varies by target. | |
| 207 | ||
| 205 | 208 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 206 | 209 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 207 | 210 |
test/cases/compile_errors/coerce_int_to_float.zig deleted-52| ... | ... | @@ -1,52 +0,0 @@ |
| 1 | // Test that integer types above a certain size will not coerce to a float. | |
| 2 | ||
| 3 | fn testCoerce(Float: type, Int: type) void { | |
| 4 | var i: Int = 0; | |
| 5 | _ = &i; | |
| 6 | _ = @as(Float, i); | |
| 7 | } | |
| 8 | ||
| 9 | export fn entry() void { | |
| 10 | testCoerce(f16, u11); // Okay | |
| 11 | testCoerce(f16, u12); // Too big | |
| 12 | ||
| 13 | testCoerce(f16, i12); | |
| 14 | testCoerce(f16, i13); | |
| 15 | ||
| 16 | testCoerce(f32, u24); | |
| 17 | testCoerce(f32, u25); | |
| 18 | ||
| 19 | testCoerce(f32, i25); | |
| 20 | testCoerce(f32, i26); | |
| 21 | ||
| 22 | testCoerce(f64, u53); | |
| 23 | testCoerce(f64, u54); | |
| 24 | ||
| 25 | testCoerce(f64, i54); | |
| 26 | testCoerce(f64, i55); | |
| 27 | ||
| 28 | testCoerce(f80, u64); | |
| 29 | testCoerce(f80, u65); | |
| 30 | ||
| 31 | testCoerce(f80, i65); | |
| 32 | testCoerce(f80, i66); | |
| 33 | ||
| 34 | testCoerce(f128, u113); | |
| 35 | testCoerce(f128, u114); | |
| 36 | ||
| 37 | testCoerce(f128, i114); | |
| 38 | testCoerce(f128, i115); | |
| 39 | } | |
| 40 | ||
| 41 | // error | |
| 42 | // | |
| 43 | // :6:20: error: expected type 'f128', found 'i115' | |
| 44 | // :6:20: error: expected type 'f128', found 'u114' | |
| 45 | // :6:20: error: expected type 'f16', found 'i13' | |
| 46 | // :6:20: error: expected type 'f16', found 'u12' | |
| 47 | // :6:20: error: expected type 'f32', found 'i26' | |
| 48 | // :6:20: error: expected type 'f32', found 'u25' | |
| 49 | // :6:20: error: expected type 'f64', found 'i55' | |
| 50 | // :6:20: error: expected type 'f64', found 'u54' | |
| 51 | // :6:20: error: expected type 'f80', found 'i66' | |
| 52 | // :6:20: error: expected type 'f80', found 'u65' |
test/cases/compile_errors/coerce_large_int_to_float.zig created+52| ... | ... | @@ -0,0 +1,52 @@ |
| 1 | // Test that integer types above a certain size will not coerce to a float. | |
| 2 | ||
| 3 | fn testCoerce(Float: type, Int: type) void { | |
| 4 | var i: Int = 0; | |
| 5 | _ = &i; | |
| 6 | _ = @as(Float, i); | |
| 7 | } | |
| 8 | ||
| 9 | export fn entry() void { | |
| 10 | testCoerce(f16, u11); // Okay | |
| 11 | testCoerce(f16, u12); // Too big | |
| 12 | ||
| 13 | testCoerce(f16, i12); | |
| 14 | testCoerce(f16, i13); | |
| 15 | ||
| 16 | testCoerce(f32, u24); | |
| 17 | testCoerce(f32, u25); | |
| 18 | ||
| 19 | testCoerce(f32, i25); | |
| 20 | testCoerce(f32, i26); | |
| 21 | ||
| 22 | testCoerce(f64, u53); | |
| 23 | testCoerce(f64, u54); | |
| 24 | ||
| 25 | testCoerce(f64, i54); | |
| 26 | testCoerce(f64, i55); | |
| 27 | ||
| 28 | testCoerce(f80, u64); | |
| 29 | testCoerce(f80, u65); | |
| 30 | ||
| 31 | testCoerce(f80, i65); | |
| 32 | testCoerce(f80, i66); | |
| 33 | ||
| 34 | testCoerce(f128, u113); | |
| 35 | testCoerce(f128, u114); | |
| 36 | ||
| 37 | testCoerce(f128, i114); | |
| 38 | testCoerce(f128, i115); | |
| 39 | } | |
| 40 | ||
| 41 | // error | |
| 42 | // | |
| 43 | // :6:20: error: expected type 'f128', found 'i115' | |
| 44 | // :6:20: error: expected type 'f128', found 'u114' | |
| 45 | // :6:20: error: expected type 'f16', found 'i13' | |
| 46 | // :6:20: error: expected type 'f16', found 'u12' | |
| 47 | // :6:20: error: expected type 'f32', found 'i26' | |
| 48 | // :6:20: error: expected type 'f32', found 'u25' | |
| 49 | // :6:20: error: expected type 'f64', found 'i55' | |
| 50 | // :6:20: error: expected type 'f64', found 'u54' | |
| 51 | // :6:20: error: expected type 'f80', found 'i66' | |
| 52 | // :6:20: error: expected type 'f80', found 'u65' |