mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
compiler-rt: remove dead code
`__addosi4`, `__addodi4`, `__addoti4`, `__subosi4`, `__subodi4`, and `__suboti4` were all functions which we invented for no apparent reason. Neither LLVM, nor GCC, nor the Zig compiler use these functions. It appears the functions were created in a kind of misunderstanding of an old language proposal; see https://github.com/ziglang/zig/pull/10824. There is no benefit to these functions existing; if a Zig compiler backend needs this operation, it is trivial to implement, and *far* simpler than calling a compiler-rt routine. Therefore, this commit deletes them. A small amount of that code was used by other parts of compiler-rt; the logic is trivial so has just been inlined where needed. I also chose to quickly implement `__addvdi3` (a standard function) because it is trivial and we already implement the `sub` parallel.
This commit is contained in:
parent
c091e27aac
commit
20bd5e8018
@ -211,10 +211,10 @@ set(ZIG_STAGE2_SOURCES
|
|||||||
lib/compiler_rt/absvti2.zig
|
lib/compiler_rt/absvti2.zig
|
||||||
lib/compiler_rt/adddf3.zig
|
lib/compiler_rt/adddf3.zig
|
||||||
lib/compiler_rt/addf3.zig
|
lib/compiler_rt/addf3.zig
|
||||||
lib/compiler_rt/addo.zig
|
|
||||||
lib/compiler_rt/addsf3.zig
|
lib/compiler_rt/addsf3.zig
|
||||||
lib/compiler_rt/addtf3.zig
|
lib/compiler_rt/addtf3.zig
|
||||||
lib/compiler_rt/addvsi3.zig
|
lib/compiler_rt/addvsi3.zig
|
||||||
|
lib/compiler_rt/addvdi3.zig
|
||||||
lib/compiler_rt/addxf3.zig
|
lib/compiler_rt/addxf3.zig
|
||||||
lib/compiler_rt/arm.zig
|
lib/compiler_rt/arm.zig
|
||||||
lib/compiler_rt/atomics.zig
|
lib/compiler_rt/atomics.zig
|
||||||
@ -354,7 +354,6 @@ set(ZIG_STAGE2_SOURCES
|
|||||||
lib/compiler_rt/sqrt.zig
|
lib/compiler_rt/sqrt.zig
|
||||||
lib/compiler_rt/stack_probe.zig
|
lib/compiler_rt/stack_probe.zig
|
||||||
lib/compiler_rt/subdf3.zig
|
lib/compiler_rt/subdf3.zig
|
||||||
lib/compiler_rt/subo.zig
|
|
||||||
lib/compiler_rt/subsf3.zig
|
lib/compiler_rt/subsf3.zig
|
||||||
lib/compiler_rt/subtf3.zig
|
lib/compiler_rt/subtf3.zig
|
||||||
lib/compiler_rt/subvdi3.zig
|
lib/compiler_rt/subvdi3.zig
|
||||||
|
|||||||
@ -28,12 +28,13 @@ comptime {
|
|||||||
_ = @import("compiler_rt/negv.zig");
|
_ = @import("compiler_rt/negv.zig");
|
||||||
|
|
||||||
_ = @import("compiler_rt/addvsi3.zig");
|
_ = @import("compiler_rt/addvsi3.zig");
|
||||||
|
_ = @import("compiler_rt/addvdi3.zig");
|
||||||
|
|
||||||
_ = @import("compiler_rt/subvsi3.zig");
|
_ = @import("compiler_rt/subvsi3.zig");
|
||||||
_ = @import("compiler_rt/subvdi3.zig");
|
_ = @import("compiler_rt/subvdi3.zig");
|
||||||
|
|
||||||
_ = @import("compiler_rt/mulvsi3.zig");
|
_ = @import("compiler_rt/mulvsi3.zig");
|
||||||
|
|
||||||
_ = @import("compiler_rt/addo.zig");
|
|
||||||
_ = @import("compiler_rt/subo.zig");
|
|
||||||
_ = @import("compiler_rt/mulo.zig");
|
_ = @import("compiler_rt/mulo.zig");
|
||||||
|
|
||||||
// Float routines
|
// Float routines
|
||||||
|
|||||||
@ -1,46 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const common = @import("./common.zig");
|
|
||||||
pub const panic = @import("common.zig").panic;
|
|
||||||
|
|
||||||
comptime {
|
|
||||||
@export(&__addosi4, .{ .name = "__addosi4", .linkage = common.linkage, .visibility = common.visibility });
|
|
||||||
@export(&__addodi4, .{ .name = "__addodi4", .linkage = common.linkage, .visibility = common.visibility });
|
|
||||||
@export(&__addoti4, .{ .name = "__addoti4", .linkage = common.linkage, .visibility = common.visibility });
|
|
||||||
}
|
|
||||||
|
|
||||||
// addo - add overflow
|
|
||||||
// * return a+%b.
|
|
||||||
// * return if a+b overflows => 1 else => 0
|
|
||||||
// - addoXi4_generic as default
|
|
||||||
|
|
||||||
inline fn addoXi4_generic(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST {
|
|
||||||
@setRuntimeSafety(common.test_safety);
|
|
||||||
overflow.* = 0;
|
|
||||||
const sum: ST = a +% b;
|
|
||||||
// Hackers Delight: section Overflow Detection, subsection Signed Add/Subtract
|
|
||||||
// Let sum = a +% b == a + b + carry == wraparound addition.
|
|
||||||
// Overflow in a+b+carry occurs, iff a and b have opposite signs
|
|
||||||
// and the sign of a+b+carry is the same as a (or equivalently b).
|
|
||||||
// Slower routine: res = ~(a ^ b) & ((sum ^ a)
|
|
||||||
// Faster routine: res = (sum ^ a) & (sum ^ b)
|
|
||||||
// Overflow occurred, iff (res < 0)
|
|
||||||
if (((sum ^ a) & (sum ^ b)) < 0)
|
|
||||||
overflow.* = 1;
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __addosi4(a: i32, b: i32, overflow: *c_int) callconv(.c) i32 {
|
|
||||||
return addoXi4_generic(i32, a, b, overflow);
|
|
||||||
}
|
|
||||||
pub fn __addodi4(a: i64, b: i64, overflow: *c_int) callconv(.c) i64 {
|
|
||||||
return addoXi4_generic(i64, a, b, overflow);
|
|
||||||
}
|
|
||||||
pub fn __addoti4(a: i128, b: i128, overflow: *c_int) callconv(.c) i128 {
|
|
||||||
return addoXi4_generic(i128, a, b, overflow);
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
_ = @import("addosi4_test.zig");
|
|
||||||
_ = @import("addodi4_test.zig");
|
|
||||||
_ = @import("addoti4_test.zig");
|
|
||||||
}
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
const addv = @import("addo.zig");
|
|
||||||
const std = @import("std");
|
|
||||||
const testing = std.testing;
|
|
||||||
const math = std.math;
|
|
||||||
|
|
||||||
fn test__addodi4(a: i64, b: i64) !void {
|
|
||||||
var result_ov: c_int = undefined;
|
|
||||||
var expected_ov: c_int = undefined;
|
|
||||||
const result = addv.__addodi4(a, b, &result_ov);
|
|
||||||
const expected: i64 = simple_addodi4(a, b, &expected_ov);
|
|
||||||
try testing.expectEqual(expected, result);
|
|
||||||
try testing.expectEqual(expected_ov, result_ov);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn simple_addodi4(a: i64, b: i64, overflow: *c_int) i64 {
|
|
||||||
overflow.* = 0;
|
|
||||||
const min: i64 = math.minInt(i64);
|
|
||||||
const max: i64 = math.maxInt(i64);
|
|
||||||
if (((a > 0) and (b > max - a)) or
|
|
||||||
((a < 0) and (b < min - a)))
|
|
||||||
overflow.* = 1;
|
|
||||||
return a +% b;
|
|
||||||
}
|
|
||||||
|
|
||||||
test "addodi4" {
|
|
||||||
const min: i64 = math.minInt(i64);
|
|
||||||
const max: i64 = math.maxInt(i64);
|
|
||||||
var i: i64 = 1;
|
|
||||||
while (i < max) : (i *|= 2) {
|
|
||||||
try test__addodi4(i, i);
|
|
||||||
try test__addodi4(-i, -i);
|
|
||||||
try test__addodi4(i, -i);
|
|
||||||
try test__addodi4(-i, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// edge cases
|
|
||||||
// 0 + 0 = 0
|
|
||||||
// MIN + MIN overflow
|
|
||||||
// MAX + MAX overflow
|
|
||||||
// 0 + MIN MIN
|
|
||||||
// 0 + MAX MAX
|
|
||||||
// MIN + 0 MIN
|
|
||||||
// MAX + 0 MAX
|
|
||||||
// MIN + MAX -1
|
|
||||||
// MAX + MIN -1
|
|
||||||
try test__addodi4(0, 0);
|
|
||||||
try test__addodi4(min, min);
|
|
||||||
try test__addodi4(max, max);
|
|
||||||
try test__addodi4(0, min);
|
|
||||||
try test__addodi4(0, max);
|
|
||||||
try test__addodi4(min, 0);
|
|
||||||
try test__addodi4(max, 0);
|
|
||||||
try test__addodi4(min, max);
|
|
||||||
try test__addodi4(max, min);
|
|
||||||
|
|
||||||
// derived edge cases
|
|
||||||
// MIN+1 + MIN overflow
|
|
||||||
// MAX-1 + MAX overflow
|
|
||||||
// 1 + MIN = MIN+1
|
|
||||||
// -1 + MIN overflow
|
|
||||||
// -1 + MAX = MAX-1
|
|
||||||
// +1 + MAX overflow
|
|
||||||
// MIN + 1 = MIN+1
|
|
||||||
// MIN + -1 overflow
|
|
||||||
// MAX + 1 overflow
|
|
||||||
// MAX + -1 = MAX-1
|
|
||||||
try test__addodi4(min + 1, min);
|
|
||||||
try test__addodi4(max - 1, max);
|
|
||||||
try test__addodi4(1, min);
|
|
||||||
try test__addodi4(-1, min);
|
|
||||||
try test__addodi4(-1, max);
|
|
||||||
try test__addodi4(1, max);
|
|
||||||
try test__addodi4(min, 1);
|
|
||||||
try test__addodi4(min, -1);
|
|
||||||
try test__addodi4(max, -1);
|
|
||||||
try test__addodi4(max, 1);
|
|
||||||
}
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
const addv = @import("addo.zig");
|
|
||||||
const testing = @import("std").testing;
|
|
||||||
|
|
||||||
fn test__addosi4(a: i32, b: i32) !void {
|
|
||||||
var result_ov: c_int = undefined;
|
|
||||||
var expected_ov: c_int = undefined;
|
|
||||||
const result = addv.__addosi4(a, b, &result_ov);
|
|
||||||
const expected: i32 = simple_addosi4(a, b, &expected_ov);
|
|
||||||
try testing.expectEqual(expected, result);
|
|
||||||
try testing.expectEqual(expected_ov, result_ov);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn simple_addosi4(a: i32, b: i32, overflow: *c_int) i32 {
|
|
||||||
overflow.* = 0;
|
|
||||||
const min: i32 = -2147483648;
|
|
||||||
const max: i32 = 2147483647;
|
|
||||||
if (((a > 0) and (b > max - a)) or
|
|
||||||
((a < 0) and (b < min - a)))
|
|
||||||
overflow.* = 1;
|
|
||||||
return a +% b;
|
|
||||||
}
|
|
||||||
|
|
||||||
test "addosi4" {
|
|
||||||
// -2^31 <= i32 <= 2^31-1
|
|
||||||
// 2^31 = 2147483648
|
|
||||||
// 2^31-1 = 2147483647
|
|
||||||
const min: i32 = -2147483648;
|
|
||||||
const max: i32 = 2147483647;
|
|
||||||
var i: i32 = 1;
|
|
||||||
while (i < max) : (i *|= 2) {
|
|
||||||
try test__addosi4(i, i);
|
|
||||||
try test__addosi4(-i, -i);
|
|
||||||
try test__addosi4(i, -i);
|
|
||||||
try test__addosi4(-i, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// edge cases
|
|
||||||
// 0 + 0 = 0
|
|
||||||
// MIN + MIN overflow
|
|
||||||
// MAX + MAX overflow
|
|
||||||
// 0 + MIN MIN
|
|
||||||
// 0 + MAX MAX
|
|
||||||
// MIN + 0 MIN
|
|
||||||
// MAX + 0 MAX
|
|
||||||
// MIN + MAX -1
|
|
||||||
// MAX + MIN -1
|
|
||||||
try test__addosi4(0, 0);
|
|
||||||
try test__addosi4(min, min);
|
|
||||||
try test__addosi4(max, max);
|
|
||||||
try test__addosi4(0, min);
|
|
||||||
try test__addosi4(0, max);
|
|
||||||
try test__addosi4(min, 0);
|
|
||||||
try test__addosi4(max, 0);
|
|
||||||
try test__addosi4(min, max);
|
|
||||||
try test__addosi4(max, min);
|
|
||||||
|
|
||||||
// derived edge cases
|
|
||||||
// MIN+1 + MIN overflow
|
|
||||||
// MAX-1 + MAX overflow
|
|
||||||
// 1 + MIN = MIN+1
|
|
||||||
// -1 + MIN overflow
|
|
||||||
// -1 + MAX = MAX-1
|
|
||||||
// +1 + MAX overflow
|
|
||||||
// MIN + 1 = MIN+1
|
|
||||||
// MIN + -1 overflow
|
|
||||||
// MAX + 1 overflow
|
|
||||||
// MAX + -1 = MAX-1
|
|
||||||
try test__addosi4(min + 1, min);
|
|
||||||
try test__addosi4(max - 1, max);
|
|
||||||
try test__addosi4(1, min);
|
|
||||||
try test__addosi4(-1, min);
|
|
||||||
try test__addosi4(-1, max);
|
|
||||||
try test__addosi4(1, max);
|
|
||||||
try test__addosi4(min, 1);
|
|
||||||
try test__addosi4(min, -1);
|
|
||||||
try test__addosi4(max, -1);
|
|
||||||
try test__addosi4(max, 1);
|
|
||||||
}
|
|
||||||
@ -1,80 +0,0 @@
|
|||||||
const addv = @import("addo.zig");
|
|
||||||
const builtin = @import("builtin");
|
|
||||||
const std = @import("std");
|
|
||||||
const testing = std.testing;
|
|
||||||
const math = std.math;
|
|
||||||
|
|
||||||
fn test__addoti4(a: i128, b: i128) !void {
|
|
||||||
var result_ov: c_int = undefined;
|
|
||||||
var expected_ov: c_int = undefined;
|
|
||||||
const result = addv.__addoti4(a, b, &result_ov);
|
|
||||||
const expected: i128 = simple_addoti4(a, b, &expected_ov);
|
|
||||||
try testing.expectEqual(expected, result);
|
|
||||||
try testing.expectEqual(expected_ov, result_ov);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn simple_addoti4(a: i128, b: i128, overflow: *c_int) i128 {
|
|
||||||
overflow.* = 0;
|
|
||||||
const min: i128 = math.minInt(i128);
|
|
||||||
const max: i128 = math.maxInt(i128);
|
|
||||||
if (((a > 0) and (b > max - a)) or
|
|
||||||
((a < 0) and (b < min - a)))
|
|
||||||
overflow.* = 1;
|
|
||||||
return a +% b;
|
|
||||||
}
|
|
||||||
|
|
||||||
test "addoti4" {
|
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
||||||
|
|
||||||
const min: i128 = math.minInt(i128);
|
|
||||||
const max: i128 = math.maxInt(i128);
|
|
||||||
var i: i128 = 1;
|
|
||||||
while (i < max) : (i *|= 2) {
|
|
||||||
try test__addoti4(i, i);
|
|
||||||
try test__addoti4(-i, -i);
|
|
||||||
try test__addoti4(i, -i);
|
|
||||||
try test__addoti4(-i, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// edge cases
|
|
||||||
// 0 + 0 = 0
|
|
||||||
// MIN + MIN overflow
|
|
||||||
// MAX + MAX overflow
|
|
||||||
// 0 + MIN MIN
|
|
||||||
// 0 + MAX MAX
|
|
||||||
// MIN + 0 MIN
|
|
||||||
// MAX + 0 MAX
|
|
||||||
// MIN + MAX -1
|
|
||||||
// MAX + MIN -1
|
|
||||||
try test__addoti4(0, 0);
|
|
||||||
try test__addoti4(min, min);
|
|
||||||
try test__addoti4(max, max);
|
|
||||||
try test__addoti4(0, min);
|
|
||||||
try test__addoti4(0, max);
|
|
||||||
try test__addoti4(min, 0);
|
|
||||||
try test__addoti4(max, 0);
|
|
||||||
try test__addoti4(min, max);
|
|
||||||
try test__addoti4(max, min);
|
|
||||||
|
|
||||||
// derived edge cases
|
|
||||||
// MIN+1 + MIN overflow
|
|
||||||
// MAX-1 + MAX overflow
|
|
||||||
// 1 + MIN = MIN+1
|
|
||||||
// -1 + MIN overflow
|
|
||||||
// -1 + MAX = MAX-1
|
|
||||||
// +1 + MAX overflow
|
|
||||||
// MIN + 1 = MIN+1
|
|
||||||
// MIN + -1 overflow
|
|
||||||
// MAX + 1 overflow
|
|
||||||
// MAX + -1 = MAX-1
|
|
||||||
try test__addoti4(min + 1, min);
|
|
||||||
try test__addoti4(max - 1, max);
|
|
||||||
try test__addoti4(1, min);
|
|
||||||
try test__addoti4(-1, min);
|
|
||||||
try test__addoti4(-1, max);
|
|
||||||
try test__addoti4(1, max);
|
|
||||||
try test__addoti4(min, 1);
|
|
||||||
try test__addoti4(min, -1);
|
|
||||||
try test__addoti4(max, -1);
|
|
||||||
try test__addoti4(max, 1);
|
|
||||||
}
|
|
||||||
26
lib/compiler_rt/addvdi3.zig
Normal file
26
lib/compiler_rt/addvdi3.zig
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
const common = @import("./common.zig");
|
||||||
|
const testing = @import("std").testing;
|
||||||
|
|
||||||
|
pub const panic = common.panic;
|
||||||
|
|
||||||
|
comptime {
|
||||||
|
@export(&__addvdi3, .{ .name = "__addvdi3", .linkage = common.linkage, .visibility = common.visibility });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __addvdi3(a: i64, b: i64) callconv(.c) i64 {
|
||||||
|
const sum = a +% b;
|
||||||
|
// Overflow occurred iff both operands have the same sign, and the sign of the sum does
|
||||||
|
// not match it. In other words, iff the sum sign is not the sign of either operand.
|
||||||
|
if (((sum ^ a) & (sum ^ b)) < 0) @panic("compiler-rt: integer overflow");
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
test "addvdi3" {
|
||||||
|
// const min: i64 = -9223372036854775808
|
||||||
|
// const max: i64 = 9223372036854775807
|
||||||
|
// TODO write panic handler for testing panics
|
||||||
|
// try test__addvdi3(-9223372036854775808, -1, -1); // panic
|
||||||
|
// try test__addvdi3(9223372036854775807, 1, 1); // panic
|
||||||
|
try testing.expectEqual(-9223372036854775808, __addvdi3(-9223372036854775807, -1));
|
||||||
|
try testing.expectEqual(9223372036854775807, __addvdi3(9223372036854775806, 1));
|
||||||
|
}
|
||||||
@ -1,4 +1,3 @@
|
|||||||
const addv = @import("addo.zig");
|
|
||||||
const common = @import("./common.zig");
|
const common = @import("./common.zig");
|
||||||
const testing = @import("std").testing;
|
const testing = @import("std").testing;
|
||||||
|
|
||||||
@ -9,9 +8,10 @@ comptime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn __addvsi3(a: i32, b: i32) callconv(.c) i32 {
|
pub fn __addvsi3(a: i32, b: i32) callconv(.c) i32 {
|
||||||
var overflow: c_int = 0;
|
const sum = a +% b;
|
||||||
const sum = addv.__addosi4(a, b, &overflow);
|
// Overflow occurred iff both operands have the same sign, and the sign of the sum does
|
||||||
if (overflow != 0) @panic("compiler-rt: integer overflow");
|
// not match it. In other words, iff the sum sign is not the sign of either operand.
|
||||||
|
if (((sum ^ a) & (sum ^ b)) < 0) @panic("compiler-rt: integer overflow");
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,47 +0,0 @@
|
|||||||
//! subo - subtract overflow
|
|
||||||
//! * return a-%b.
|
|
||||||
//! * return if a-b overflows => 1 else => 0
|
|
||||||
//! - suboXi4_generic as default
|
|
||||||
|
|
||||||
const std = @import("std");
|
|
||||||
const builtin = @import("builtin");
|
|
||||||
const common = @import("common.zig");
|
|
||||||
|
|
||||||
pub const panic = common.panic;
|
|
||||||
|
|
||||||
comptime {
|
|
||||||
@export(&__subosi4, .{ .name = "__subosi4", .linkage = common.linkage, .visibility = common.visibility });
|
|
||||||
@export(&__subodi4, .{ .name = "__subodi4", .linkage = common.linkage, .visibility = common.visibility });
|
|
||||||
@export(&__suboti4, .{ .name = "__suboti4", .linkage = common.linkage, .visibility = common.visibility });
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __subosi4(a: i32, b: i32, overflow: *c_int) callconv(.c) i32 {
|
|
||||||
return suboXi4_generic(i32, a, b, overflow);
|
|
||||||
}
|
|
||||||
pub fn __subodi4(a: i64, b: i64, overflow: *c_int) callconv(.c) i64 {
|
|
||||||
return suboXi4_generic(i64, a, b, overflow);
|
|
||||||
}
|
|
||||||
pub fn __suboti4(a: i128, b: i128, overflow: *c_int) callconv(.c) i128 {
|
|
||||||
return suboXi4_generic(i128, a, b, overflow);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fn suboXi4_generic(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST {
|
|
||||||
overflow.* = 0;
|
|
||||||
const sum: ST = a -% b;
|
|
||||||
// Hackers Delight: section Overflow Detection, subsection Signed Add/Subtract
|
|
||||||
// Let sum = a -% b == a - b - carry == wraparound subtraction.
|
|
||||||
// Overflow in a-b-carry occurs, iff a and b have opposite signs
|
|
||||||
// and the sign of a-b-carry is opposite of a (or equivalently same as b).
|
|
||||||
// Faster routine: res = (a ^ b) & (sum ^ a)
|
|
||||||
// Slower routine: res = (sum^a) & ~(sum^b)
|
|
||||||
// Overflow occurred, iff (res < 0)
|
|
||||||
if (((a ^ b) & (sum ^ a)) < 0)
|
|
||||||
overflow.* = 1;
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
_ = @import("subosi4_test.zig");
|
|
||||||
_ = @import("subodi4_test.zig");
|
|
||||||
_ = @import("suboti4_test.zig");
|
|
||||||
}
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
const subo = @import("subo.zig");
|
|
||||||
const std = @import("std");
|
|
||||||
const testing = std.testing;
|
|
||||||
const math = std.math;
|
|
||||||
|
|
||||||
fn test__subodi4(a: i64, b: i64) !void {
|
|
||||||
var result_ov: c_int = undefined;
|
|
||||||
var expected_ov: c_int = undefined;
|
|
||||||
const result = subo.__subodi4(a, b, &result_ov);
|
|
||||||
const expected: i64 = simple_subodi4(a, b, &expected_ov);
|
|
||||||
try testing.expectEqual(expected, result);
|
|
||||||
try testing.expectEqual(expected_ov, result_ov);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2 cases on evaluating `a-b`:
|
|
||||||
// 1. `a-b` may underflow, iff b>0 && a<0 and a-b < min <=> a<min+b
|
|
||||||
// 2. `a-b` may overflow, iff b<0 && a>0 and a-b > max <=> a>max+b
|
|
||||||
// `-b` evaluation may overflow, iff b==min, but this is handled by the hardware
|
|
||||||
pub fn simple_subodi4(a: i64, b: i64, overflow: *c_int) i64 {
|
|
||||||
overflow.* = 0;
|
|
||||||
const min: i64 = math.minInt(i64);
|
|
||||||
const max: i64 = math.maxInt(i64);
|
|
||||||
if (((b > 0) and (a < min + b)) or
|
|
||||||
((b < 0) and (a > max + b)))
|
|
||||||
overflow.* = 1;
|
|
||||||
return a -% b;
|
|
||||||
}
|
|
||||||
|
|
||||||
test "subodi3" {
|
|
||||||
const min: i64 = math.minInt(i64);
|
|
||||||
const max: i64 = math.maxInt(i64);
|
|
||||||
var i: i64 = 1;
|
|
||||||
while (i < max) : (i *|= 2) {
|
|
||||||
try test__subodi4(i, i);
|
|
||||||
try test__subodi4(-i, -i);
|
|
||||||
try test__subodi4(i, -i);
|
|
||||||
try test__subodi4(-i, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// edge cases
|
|
||||||
// 0 - 0 = 0
|
|
||||||
// MIN - MIN = 0
|
|
||||||
// MAX - MAX = 0
|
|
||||||
// 0 - MIN overflow
|
|
||||||
// 0 - MAX = MIN+1
|
|
||||||
// MIN - 0 = MIN
|
|
||||||
// MAX - 0 = MAX
|
|
||||||
// MIN - MAX overflow
|
|
||||||
// MAX - MIN overflow
|
|
||||||
try test__subodi4(0, 0);
|
|
||||||
try test__subodi4(min, min);
|
|
||||||
try test__subodi4(max, max);
|
|
||||||
try test__subodi4(0, min);
|
|
||||||
try test__subodi4(0, max);
|
|
||||||
try test__subodi4(min, 0);
|
|
||||||
try test__subodi4(max, 0);
|
|
||||||
try test__subodi4(min, max);
|
|
||||||
try test__subodi4(max, min);
|
|
||||||
|
|
||||||
// derived edge cases
|
|
||||||
// MIN+1 - MIN = 1
|
|
||||||
// MAX-1 - MAX = -1
|
|
||||||
// 1 - MIN overflow
|
|
||||||
// -1 - MIN = MAX
|
|
||||||
// -1 - MAX = MIN
|
|
||||||
// +1 - MAX = MIN+2
|
|
||||||
// MIN - 1 overflow
|
|
||||||
// MIN - -1 = MIN+1
|
|
||||||
// MAX - 1 = MAX-1
|
|
||||||
// MAX - -1 overflow
|
|
||||||
try test__subodi4(min + 1, min);
|
|
||||||
try test__subodi4(max - 1, max);
|
|
||||||
try test__subodi4(1, min);
|
|
||||||
try test__subodi4(-1, min);
|
|
||||||
try test__subodi4(-1, max);
|
|
||||||
try test__subodi4(1, max);
|
|
||||||
try test__subodi4(min, 1);
|
|
||||||
try test__subodi4(min, -1);
|
|
||||||
try test__subodi4(max, -1);
|
|
||||||
try test__subodi4(max, 1);
|
|
||||||
}
|
|
||||||
@ -1,82 +0,0 @@
|
|||||||
const subo = @import("subo.zig");
|
|
||||||
const testing = @import("std").testing;
|
|
||||||
|
|
||||||
fn test__subosi4(a: i32, b: i32) !void {
|
|
||||||
var result_ov: c_int = undefined;
|
|
||||||
var expected_ov: c_int = undefined;
|
|
||||||
const result = subo.__subosi4(a, b, &result_ov);
|
|
||||||
const expected: i32 = simple_subosi4(a, b, &expected_ov);
|
|
||||||
try testing.expectEqual(expected, result);
|
|
||||||
try testing.expectEqual(expected_ov, result_ov);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2 cases on evaluating `a-b`:
|
|
||||||
// 1. `a-b` may underflow, iff b>0 && a<0 and a-b < min <=> a<min+b
|
|
||||||
// 2. `a-b` may overflow, iff b<0 && a>0 and a-b > max <=> a>max+b
|
|
||||||
// `-b` evaluation may overflow, iff b==min, but this is handled by the hardware
|
|
||||||
pub fn simple_subosi4(a: i32, b: i32, overflow: *c_int) i32 {
|
|
||||||
overflow.* = 0;
|
|
||||||
const min: i32 = -2147483648;
|
|
||||||
const max: i32 = 2147483647;
|
|
||||||
if (((b > 0) and (a < min + b)) or
|
|
||||||
((b < 0) and (a > max + b)))
|
|
||||||
overflow.* = 1;
|
|
||||||
return a -% b;
|
|
||||||
}
|
|
||||||
|
|
||||||
test "subosi3" {
|
|
||||||
// -2^31 <= i32 <= 2^31-1
|
|
||||||
// 2^31 = 2147483648
|
|
||||||
// 2^31-1 = 2147483647
|
|
||||||
const min: i32 = -2147483648;
|
|
||||||
const max: i32 = 2147483647;
|
|
||||||
var i: i32 = 1;
|
|
||||||
while (i < max) : (i *|= 2) {
|
|
||||||
try test__subosi4(i, i);
|
|
||||||
try test__subosi4(-i, -i);
|
|
||||||
try test__subosi4(i, -i);
|
|
||||||
try test__subosi4(-i, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// edge cases
|
|
||||||
// 0 - 0 = 0
|
|
||||||
// MIN - MIN = 0
|
|
||||||
// MAX - MAX = 0
|
|
||||||
// 0 - MIN overflow
|
|
||||||
// 0 - MAX = MIN+1
|
|
||||||
// MIN - 0 = MIN
|
|
||||||
// MAX - 0 = MAX
|
|
||||||
// MIN - MAX overflow
|
|
||||||
// MAX - MIN overflow
|
|
||||||
try test__subosi4(0, 0);
|
|
||||||
try test__subosi4(min, min);
|
|
||||||
try test__subosi4(max, max);
|
|
||||||
try test__subosi4(0, min);
|
|
||||||
try test__subosi4(0, max);
|
|
||||||
try test__subosi4(min, 0);
|
|
||||||
try test__subosi4(max, 0);
|
|
||||||
try test__subosi4(min, max);
|
|
||||||
try test__subosi4(max, min);
|
|
||||||
|
|
||||||
// derived edge cases
|
|
||||||
// MIN+1 - MIN = 1
|
|
||||||
// MAX-1 - MAX = -1
|
|
||||||
// 1 - MIN overflow
|
|
||||||
// -1 - MIN = MAX
|
|
||||||
// -1 - MAX = MIN
|
|
||||||
// +1 - MAX = MIN+2
|
|
||||||
// MIN - 1 overflow
|
|
||||||
// MIN - -1 = MIN+1
|
|
||||||
// MAX - 1 = MAX-1
|
|
||||||
// MAX - -1 overflow
|
|
||||||
try test__subosi4(min + 1, min);
|
|
||||||
try test__subosi4(max - 1, max);
|
|
||||||
try test__subosi4(1, min);
|
|
||||||
try test__subosi4(-1, min);
|
|
||||||
try test__subosi4(-1, max);
|
|
||||||
try test__subosi4(1, max);
|
|
||||||
try test__subosi4(min, 1);
|
|
||||||
try test__subosi4(min, -1);
|
|
||||||
try test__subosi4(max, -1);
|
|
||||||
try test__subosi4(max, 1);
|
|
||||||
}
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
const subo = @import("subo.zig");
|
|
||||||
const builtin = @import("builtin");
|
|
||||||
const std = @import("std");
|
|
||||||
const testing = std.testing;
|
|
||||||
const math = std.math;
|
|
||||||
|
|
||||||
fn test__suboti4(a: i128, b: i128) !void {
|
|
||||||
var result_ov: c_int = undefined;
|
|
||||||
var expected_ov: c_int = undefined;
|
|
||||||
const result = subo.__suboti4(a, b, &result_ov);
|
|
||||||
const expected: i128 = simple_suboti4(a, b, &expected_ov);
|
|
||||||
try testing.expectEqual(expected, result);
|
|
||||||
try testing.expectEqual(expected_ov, result_ov);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2 cases on evaluating `a-b`:
|
|
||||||
// 1. `a-b` may underflow, iff b>0 && a<0 and a-b < min <=> a<min+b
|
|
||||||
// 2. `a-b` may overflow, iff b<0 && a>0 and a-b > max <=> a>max+b
|
|
||||||
// `-b` evaluation may overflow, iff b==min, but this is handled by the hardware
|
|
||||||
pub fn simple_suboti4(a: i128, b: i128, overflow: *c_int) i128 {
|
|
||||||
overflow.* = 0;
|
|
||||||
const min: i128 = math.minInt(i128);
|
|
||||||
const max: i128 = math.maxInt(i128);
|
|
||||||
if (((b > 0) and (a < min + b)) or
|
|
||||||
((b < 0) and (a > max + b)))
|
|
||||||
overflow.* = 1;
|
|
||||||
return a -% b;
|
|
||||||
}
|
|
||||||
|
|
||||||
test "suboti3" {
|
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
||||||
|
|
||||||
const min: i128 = math.minInt(i128);
|
|
||||||
const max: i128 = math.maxInt(i128);
|
|
||||||
var i: i128 = 1;
|
|
||||||
while (i < max) : (i *|= 2) {
|
|
||||||
try test__suboti4(i, i);
|
|
||||||
try test__suboti4(-i, -i);
|
|
||||||
try test__suboti4(i, -i);
|
|
||||||
try test__suboti4(-i, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// edge cases
|
|
||||||
// 0 - 0 = 0
|
|
||||||
// MIN - MIN = 0
|
|
||||||
// MAX - MAX = 0
|
|
||||||
// 0 - MIN overflow
|
|
||||||
// 0 - MAX = MIN+1
|
|
||||||
// MIN - 0 = MIN
|
|
||||||
// MAX - 0 = MAX
|
|
||||||
// MIN - MAX overflow
|
|
||||||
// MAX - MIN overflow
|
|
||||||
try test__suboti4(0, 0);
|
|
||||||
try test__suboti4(min, min);
|
|
||||||
try test__suboti4(max, max);
|
|
||||||
try test__suboti4(0, min);
|
|
||||||
try test__suboti4(0, max);
|
|
||||||
try test__suboti4(min, 0);
|
|
||||||
try test__suboti4(max, 0);
|
|
||||||
try test__suboti4(min, max);
|
|
||||||
try test__suboti4(max, min);
|
|
||||||
|
|
||||||
// derived edge cases
|
|
||||||
// MIN+1 - MIN = 1
|
|
||||||
// MAX-1 - MAX = -1
|
|
||||||
// 1 - MIN overflow
|
|
||||||
// -1 - MIN = MAX
|
|
||||||
// -1 - MAX = MIN
|
|
||||||
// +1 - MAX = MIN+2
|
|
||||||
// MIN - 1 overflow
|
|
||||||
// MIN - -1 = MIN+1
|
|
||||||
// MAX - 1 = MAX-1
|
|
||||||
// MAX - -1 overflow
|
|
||||||
try test__suboti4(min + 1, min);
|
|
||||||
try test__suboti4(max - 1, max);
|
|
||||||
try test__suboti4(1, min);
|
|
||||||
try test__suboti4(-1, min);
|
|
||||||
try test__suboti4(-1, max);
|
|
||||||
try test__suboti4(1, max);
|
|
||||||
try test__suboti4(min, 1);
|
|
||||||
try test__suboti4(min, -1);
|
|
||||||
try test__suboti4(max, -1);
|
|
||||||
try test__suboti4(max, 1);
|
|
||||||
}
|
|
||||||
@ -1,4 +1,3 @@
|
|||||||
const subv = @import("subo.zig");
|
|
||||||
const common = @import("./common.zig");
|
const common = @import("./common.zig");
|
||||||
const testing = @import("std").testing;
|
const testing = @import("std").testing;
|
||||||
|
|
||||||
@ -9,9 +8,10 @@ comptime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn __subvdi3(a: i64, b: i64) callconv(.c) i64 {
|
pub fn __subvdi3(a: i64, b: i64) callconv(.c) i64 {
|
||||||
var overflow: c_int = 0;
|
const sum = a -% b;
|
||||||
const sum = subv.__subodi4(a, b, &overflow);
|
// Overflow occurred iff the operands have opposite signs, and the sign of the
|
||||||
if (overflow != 0) @panic("compiler-rt: integer overflow");
|
// sum is the opposite of the lhs sign.
|
||||||
|
if (((a ^ b) & (sum ^ a)) < 0) @panic("compiler-rt: integer overflow");
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
const subv = @import("subo.zig");
|
|
||||||
const common = @import("./common.zig");
|
const common = @import("./common.zig");
|
||||||
const testing = @import("std").testing;
|
const testing = @import("std").testing;
|
||||||
|
|
||||||
@ -9,9 +8,10 @@ comptime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn __subvsi3(a: i32, b: i32) callconv(.c) i32 {
|
pub fn __subvsi3(a: i32, b: i32) callconv(.c) i32 {
|
||||||
var overflow: c_int = 0;
|
const sum = a -% b;
|
||||||
const sum = subv.__subosi4(a, b, &overflow);
|
// Overflow occurred iff the operands have opposite signs, and the sign of the
|
||||||
if (overflow != 0) @panic("compiler-rt: integer overflow");
|
// sum is the opposite of the lhs sign.
|
||||||
|
if (((a ^ b) & (sum ^ a)) < 0) @panic("compiler-rt: integer overflow");
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user