authorgravatar for matu3ba@users.noreply.github.commatu3ba <matu3ba@users.noreply.github.com> 2023-02-11 13:41:08+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-02-11 14:41:08+02:00
logd976b4e4a56e4ac6b45a3d9ae9766e57bf04f82b
tree1ddf6b56768e3817ecd40871a29b486fb32bcd50
parentba680aa98737ae1f572de3bf0b7ef7a7da27ed31
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

compiler_rt: __divmodti4 for libgcc symbol compatibility

- Copy and adjust __divmodsi4 tests for __divmoddi4 and __divmodti4. - Assuming d = a/b does not overflow (MIN/-1) or uses div by 0, then tmp = (d * b) = (a/b * b) = a does not overflow. => Remove wraparound for remainder in applicable routines.

3 files changed, 67 insertions(+), 4 deletions(-)

lib/compiler_rt/README.md+1-1
...@@ -114,7 +114,7 @@ Integer and Float Operations...@@ -114,7 +114,7 @@ Integer and Float Operations
114| ✓ | __udivmodti4 | u128 | u128 | u128 | .. |114| ✓ | __udivmodti4 | u128 | u128 | u128 | .. |
115| ✓ | __divmodsi4 | i32 | i32 | i32 | `a / b, rem.* = a % b` |115| ✓ | __divmodsi4 | i32 | i32 | i32 | `a / b, rem.* = a % b` |
116| ✓ | __divmoddi4 | i64 | i64 | i64 | .. |116| ✓ | __divmoddi4 | i64 | i64 | i64 | .. |
117| ✗ | __divmodti4 | i128 | i128 | i128 | .. [^libgcc_compat] |117| ✓ | __divmodti4 | i128 | i128 | i128 | .. [^libgcc_compat] |
118| | | | | | **Integer Arithmetic with Trapping Overflow**|118| | | | | | **Integer Arithmetic with Trapping Overflow**|
119| ✓ | __absvsi2 | i32 | i32 | i32 | abs(a) |119| ✓ | __absvsi2 | i32 | i32 | i32 | abs(a) |
120| ✓ | __absvdi2 | i64 | i64 | i64 | .. |120| ✓ | __absvdi2 | i64 | i64 | i64 | .. |
lib/compiler_rt/int.zig+65-3
...@@ -9,10 +9,12 @@ const arch = builtin.cpu.arch;...@@ -9,10 +9,12 @@ const arch = builtin.cpu.arch;
9const is_test = builtin.is_test;9const is_test = builtin.is_test;
10const common = @import("common.zig");10const common = @import("common.zig");
11const udivmod = @import("udivmod.zig").udivmod;11const udivmod = @import("udivmod.zig").udivmod;
12const __divti3 = @import("divti3.zig").__divti3;
1213
13pub const panic = common.panic;14pub const panic = common.panic;
1415
15comptime {16comptime {
17 @export(__divmodti4, .{ .name = "__divmodti4", .linkage = common.linkage, .visibility = common.visibility });
16 @export(__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = common.linkage, .visibility = common.visibility });18 @export(__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = common.linkage, .visibility = common.visibility });
17 @export(__mulsi3, .{ .name = "__mulsi3", .linkage = common.linkage, .visibility = common.visibility });19 @export(__mulsi3, .{ .name = "__mulsi3", .linkage = common.linkage, .visibility = common.visibility });
18 @export(__divmoddi4, .{ .name = "__divmoddi4", .linkage = common.linkage, .visibility = common.visibility });20 @export(__divmoddi4, .{ .name = "__divmoddi4", .linkage = common.linkage, .visibility = common.visibility });
...@@ -33,12 +35,72 @@ comptime {...@@ -33,12 +35,72 @@ comptime {
33 @export(__udivmodsi4, .{ .name = "__udivmodsi4", .linkage = common.linkage, .visibility = common.visibility });35 @export(__udivmodsi4, .{ .name = "__udivmodsi4", .linkage = common.linkage, .visibility = common.visibility });
34}36}
3537
38pub fn __divmodti4(a: i128, b: i128, rem: *i128) callconv(.C) i128 {
39 const d = __divti3(a, b);
40 rem.* = a -% (d * b);
41 return d;
42}
43
44test "test_divmodti4" {
45 const cases = [_][4]i128{
46 [_]i128{ 0, 1, 0, 0 },
47 [_]i128{ 0, -1, 0, 0 },
48 [_]i128{ 2, 1, 2, 0 },
49 [_]i128{ 2, -1, -2, 0 },
50 [_]i128{ -2, 1, -2, 0 },
51 [_]i128{ -2, -1, 2, 0 },
52 [_]i128{ 7, 5, 1, 2 },
53 [_]i128{ -7, 5, -1, -2 },
54 [_]i128{ 19, 5, 3, 4 },
55 [_]i128{ 19, -5, -3, 4 },
56 [_]i128{ @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 8, @bitCast(i128, @as(u128, 0xf0000000000000000000000000000000)), 0 },
57 [_]i128{ @bitCast(i128, @as(u128, 0x80000000000000000000000000000007)), 8, @bitCast(i128, @as(u128, 0xf0000000000000000000000000000001)), -1 },
58 };
59
60 for (cases) |case| {
61 try test_one_divmodti4(case[0], case[1], case[2], case[3]);
62 }
63}
64
65fn test_one_divmodti4(a: i128, b: i128, expected_q: i128, expected_r: i128) !void {
66 var r: i128 = undefined;
67 const q: i128 = __divmodti4(a, b, &r);
68 try testing.expect(q == expected_q and r == expected_r);
69}
70
36pub fn __divmoddi4(a: i64, b: i64, rem: *i64) callconv(.C) i64 {71pub fn __divmoddi4(a: i64, b: i64, rem: *i64) callconv(.C) i64 {
37 const d = __divdi3(a, b);72 const d = __divdi3(a, b);
38 rem.* = a -% (d *% b);73 rem.* = a -% (d * b);
39 return d;74 return d;
40}75}
4176
77test "test_divmoddi4" {
78 const cases = [_][4]i64{
79 [_]i64{ 0, 1, 0, 0 },
80 [_]i64{ 0, -1, 0, 0 },
81 [_]i64{ 2, 1, 2, 0 },
82 [_]i64{ 2, -1, -2, 0 },
83 [_]i64{ -2, 1, -2, 0 },
84 [_]i64{ -2, -1, 2, 0 },
85 [_]i64{ 7, 5, 1, 2 },
86 [_]i64{ -7, 5, -1, -2 },
87 [_]i64{ 19, 5, 3, 4 },
88 [_]i64{ 19, -5, -3, 4 },
89 [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 8, @bitCast(i64, @as(u64, 0xf000000000000000)), 0 },
90 [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000007)), 8, @bitCast(i64, @as(u64, 0xf000000000000001)), -1 },
91 };
92
93 for (cases) |case| {
94 try test_one_divmoddi4(case[0], case[1], case[2], case[3]);
95 }
96}
97
98fn test_one_divmoddi4(a: i64, b: i64, expected_q: i64, expected_r: i64) !void {
99 var r: i64 = undefined;
100 const q: i64 = __divmoddi4(a, b, &r);
101 try testing.expect(q == expected_q and r == expected_r);
102}
103
42pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.C) u64 {104pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.C) u64 {
43 return udivmod(u64, a, b, maybe_rem);105 return udivmod(u64, a, b, maybe_rem);
44}106}
...@@ -424,7 +486,7 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) !void {...@@ -424,7 +486,7 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) !void {
424}486}
425487
426pub fn __modsi3(n: i32, d: i32) callconv(.C) i32 {488pub fn __modsi3(n: i32, d: i32) callconv(.C) i32 {
427 return n -% __divsi3(n, d) *% d;489 return n -% __divsi3(n, d) * d;
428}490}
429491
430test "test_modsi3" {492test "test_modsi3" {
...@@ -453,7 +515,7 @@ fn test_one_modsi3(a: i32, b: i32, expected_r: i32) !void {...@@ -453,7 +515,7 @@ fn test_one_modsi3(a: i32, b: i32, expected_r: i32) !void {
453}515}
454516
455pub fn __umodsi3(n: u32, d: u32) callconv(.C) u32 {517pub fn __umodsi3(n: u32, d: u32) callconv(.C) u32 {
456 return n -% __udivsi3(n, d) *% d;518 return n -% __udivsi3(n, d) * d;
457}519}
458520
459test "test_umodsi3" {521test "test_umodsi3" {
tools/gen_stubs.zig+1
...@@ -666,6 +666,7 @@ const blacklisted_symbols = [_][]const u8{...@@ -666,6 +666,7 @@ const blacklisted_symbols = [_][]const u8{
666 "__divkf3",666 "__divkf3",
667 "__divmoddi4",667 "__divmoddi4",
668 "__divmodsi4",668 "__divmodsi4",
669 "__divmodti4",
669 "__divsf3",670 "__divsf3",
670 "__divsi3",671 "__divsi3",
671 "__divtf3",672 "__divtf3",