diff --git a/lib/std/special/compiler_rt.zig b/lib/std/special/compiler_rt.zig index 357fab37bd..c8cb00ee3e 100644 --- a/lib/std/special/compiler_rt.zig +++ b/lib/std/special/compiler_rt.zig @@ -45,46 +45,45 @@ comptime { const __getf2 = @import("compiler_rt/compareXf2.zig").__getf2; @export(__getf2, .{ .name = "__getf2", .linkage = linkage }); + const __eqsf2 = @import("compiler_rt/compareXf2.zig").__eqsf2; + @export(__eqsf2, .{ .name = "__eqsf2", .linkage = linkage }); + const __eqdf2 = @import("compiler_rt/compareXf2.zig").__eqdf2; + @export(__eqdf2, .{ .name = "__eqdf2", .linkage = linkage }); + + const __ltsf2 = @import("compiler_rt/compareXf2.zig").__ltsf2; + @export(__ltsf2, .{ .name = "__ltsf2", .linkage = linkage }); + const __ltdf2 = @import("compiler_rt/compareXf2.zig").__ltdf2; + @export(__ltdf2, .{ .name = "__ltdf2", .linkage = linkage }); + + const __nesf2 = @import("compiler_rt/compareXf2.zig").__nesf2; + @export(__nesf2, .{ .name = "__nesf2", .linkage = linkage }); + const __nedf2 = @import("compiler_rt/compareXf2.zig").__nedf2; + @export(__nedf2, .{ .name = "__nedf2", .linkage = linkage }); + + const __gtsf2 = @import("compiler_rt/compareXf2.zig").__gtsf2; + @export(__gtsf2, .{ .name = "__gtsf2", .linkage = linkage }); + const __gtdf2 = @import("compiler_rt/compareXf2.zig").__gtdf2; + @export(__gtdf2, .{ .name = "__gtdf2", .linkage = linkage }); + if (!is_test) { @export(__lesf2, .{ .name = "__cmpsf2", .linkage = linkage }); @export(__ledf2, .{ .name = "__cmpdf2", .linkage = linkage }); @export(__letf2, .{ .name = "__cmptf2", .linkage = linkage }); - - const __eqsf2 = @import("compiler_rt/compareXf2.zig").__eqsf2; - @export(__eqsf2, .{ .name = "__eqsf2", .linkage = linkage }); - const __eqdf2 = @import("compiler_rt/compareXf2.zig").__eqdf2; - @export(__eqdf2, .{ .name = "__eqdf2", .linkage = linkage }); @export(__letf2, .{ .name = "__eqtf2", .linkage = linkage }); - - const __ltsf2 = @import("compiler_rt/compareXf2.zig").__ltsf2; - @export(__ltsf2, .{ .name = "__ltsf2", .linkage = linkage }); - const __ltdf2 = @import("compiler_rt/compareXf2.zig").__ltdf2; - @export(__ltdf2, .{ .name = "__ltdf2", .linkage = linkage }); @export(__letf2, .{ .name = "__lttf2", .linkage = linkage }); - - const __nesf2 = @import("compiler_rt/compareXf2.zig").__nesf2; - @export(__nesf2, .{ .name = "__nesf2", .linkage = linkage }); - const __nedf2 = @import("compiler_rt/compareXf2.zig").__nedf2; - @export(__nedf2, .{ .name = "__nedf2", .linkage = linkage }); - @export(__letf2, .{ .name = "__netf2", .linkage = linkage }); - - const __gtsf2 = @import("compiler_rt/compareXf2.zig").__gtsf2; - @export(__gtsf2, .{ .name = "__gtsf2", .linkage = linkage }); - const __gtdf2 = @import("compiler_rt/compareXf2.zig").__gtdf2; - @export(__gtdf2, .{ .name = "__gtdf2", .linkage = linkage }); @export(__getf2, .{ .name = "__gttf2", .linkage = linkage }); - + @export(__letf2, .{ .name = "__netf2", .linkage = linkage }); @export(__extendhfsf2, .{ .name = "__gnu_h2f_ieee", .linkage = linkage }); - - // Integral arithmetic which returns if overflow - const __mulosi4 = @import("compiler_rt/mulo.zig").__mulosi4; - @export(__mulosi4, .{ .name = "__mulosi4", .linkage = linkage }); - const __mulodi4 = @import("compiler_rt/mulo.zig").__mulodi4; - @export(__mulodi4, .{ .name = "__mulodi4", .linkage = linkage }); - const __muloti4 = @import("compiler_rt/mulo.zig").__muloti4; - @export(__muloti4, .{ .name = "__muloti4", .linkage = linkage }); } + // Integral arithmetic which returns if overflow + const __mulosi4 = @import("compiler_rt/mulo.zig").__mulosi4; + @export(__mulosi4, .{ .name = "__mulosi4", .linkage = linkage }); + const __mulodi4 = @import("compiler_rt/mulo.zig").__mulodi4; + @export(__mulodi4, .{ .name = "__mulodi4", .linkage = linkage }); + const __muloti4 = @import("compiler_rt/mulo.zig").__muloti4; + @export(__muloti4, .{ .name = "__muloti4", .linkage = linkage }); + if (builtin.os.tag == .windows) { // Default stack-probe functions emitted by LLVM if (is_mingw) { diff --git a/lib/std/special/compiler_rt/mulo.zig b/lib/std/special/compiler_rt/mulo.zig index 1e812c7e99..9fa5d3830b 100644 --- a/lib/std/special/compiler_rt/mulo.zig +++ b/lib/std/special/compiler_rt/mulo.zig @@ -7,60 +7,62 @@ const builtin = @import("builtin"); // return if a*b overflows => 1 else => 0 // see https://stackoverflow.com/a/26320664 for possible implementations -fn muloXi4_generic(comptime ST: type) fn (a: ST, b: ST, overflow: *c_int) callconv(.C) ST { - return struct { - fn f(a: ST, b: ST, overflow: *c_int) callconv(.C) ST { - @setRuntimeSafety(builtin.is_test); - const BSIZE = @bitSizeOf(ST); - comptime var UT = switch (ST) { - i32 => u32, - i64 => u64, - i128 => u128, - else => unreachable, - }; - const min = @bitCast(ST, @as(UT, 1 << (BSIZE - 1))); - const max = ~min; - overflow.* = 0; - const result = a *% b; +inline fn muloXi4_generic(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST { + @setRuntimeSafety(builtin.is_test); + const BSIZE = @bitSizeOf(ST); + comptime var UT = switch (ST) { + i32 => u32, + i64 => u64, + i128 => u128, + else => unreachable, + }; + const min = @bitCast(ST, @as(UT, 1 << (BSIZE - 1))); + const max = ~min; + overflow.* = 0; + const result = a *% b; - // edge cases - if (a == min) { - if (b != 0 and b != 1) overflow.* = 1; - return result; - } - if (b == min) { - if (a != 0 and a != 1) overflow.* = 1; - return result; - } + // edge cases + if (a == min) { + if (b != 0 and b != 1) overflow.* = 1; + return result; + } + if (b == min) { + if (a != 0 and a != 1) overflow.* = 1; + return result; + } - // take sign of x sx - const sa = a >> (BSIZE - 1); - const sb = b >> (BSIZE - 1); - // take absolute value of a and b via - // abs(x) = (x^sx)) - sx - const abs_a = (a ^ sa) -% sa; - const abs_b = (b ^ sb) -% sb; + // take sign of x sx + const sa = a >> (BSIZE - 1); + const sb = b >> (BSIZE - 1); + // take absolute value of a and b via + // abs(x) = (x^sx)) - sx + const abs_a = (a ^ sa) -% sa; + const abs_b = (b ^ sb) -% sb; - // unitary magnitude, cannot have overflow - if (abs_a < 2 or abs_b < 2) return result; + // unitary magnitude, cannot have overflow + if (abs_a < 2 or abs_b < 2) return result; - // compare the signs of operands - if ((a ^ b) >> (BSIZE - 1) != 0) { - if (abs_a > @divTrunc(max, abs_b)) overflow.* = 1; - } else { - if (abs_a > @divTrunc(min, -abs_b)) overflow.* = 1; - } + // compare the signs of operands + if ((a ^ b) >> (BSIZE - 1) != 0) { + if (abs_a > @divTrunc(max, abs_b)) overflow.* = 1; + } else { + if (abs_a > @divTrunc(min, -abs_b)) overflow.* = 1; + } - return result; - } - }.f; + return result; } -pub const __mulosi4 = muloXi4_generic(i32); +pub fn __mulosi4(a: i32, b: i32, overflow: *c_int) callconv(.C) i32 { + return muloXi4_generic(i32, a, b, overflow); +} -pub const __mulodi4 = muloXi4_generic(i64); +pub fn __mulodi4(a: i64, b: i64, overflow: *c_int) callconv(.C) i64 { + return muloXi4_generic(i64, a, b, overflow); +} -pub const __muloti4 = muloXi4_generic(i128); +pub fn __muloti4(a: i128, b: i128, overflow: *c_int) callconv(.C) i128 { + return muloXi4_generic(i128, a, b, overflow); +} test { _ = @import("mulosi4_test.zig");