| author | |
| committer | |
| log | 17046674a745faaa34cf2646b9cf43455b12aba9 |
| tree | 0826d357cbfedea2e0b5309b1316b2ea731d1dbf |
| parent | 70894d5c2f6032b0d0be1fa00a30554b7e6db2d6 |
- neg can only overflow, if a == MIN
- case `-0` is properly handled by hardware, so overflow check by comparing
`a == MIN` is sufficient
- tests: MIN, MIN+1, MIN+4, -42, -7, -1, 0, 1, 7..
See #12906 files changed, 128 insertions(+), 0 deletions(-)
CMakeLists.txt+1| ... | @@ -500,6 +500,7 @@ set(ZIG_STAGE2_SOURCES | ... | @@ -500,6 +500,7 @@ set(ZIG_STAGE2_SOURCES |
| 500 | "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/multi3.zig" | 500 | "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/multi3.zig" |
| 501 | "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/negXf2.zig" | 501 | "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/negXf2.zig" |
| 502 | "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/negXi2.zig" | 502 | "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/negXi2.zig" |
| 503 | "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/negv.zig" | ||
| 503 | "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/os_version_check.zig" | 504 | "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/os_version_check.zig" |
| 504 | "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/parity.zig" | 505 | "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/parity.zig" |
| 505 | "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/popcount.zig" | 506 | "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/popcount.zig" |
lib/std/special/compiler_rt.zig+6| ... | @@ -423,6 +423,12 @@ comptime { | ... | @@ -423,6 +423,12 @@ comptime { |
| 423 | @export(__absvdi2, .{ .name = "__absvdi2", .linkage = linkage }); | 423 | @export(__absvdi2, .{ .name = "__absvdi2", .linkage = linkage }); |
| 424 | const __absvti2 = @import("compiler_rt/absv.zig").__absvti2; | 424 | const __absvti2 = @import("compiler_rt/absv.zig").__absvti2; |
| 425 | @export(__absvti2, .{ .name = "__absvti2", .linkage = linkage }); | 425 | @export(__absvti2, .{ .name = "__absvti2", .linkage = linkage }); |
| 426 | const __negvsi2 = @import("compiler_rt/negv.zig").__negvsi2; | ||
| 427 | @export(__negvsi2, .{ .name = "__negvsi2", .linkage = linkage }); | ||
| 428 | const __negvdi2 = @import("compiler_rt/negv.zig").__negvdi2; | ||
| 429 | @export(__negvdi2, .{ .name = "__negvdi2", .linkage = linkage }); | ||
| 430 | const __negvti2 = @import("compiler_rt/negv.zig").__negvti2; | ||
| 431 | @export(__negvti2, .{ .name = "__negvti2", .linkage = linkage }); | ||
| 426 | 432 | ||
| 427 | // missing: Integral arithmetic which returns if overflow | 433 | // missing: Integral arithmetic which returns if overflow |
| 428 | 434 |
lib/std/special/compiler_rt/negv.zig created+31| ... | @@ -0,0 +1,31 @@ | ||
| 1 | // negv - negate oVerflow | ||
| 2 | // * @panic, if result can not be represented | ||
| 3 | // - negvXi4_generic for unoptimized version | ||
| 4 | |||
| 5 | // assume -0 == 0 is gracefully handled by the hardware | ||
| 6 | fn negvXi_generic(comptime ST: type) fn (a: ST) callconv(.C) ST { | ||
| 7 | return struct { | ||
| 8 | fn f(a: ST) callconv(.C) ST { | ||
| 9 | const UT = switch (ST) { | ||
| 10 | i32 => u32, | ||
| 11 | i64 => u64, | ||
| 12 | i128 => u128, | ||
| 13 | else => unreachable, | ||
| 14 | }; | ||
| 15 | const N: UT = @bitSizeOf(ST); | ||
| 16 | const min: ST = @bitCast(ST, (@as(UT, 1) << (N - 1))); | ||
| 17 | if (a == min) | ||
| 18 | @panic("compiler_rt negv: overflow"); | ||
| 19 | return -a; | ||
| 20 | } | ||
| 21 | }.f; | ||
| 22 | } | ||
| 23 | pub const __negvsi2 = negvXi_generic(i32); | ||
| 24 | pub const __negvdi2 = negvXi_generic(i64); | ||
| 25 | pub const __negvti2 = negvXi_generic(i128); | ||
| 26 | |||
| 27 | test { | ||
| 28 | _ = @import("negvsi2_test.zig"); | ||
| 29 | _ = @import("negvdi2_test.zig"); | ||
| 30 | _ = @import("negvti2_test.zig"); | ||
| 31 | } | ||
lib/std/special/compiler_rt/negvdi2_test.zig created+30| ... | @@ -0,0 +1,30 @@ | ||
| 1 | const negv = @import("negv.zig"); | ||
| 2 | const testing = @import("std").testing; | ||
| 3 | |||
| 4 | fn test__negvdi2(a: i64, expected: i64) !void { | ||
| 5 | var result = negv.__negvdi2(a); | ||
| 6 | try testing.expectEqual(expected, result); | ||
| 7 | } | ||
| 8 | |||
| 9 | test "negvdi2" { | ||
| 10 | // -2^63 <= i64 <= 2^63-1 | ||
| 11 | // 2^63 = 9223372036854775808 | ||
| 12 | // 2^63-1 = 9223372036854775807 | ||
| 13 | // TODO write panic handler for testing panics | ||
| 14 | //try test__negvdi2(-9223372036854775808, -5); // tested with return -5; and panic | ||
| 15 | try test__negvdi2(-9223372036854775807, 9223372036854775807); | ||
| 16 | try test__negvdi2(-9223372036854775806, 9223372036854775806); | ||
| 17 | try test__negvdi2(-9223372036854775805, 9223372036854775805); | ||
| 18 | try test__negvdi2(-9223372036854775804, 9223372036854775804); | ||
| 19 | try test__negvdi2(-42, 42); | ||
| 20 | try test__negvdi2(-7, 7); | ||
| 21 | try test__negvdi2(-1, 1); | ||
| 22 | try test__negvdi2(0, 0); | ||
| 23 | try test__negvdi2(1, -1); | ||
| 24 | try test__negvdi2(7, -7); | ||
| 25 | try test__negvdi2(42, -42); | ||
| 26 | try test__negvdi2(9223372036854775804, -9223372036854775804); | ||
| 27 | try test__negvdi2(9223372036854775805, -9223372036854775805); | ||
| 28 | try test__negvdi2(9223372036854775806, -9223372036854775806); | ||
| 29 | try test__negvdi2(9223372036854775807, -9223372036854775807); | ||
| 30 | } | ||
lib/std/special/compiler_rt/negvsi2_test.zig created+30| ... | @@ -0,0 +1,30 @@ | ||
| 1 | const negv = @import("negv.zig"); | ||
| 2 | const testing = @import("std").testing; | ||
| 3 | |||
| 4 | fn test__negvsi2(a: i32, expected: i32) !void { | ||
| 5 | var result = negv.__negvsi2(a); | ||
| 6 | try testing.expectEqual(expected, result); | ||
| 7 | } | ||
| 8 | |||
| 9 | test "negvsi2" { | ||
| 10 | // -2^31 <= i32 <= 2^31-1 | ||
| 11 | // 2^31 = 2147483648 | ||
| 12 | // 2^31-1 = 2147483647 | ||
| 13 | // TODO write panic handler for testing panics | ||
| 14 | //try test__negvsi2(-2147483648, -5); // tested with return -5; and panic | ||
| 15 | try test__negvsi2(-2147483647, 2147483647); | ||
| 16 | try test__negvsi2(-2147483646, 2147483646); | ||
| 17 | try test__negvsi2(-2147483645, 2147483645); | ||
| 18 | try test__negvsi2(-2147483644, 2147483644); | ||
| 19 | try test__negvsi2(-42, 42); | ||
| 20 | try test__negvsi2(-7, 7); | ||
| 21 | try test__negvsi2(-1, 1); | ||
| 22 | try test__negvsi2(0, 0); | ||
| 23 | try test__negvsi2(1, -1); | ||
| 24 | try test__negvsi2(7, -7); | ||
| 25 | try test__negvsi2(42, -42); | ||
| 26 | try test__negvsi2(2147483644, -2147483644); | ||
| 27 | try test__negvsi2(2147483645, -2147483645); | ||
| 28 | try test__negvsi2(2147483646, -2147483646); | ||
| 29 | try test__negvsi2(2147483647, -2147483647); | ||
| 30 | } | ||
lib/std/special/compiler_rt/negvti2_test.zig created+30| ... | @@ -0,0 +1,30 @@ | ||
| 1 | const negv = @import("negv.zig"); | ||
| 2 | const testing = @import("std").testing; | ||
| 3 | |||
| 4 | fn test__negvti2(a: i128, expected: i128) !void { | ||
| 5 | var result = negv.__negvti2(a); | ||
| 6 | try testing.expectEqual(expected, result); | ||
| 7 | } | ||
| 8 | |||
| 9 | test "negvti2" { | ||
| 10 | // -2^127 <= i128 <= 2^127-1 | ||
| 11 | // 2^127 = 170141183460469231731687303715884105728 | ||
| 12 | // 2^127+1 = 170141183460469231731687303715884105727 | ||
| 13 | // TODO write panic handler for testing panics | ||
| 14 | //try test__negvti2(-170141183460469231731687303715884105728, -5); // tested with return -5; and panic | ||
| 15 | try test__negvti2(-170141183460469231731687303715884105727, 170141183460469231731687303715884105727); | ||
| 16 | try test__negvti2(-170141183460469231731687303715884105726, 170141183460469231731687303715884105726); | ||
| 17 | try test__negvti2(-170141183460469231731687303715884105725, 170141183460469231731687303715884105725); | ||
| 18 | try test__negvti2(-170141183460469231731687303715884105724, 170141183460469231731687303715884105724); | ||
| 19 | try test__negvti2(-42, 42); | ||
| 20 | try test__negvti2(-7, 7); | ||
| 21 | try test__negvti2(-1, 1); | ||
| 22 | try test__negvti2(0, 0); | ||
| 23 | try test__negvti2(1, -1); | ||
| 24 | try test__negvti2(7, -7); | ||
| 25 | try test__negvti2(42, -42); | ||
| 26 | try test__negvti2(170141183460469231731687303715884105724, -170141183460469231731687303715884105724); | ||
| 27 | try test__negvti2(170141183460469231731687303715884105725, -170141183460469231731687303715884105725); | ||
| 28 | try test__negvti2(170141183460469231731687303715884105726, -170141183460469231731687303715884105726); | ||
| 29 | try test__negvti2(170141183460469231731687303715884105727, -170141183460469231731687303715884105727); | ||
| 30 | } | ||