mirror of
https://github.com/ziglang/zig.git
synced 2025-01-19 16:31:52 +00:00
compiler_rt: add __negvsi2, __negvdi2, __negvti2
- 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 #1290
This commit is contained in:
parent
70894d5c2f
commit
17046674a7
@ -500,6 +500,7 @@ set(ZIG_STAGE2_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/multi3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/negXf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/negXi2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/negv.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/os_version_check.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/parity.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/popcount.zig"
|
||||
|
@ -423,6 +423,12 @@ comptime {
|
||||
@export(__absvdi2, .{ .name = "__absvdi2", .linkage = linkage });
|
||||
const __absvti2 = @import("compiler_rt/absv.zig").__absvti2;
|
||||
@export(__absvti2, .{ .name = "__absvti2", .linkage = linkage });
|
||||
const __negvsi2 = @import("compiler_rt/negv.zig").__negvsi2;
|
||||
@export(__negvsi2, .{ .name = "__negvsi2", .linkage = linkage });
|
||||
const __negvdi2 = @import("compiler_rt/negv.zig").__negvdi2;
|
||||
@export(__negvdi2, .{ .name = "__negvdi2", .linkage = linkage });
|
||||
const __negvti2 = @import("compiler_rt/negv.zig").__negvti2;
|
||||
@export(__negvti2, .{ .name = "__negvti2", .linkage = linkage });
|
||||
|
||||
// missing: Integral arithmetic which returns if overflow
|
||||
|
||||
|
31
lib/std/special/compiler_rt/negv.zig
Normal file
31
lib/std/special/compiler_rt/negv.zig
Normal file
@ -0,0 +1,31 @@
|
||||
// negv - negate oVerflow
|
||||
// * @panic, if result can not be represented
|
||||
// - negvXi4_generic for unoptimized version
|
||||
|
||||
// assume -0 == 0 is gracefully handled by the hardware
|
||||
fn negvXi_generic(comptime ST: type) fn (a: ST) callconv(.C) ST {
|
||||
return struct {
|
||||
fn f(a: ST) callconv(.C) ST {
|
||||
const UT = switch (ST) {
|
||||
i32 => u32,
|
||||
i64 => u64,
|
||||
i128 => u128,
|
||||
else => unreachable,
|
||||
};
|
||||
const N: UT = @bitSizeOf(ST);
|
||||
const min: ST = @bitCast(ST, (@as(UT, 1) << (N - 1)));
|
||||
if (a == min)
|
||||
@panic("compiler_rt negv: overflow");
|
||||
return -a;
|
||||
}
|
||||
}.f;
|
||||
}
|
||||
pub const __negvsi2 = negvXi_generic(i32);
|
||||
pub const __negvdi2 = negvXi_generic(i64);
|
||||
pub const __negvti2 = negvXi_generic(i128);
|
||||
|
||||
test {
|
||||
_ = @import("negvsi2_test.zig");
|
||||
_ = @import("negvdi2_test.zig");
|
||||
_ = @import("negvti2_test.zig");
|
||||
}
|
30
lib/std/special/compiler_rt/negvdi2_test.zig
Normal file
30
lib/std/special/compiler_rt/negvdi2_test.zig
Normal file
@ -0,0 +1,30 @@
|
||||
const negv = @import("negv.zig");
|
||||
const testing = @import("std").testing;
|
||||
|
||||
fn test__negvdi2(a: i64, expected: i64) !void {
|
||||
var result = negv.__negvdi2(a);
|
||||
try testing.expectEqual(expected, result);
|
||||
}
|
||||
|
||||
test "negvdi2" {
|
||||
// -2^63 <= i64 <= 2^63-1
|
||||
// 2^63 = 9223372036854775808
|
||||
// 2^63-1 = 9223372036854775807
|
||||
// TODO write panic handler for testing panics
|
||||
//try test__negvdi2(-9223372036854775808, -5); // tested with return -5; and panic
|
||||
try test__negvdi2(-9223372036854775807, 9223372036854775807);
|
||||
try test__negvdi2(-9223372036854775806, 9223372036854775806);
|
||||
try test__negvdi2(-9223372036854775805, 9223372036854775805);
|
||||
try test__negvdi2(-9223372036854775804, 9223372036854775804);
|
||||
try test__negvdi2(-42, 42);
|
||||
try test__negvdi2(-7, 7);
|
||||
try test__negvdi2(-1, 1);
|
||||
try test__negvdi2(0, 0);
|
||||
try test__negvdi2(1, -1);
|
||||
try test__negvdi2(7, -7);
|
||||
try test__negvdi2(42, -42);
|
||||
try test__negvdi2(9223372036854775804, -9223372036854775804);
|
||||
try test__negvdi2(9223372036854775805, -9223372036854775805);
|
||||
try test__negvdi2(9223372036854775806, -9223372036854775806);
|
||||
try test__negvdi2(9223372036854775807, -9223372036854775807);
|
||||
}
|
30
lib/std/special/compiler_rt/negvsi2_test.zig
Normal file
30
lib/std/special/compiler_rt/negvsi2_test.zig
Normal file
@ -0,0 +1,30 @@
|
||||
const negv = @import("negv.zig");
|
||||
const testing = @import("std").testing;
|
||||
|
||||
fn test__negvsi2(a: i32, expected: i32) !void {
|
||||
var result = negv.__negvsi2(a);
|
||||
try testing.expectEqual(expected, result);
|
||||
}
|
||||
|
||||
test "negvsi2" {
|
||||
// -2^31 <= i32 <= 2^31-1
|
||||
// 2^31 = 2147483648
|
||||
// 2^31-1 = 2147483647
|
||||
// TODO write panic handler for testing panics
|
||||
//try test__negvsi2(-2147483648, -5); // tested with return -5; and panic
|
||||
try test__negvsi2(-2147483647, 2147483647);
|
||||
try test__negvsi2(-2147483646, 2147483646);
|
||||
try test__negvsi2(-2147483645, 2147483645);
|
||||
try test__negvsi2(-2147483644, 2147483644);
|
||||
try test__negvsi2(-42, 42);
|
||||
try test__negvsi2(-7, 7);
|
||||
try test__negvsi2(-1, 1);
|
||||
try test__negvsi2(0, 0);
|
||||
try test__negvsi2(1, -1);
|
||||
try test__negvsi2(7, -7);
|
||||
try test__negvsi2(42, -42);
|
||||
try test__negvsi2(2147483644, -2147483644);
|
||||
try test__negvsi2(2147483645, -2147483645);
|
||||
try test__negvsi2(2147483646, -2147483646);
|
||||
try test__negvsi2(2147483647, -2147483647);
|
||||
}
|
30
lib/std/special/compiler_rt/negvti2_test.zig
Normal file
30
lib/std/special/compiler_rt/negvti2_test.zig
Normal file
@ -0,0 +1,30 @@
|
||||
const negv = @import("negv.zig");
|
||||
const testing = @import("std").testing;
|
||||
|
||||
fn test__negvti2(a: i128, expected: i128) !void {
|
||||
var result = negv.__negvti2(a);
|
||||
try testing.expectEqual(expected, result);
|
||||
}
|
||||
|
||||
test "negvti2" {
|
||||
// -2^127 <= i128 <= 2^127-1
|
||||
// 2^127 = 170141183460469231731687303715884105728
|
||||
// 2^127+1 = 170141183460469231731687303715884105727
|
||||
// TODO write panic handler for testing panics
|
||||
//try test__negvti2(-170141183460469231731687303715884105728, -5); // tested with return -5; and panic
|
||||
try test__negvti2(-170141183460469231731687303715884105727, 170141183460469231731687303715884105727);
|
||||
try test__negvti2(-170141183460469231731687303715884105726, 170141183460469231731687303715884105726);
|
||||
try test__negvti2(-170141183460469231731687303715884105725, 170141183460469231731687303715884105725);
|
||||
try test__negvti2(-170141183460469231731687303715884105724, 170141183460469231731687303715884105724);
|
||||
try test__negvti2(-42, 42);
|
||||
try test__negvti2(-7, 7);
|
||||
try test__negvti2(-1, 1);
|
||||
try test__negvti2(0, 0);
|
||||
try test__negvti2(1, -1);
|
||||
try test__negvti2(7, -7);
|
||||
try test__negvti2(42, -42);
|
||||
try test__negvti2(170141183460469231731687303715884105724, -170141183460469231731687303715884105724);
|
||||
try test__negvti2(170141183460469231731687303715884105725, -170141183460469231731687303715884105725);
|
||||
try test__negvti2(170141183460469231731687303715884105726, -170141183460469231731687303715884105726);
|
||||
try test__negvti2(170141183460469231731687303715884105727, -170141183460469231731687303715884105727);
|
||||
}
|
Loading…
Reference in New Issue
Block a user