From 663b67783e3e140fcaf06747f4aa28b57259023c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 7 May 2022 17:41:20 -0700 Subject: [PATCH 1/3] compiler-rt: avoid symbol collisions with Windows libc closes #11600 --- lib/compiler_rt.zig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/compiler_rt.zig b/lib/compiler_rt.zig index 638bbcc695..2ed0bdc520 100644 --- a/lib/compiler_rt.zig +++ b/lib/compiler_rt.zig @@ -724,24 +724,24 @@ comptime { @export(_aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage }); } - mathExport("ceil", @import("./compiler_rt/ceil.zig"), true); + mathExport("ceil", @import("./compiler_rt/ceil.zig"), false); mathExport("cos", @import("./compiler_rt/cos.zig"), true); mathExport("exp", @import("./compiler_rt/exp.zig"), true); mathExport("exp2", @import("./compiler_rt/exp2.zig"), true); mathExport("fabs", @import("./compiler_rt/fabs.zig"), true); - mathExport("floor", @import("./compiler_rt/floor.zig"), true); + mathExport("floor", @import("./compiler_rt/floor.zig"), false); mathExport("fma", @import("./compiler_rt/fma.zig"), true); mathExport("fmax", @import("./compiler_rt/fmax.zig"), true); mathExport("fmin", @import("./compiler_rt/fmin.zig"), true); mathExport("fmod", @import("./compiler_rt/fmod.zig"), true); mathExport("log", @import("./compiler_rt/log.zig"), true); - mathExport("log10", @import("./compiler_rt/log10.zig"), true); + mathExport("log10", @import("./compiler_rt/log10.zig"), false); mathExport("log2", @import("./compiler_rt/log2.zig"), true); mathExport("round", @import("./compiler_rt/round.zig"), true); mathExport("sin", @import("./compiler_rt/sin.zig"), true); mathExport("sincos", @import("./compiler_rt/sincos.zig"), true); mathExport("sqrt", @import("./compiler_rt/sqrt.zig"), true); - mathExport("tan", @import("./compiler_rt/tan.zig"), false); + mathExport("tan", @import("./compiler_rt/tan.zig"), true); mathExport("trunc", @import("./compiler_rt/trunc.zig"), true); if (arch.isSPARC()) { @@ -825,7 +825,7 @@ comptime { } } -inline fn mathExport(double_name: []const u8, comptime import: type, is_standard: bool) void { +inline fn mathExport(double_name: []const u8, comptime import: type, win_libc_has_it: bool) void { const half_name = "__" ++ double_name ++ "h"; const half_fn = @field(import, half_name); const float_name = double_name ++ "f"; @@ -855,7 +855,7 @@ inline fn mathExport(double_name: []const u8, comptime import: type, is_standard // Weak aliases don't work on Windows, so we avoid exporting the `l` alias // on this platform for functions we know will collide. - if (builtin.os.tag != .windows or !builtin.link_libc or !is_standard) { + if (builtin.os.tag != .windows or !builtin.link_libc or !win_libc_has_it) { inline for (pairs) |pair| { const F = pair[0]; const func = pair[1]; @@ -865,7 +865,7 @@ inline fn mathExport(double_name: []const u8, comptime import: type, is_standard } } - if (is_ppc and is_standard) { + if (is_ppc) { // LLVM PPC backend lowers f128 ops with the suffix `f128` instead of `l`. @export(quad_fn, .{ .name = double_name ++ "f128", .linkage = linkage }); } From 6fde2fcd519cacdc44871fc1035b05afee072f44 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 8 May 2022 13:05:16 -0700 Subject: [PATCH 2/3] allow in-memory coercion of differently-named floats with same bits For example, this allows passing a `*c_longdouble` where a `*f80` is expected, provided that `c_longdouble` maps to `f80` for this target. --- src/Sema.zig | 9 +++++++++ src/stage1/ir.cpp | 6 ++++++ test/behavior/cast.zig | 20 ++++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/src/Sema.zig b/src/Sema.zig index 76edfbf2cd..2e7e5c9293 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -18673,6 +18673,15 @@ fn coerceInMemoryAllowed( } } + // Differently-named floats with the same number of bits. + if (dest_ty.zigTypeTag() == .Float and src_ty.zigTypeTag() == .Float) { + const dest_bits = dest_ty.floatBits(target); + const src_bits = src_ty.floatBits(target); + if (dest_bits == src_bits) { + return .ok; + } + } + // Pointers / Pointer-like Optionals var dest_buf: Type.Payload.ElemType = undefined; var src_buf: Type.Payload.ElemType = undefined; diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index f7ab5e12fa..ee195680cd 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -4480,6 +4480,12 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted return result; } + if (wanted_type->id == ZigTypeIdFloat && actual_type->id == ZigTypeIdFloat) { + if (wanted_type->data.floating.bit_count == actual_type->data.floating.bit_count) { + return result; + } + } + if (wanted_type->id == ZigTypeIdVector && actual_type->id == ZigTypeIdVector) { if (actual_type->data.vector.len != wanted_type->data.vector.len) { result.id = ConstCastResultIdVectorLength; diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 416c7914e7..231fa25b2d 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -1426,3 +1426,23 @@ test "pointer to empty struct literal to mutable slice" { var x: []i32 = &.{}; try expect(x.len == 0); } + +test "coerce between pointers of compatible differently-named floats" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const F = switch (@typeInfo(c_longdouble).Float.bits) { + 16 => f16, + 32 => f32, + 64 => f64, + 80 => f80, + 128 => f128, + else => @compileError("unreachable"), + }; + var f1: F = 12.34; + var f2: *c_longdouble = &f1; + f2.* += 1; + try expect(f1 == @as(F, 12.34) + 1); +} From cd019ee502d6792c1615b0fab10827db419beab4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 8 May 2022 13:06:21 -0700 Subject: [PATCH 3/3] compiler_rt: avoid weak aliases on Windows When exporting math functions for Windows, we provide weak exports of 'l' variants rather than weak aliases. We still use aliases on other operating systems so that the 'l' variants have one less jump instruction in this case. --- lib/compiler_rt.zig | 49 ++++++++++++++++++++------------------ lib/compiler_rt/ceil.zig | 11 +++++++++ lib/compiler_rt/cos.zig | 11 +++++++++ lib/compiler_rt/exp.zig | 11 +++++++++ lib/compiler_rt/exp2.zig | 11 +++++++++ lib/compiler_rt/fabs.zig | 11 +++++++++ lib/compiler_rt/floor.zig | 11 +++++++++ lib/compiler_rt/fma.zig | 11 +++++++++ lib/compiler_rt/fmax.zig | 11 +++++++++ lib/compiler_rt/fmin.zig | 11 +++++++++ lib/compiler_rt/fmod.zig | 11 +++++++++ lib/compiler_rt/log.zig | 11 +++++++++ lib/compiler_rt/log10.zig | 11 +++++++++ lib/compiler_rt/log2.zig | 11 +++++++++ lib/compiler_rt/round.zig | 11 +++++++++ lib/compiler_rt/sin.zig | 11 +++++++++ lib/compiler_rt/sincos.zig | 11 +++++++++ lib/compiler_rt/sqrt.zig | 11 +++++++++ lib/compiler_rt/tan.zig | 11 +++++++++ lib/compiler_rt/trunc.zig | 11 +++++++++ 20 files changed, 235 insertions(+), 23 deletions(-) diff --git a/lib/compiler_rt.zig b/lib/compiler_rt.zig index 2ed0bdc520..fdf5940702 100644 --- a/lib/compiler_rt.zig +++ b/lib/compiler_rt.zig @@ -724,25 +724,25 @@ comptime { @export(_aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage }); } - mathExport("ceil", @import("./compiler_rt/ceil.zig"), false); - mathExport("cos", @import("./compiler_rt/cos.zig"), true); - mathExport("exp", @import("./compiler_rt/exp.zig"), true); - mathExport("exp2", @import("./compiler_rt/exp2.zig"), true); - mathExport("fabs", @import("./compiler_rt/fabs.zig"), true); - mathExport("floor", @import("./compiler_rt/floor.zig"), false); - mathExport("fma", @import("./compiler_rt/fma.zig"), true); - mathExport("fmax", @import("./compiler_rt/fmax.zig"), true); - mathExport("fmin", @import("./compiler_rt/fmin.zig"), true); - mathExport("fmod", @import("./compiler_rt/fmod.zig"), true); - mathExport("log", @import("./compiler_rt/log.zig"), true); - mathExport("log10", @import("./compiler_rt/log10.zig"), false); - mathExport("log2", @import("./compiler_rt/log2.zig"), true); - mathExport("round", @import("./compiler_rt/round.zig"), true); - mathExport("sin", @import("./compiler_rt/sin.zig"), true); - mathExport("sincos", @import("./compiler_rt/sincos.zig"), true); - mathExport("sqrt", @import("./compiler_rt/sqrt.zig"), true); - mathExport("tan", @import("./compiler_rt/tan.zig"), true); - mathExport("trunc", @import("./compiler_rt/trunc.zig"), true); + mathExport("ceil", @import("./compiler_rt/ceil.zig")); + mathExport("cos", @import("./compiler_rt/cos.zig")); + mathExport("exp", @import("./compiler_rt/exp.zig")); + mathExport("exp2", @import("./compiler_rt/exp2.zig")); + mathExport("fabs", @import("./compiler_rt/fabs.zig")); + mathExport("floor", @import("./compiler_rt/floor.zig")); + mathExport("fma", @import("./compiler_rt/fma.zig")); + mathExport("fmax", @import("./compiler_rt/fmax.zig")); + mathExport("fmin", @import("./compiler_rt/fmin.zig")); + mathExport("fmod", @import("./compiler_rt/fmod.zig")); + mathExport("log", @import("./compiler_rt/log.zig")); + mathExport("log10", @import("./compiler_rt/log10.zig")); + mathExport("log2", @import("./compiler_rt/log2.zig")); + mathExport("round", @import("./compiler_rt/round.zig")); + mathExport("sin", @import("./compiler_rt/sin.zig")); + mathExport("sincos", @import("./compiler_rt/sincos.zig")); + mathExport("sqrt", @import("./compiler_rt/sqrt.zig")); + mathExport("tan", @import("./compiler_rt/tan.zig")); + mathExport("trunc", @import("./compiler_rt/trunc.zig")); if (arch.isSPARC()) { // SPARC systems use a different naming scheme @@ -825,7 +825,7 @@ comptime { } } -inline fn mathExport(double_name: []const u8, comptime import: type, win_libc_has_it: bool) void { +inline fn mathExport(double_name: []const u8, comptime import: type) void { const half_name = "__" ++ double_name ++ "h"; const half_fn = @field(import, half_name); const float_name = double_name ++ "f"; @@ -853,9 +853,12 @@ inline fn mathExport(double_name: []const u8, comptime import: type, win_libc_ha .{ f128, quad_fn }, }; - // Weak aliases don't work on Windows, so we avoid exporting the `l` alias - // on this platform for functions we know will collide. - if (builtin.os.tag != .windows or !builtin.link_libc or !win_libc_has_it) { + if (builtin.os.tag == .windows) { + // Weak aliases don't work on Windows, so we have to provide the 'l' variants + // as additional function definitions that jump to the real definition. + const long_double_fn = @field(import, long_double_name); + @export(long_double_fn, .{ .name = long_double_name, .linkage = linkage }); + } else { inline for (pairs) |pair| { const F = pair[0]; const func = pair[1]; diff --git a/lib/compiler_rt/ceil.zig b/lib/compiler_rt/ceil.zig index c7087a2c3a..06020ea8f8 100644 --- a/lib/compiler_rt/ceil.zig +++ b/lib/compiler_rt/ceil.zig @@ -111,6 +111,17 @@ pub fn ceilq(x: f128) callconv(.C) f128 { } } +pub fn ceill(x: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __ceilh(x), + 32 => return ceilf(x), + 64 => return ceil(x), + 80 => return __ceilx(x), + 128 => return ceilq(x), + else => @compileError("unreachable"), + } +} + test "ceil32" { try expect(ceilf(1.3) == 2.0); try expect(ceilf(-1.3) == -1.0); diff --git a/lib/compiler_rt/cos.zig b/lib/compiler_rt/cos.zig index 957e5f9c91..e01f458243 100644 --- a/lib/compiler_rt/cos.zig +++ b/lib/compiler_rt/cos.zig @@ -107,6 +107,17 @@ pub fn cosq(a: f128) callconv(.C) f128 { return cos(@floatCast(f64, a)); } +pub fn cosl(x: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __cosh(x), + 32 => return cosf(x), + 64 => return cos(x), + 80 => return __cosx(x), + 128 => return cosq(x), + else => @compileError("unreachable"), + } +} + test "cos32" { const epsilon = 0.00001; diff --git a/lib/compiler_rt/exp.zig b/lib/compiler_rt/exp.zig index 0f129dfd4c..a2c5d0e550 100644 --- a/lib/compiler_rt/exp.zig +++ b/lib/compiler_rt/exp.zig @@ -182,6 +182,17 @@ pub fn expq(a: f128) callconv(.C) f128 { return exp(@floatCast(f64, a)); } +pub fn expl(x: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __exph(x), + 32 => return expf(x), + 64 => return exp(x), + 80 => return __expx(x), + 128 => return expq(x), + else => @compileError("unreachable"), + } +} + test "exp32" { const epsilon = 0.000001; diff --git a/lib/compiler_rt/exp2.zig b/lib/compiler_rt/exp2.zig index 53432a831d..cbcb53c99f 100644 --- a/lib/compiler_rt/exp2.zig +++ b/lib/compiler_rt/exp2.zig @@ -149,6 +149,17 @@ pub fn exp2q(x: f128) callconv(.C) f128 { return exp2(@floatCast(f64, x)); } +pub fn exp2l(x: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __exp2h(x), + 32 => return exp2f(x), + 64 => return exp2(x), + 80 => return __exp2x(x), + 128 => return exp2q(x), + else => @compileError("unreachable"), + } +} + const exp2ft = [_]f64{ 0x1.6a09e667f3bcdp-1, 0x1.7a11473eb0187p-1, diff --git a/lib/compiler_rt/fabs.zig b/lib/compiler_rt/fabs.zig index fbef81fc9a..396fdd46b7 100644 --- a/lib/compiler_rt/fabs.zig +++ b/lib/compiler_rt/fabs.zig @@ -20,6 +20,17 @@ pub fn fabsq(a: f128) callconv(.C) f128 { return generic_fabs(a); } +pub fn fabsl(x: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __fabsh(x), + 32 => return fabsf(x), + 64 => return fabs(x), + 80 => return __fabsx(x), + 128 => return fabsq(x), + else => @compileError("unreachable"), + } +} + inline fn generic_fabs(x: anytype) @TypeOf(x) { const T = @TypeOf(x); const TBits = std.meta.Int(.unsigned, @typeInfo(T).Float.bits); diff --git a/lib/compiler_rt/floor.zig b/lib/compiler_rt/floor.zig index f6df164b58..783898fca7 100644 --- a/lib/compiler_rt/floor.zig +++ b/lib/compiler_rt/floor.zig @@ -141,6 +141,17 @@ pub fn floorq(x: f128) callconv(.C) f128 { } } +pub fn floorl(x: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __floorh(x), + 32 => return floorf(x), + 64 => return floor(x), + 80 => return __floorx(x), + 128 => return floorq(x), + else => @compileError("unreachable"), + } +} + test "floor16" { try expect(__floorh(1.3) == 1.0); try expect(__floorh(-1.3) == -2.0); diff --git a/lib/compiler_rt/fma.zig b/lib/compiler_rt/fma.zig index 4c603bf095..7a39a4c9a0 100644 --- a/lib/compiler_rt/fma.zig +++ b/lib/compiler_rt/fma.zig @@ -135,6 +135,17 @@ pub fn fmaq(x: f128, y: f128, z: f128) callconv(.C) f128 { } } +pub fn fmal(x: c_longdouble, y: c_longdouble, z: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __fmah(x, y, z), + 32 => return fmaf(x, y, z), + 64 => return fma(x, y, z), + 80 => return __fmax(x, y, z), + 128 => return fmaq(x, y, z), + else => @compileError("unreachable"), + } +} + const dd = struct { hi: f64, lo: f64, diff --git a/lib/compiler_rt/fmax.zig b/lib/compiler_rt/fmax.zig index a5bd68cd74..defc935afc 100644 --- a/lib/compiler_rt/fmax.zig +++ b/lib/compiler_rt/fmax.zig @@ -21,6 +21,17 @@ pub fn fmaxq(x: f128, y: f128) callconv(.C) f128 { return generic_fmax(f128, x, y); } +pub fn fmaxl(x: c_longdouble, y: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __fmaxh(x, y), + 32 => return fmaxf(x, y), + 64 => return fmax(x, y), + 80 => return __fmaxx(x, y), + 128 => return fmaxq(x, y), + else => @compileError("unreachable"), + } +} + inline fn generic_fmax(comptime T: type, x: T, y: T) T { if (math.isNan(x)) return y; diff --git a/lib/compiler_rt/fmin.zig b/lib/compiler_rt/fmin.zig index cc4dbf082b..e93300bd4b 100644 --- a/lib/compiler_rt/fmin.zig +++ b/lib/compiler_rt/fmin.zig @@ -21,6 +21,17 @@ pub fn fminq(x: f128, y: f128) callconv(.C) f128 { return generic_fmin(f128, x, y); } +pub fn fminl(x: c_longdouble, y: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __fminh(x, y), + 32 => return fminf(x, y), + 64 => return fmin(x, y), + 80 => return __fminx(x, y), + 128 => return fminq(x, y), + else => @compileError("unreachable"), + } +} + inline fn generic_fmin(comptime T: type, x: T, y: T) T { if (math.isNan(x)) return y; diff --git a/lib/compiler_rt/fmod.zig b/lib/compiler_rt/fmod.zig index 28e0df3d6b..5d413ca37d 100644 --- a/lib/compiler_rt/fmod.zig +++ b/lib/compiler_rt/fmod.zig @@ -237,6 +237,17 @@ pub fn fmodq(a: f128, b: f128) callconv(.C) f128 { return amod; } +pub fn fmodl(a: c_longdouble, b: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __fmodh(a, b), + 32 => return fmodf(a, b), + 64 => return fmod(a, b), + 80 => return __fmodx(a, b), + 128 => return fmodq(a, b), + else => @compileError("unreachable"), + } +} + inline fn generic_fmod(comptime T: type, x: T, y: T) T { @setRuntimeSafety(false); diff --git a/lib/compiler_rt/log.zig b/lib/compiler_rt/log.zig index 8b09baac2e..6e705dae60 100644 --- a/lib/compiler_rt/log.zig +++ b/lib/compiler_rt/log.zig @@ -131,6 +131,17 @@ pub fn logq(a: f128) callconv(.C) f128 { return log(@floatCast(f64, a)); } +pub fn logl(x: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __logh(x), + 32 => return logf(x), + 64 => return log(x), + 80 => return __logx(x), + 128 => return logq(x), + else => @compileError("unreachable"), + } +} + test "ln32" { const epsilon = 0.000001; diff --git a/lib/compiler_rt/log10.zig b/lib/compiler_rt/log10.zig index ce06d8c649..47499d2739 100644 --- a/lib/compiler_rt/log10.zig +++ b/lib/compiler_rt/log10.zig @@ -159,6 +159,17 @@ pub fn log10q(a: f128) callconv(.C) f128 { return log10(@floatCast(f64, a)); } +pub fn log10l(x: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __log10h(x), + 32 => return log10f(x), + 64 => return log10(x), + 80 => return __log10x(x), + 128 => return log10q(x), + else => @compileError("unreachable"), + } +} + test "log10_32" { const epsilon = 0.000001; diff --git a/lib/compiler_rt/log2.zig b/lib/compiler_rt/log2.zig index 2c2d620c3d..53f35c9a80 100644 --- a/lib/compiler_rt/log2.zig +++ b/lib/compiler_rt/log2.zig @@ -150,6 +150,17 @@ pub fn log2q(a: f128) callconv(.C) f128 { return math.log2(a); } +pub fn log2l(x: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __log2h(x), + 32 => return log2f(x), + 64 => return log2(x), + 80 => return __log2x(x), + 128 => return log2q(x), + else => @compileError("unreachable"), + } +} + test "log2_32" { const epsilon = 0.000001; diff --git a/lib/compiler_rt/round.zig b/lib/compiler_rt/round.zig index 99201efcf8..4f3266e00c 100644 --- a/lib/compiler_rt/round.zig +++ b/lib/compiler_rt/round.zig @@ -123,6 +123,17 @@ pub fn roundq(x_: f128) callconv(.C) f128 { } } +pub fn roundl(x: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __roundh(x), + 32 => return roundf(x), + 64 => return round(x), + 80 => return __roundx(x), + 128 => return roundq(x), + else => @compileError("unreachable"), + } +} + test "round32" { try expect(roundf(1.3) == 1.0); try expect(roundf(-1.3) == -1.0); diff --git a/lib/compiler_rt/sin.zig b/lib/compiler_rt/sin.zig index 3d5572a59f..20259bc309 100644 --- a/lib/compiler_rt/sin.zig +++ b/lib/compiler_rt/sin.zig @@ -111,6 +111,17 @@ pub fn sinq(x: f128) callconv(.C) f128 { return sin(@floatCast(f64, x)); } +pub fn sinl(x: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __sinh(x), + 32 => return sinf(x), + 64 => return sin(x), + 80 => return __sinx(x), + 128 => return sinq(x), + else => @compileError("unreachable"), + } +} + test "sin32" { const epsilon = 0.00001; diff --git a/lib/compiler_rt/sincos.zig b/lib/compiler_rt/sincos.zig index 31ebd0d1d0..8bc5b83ee5 100644 --- a/lib/compiler_rt/sincos.zig +++ b/lib/compiler_rt/sincos.zig @@ -181,6 +181,17 @@ pub fn sincosq(x: f128, r_sin: *f128, r_cos: *f128) callconv(.C) void { r_cos.* = small_cos; } +pub fn sincosl(x: c_longdouble, r_sin: *c_longdouble, r_cos: *c_longdouble) callconv(.C) void { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __sincosh(x, r_sin, r_cos), + 32 => return sincosf(x, r_sin, r_cos), + 64 => return sincos(x, r_sin, r_cos), + 80 => return __sincosx(x, r_sin, r_cos), + 128 => return sincosq(x, r_sin, r_cos), + else => @compileError("unreachable"), + } +} + const rem_pio2_generic = @compileError("TODO"); /// Ported from musl sincosl.c. Needs the following dependencies to be complete: diff --git a/lib/compiler_rt/sqrt.zig b/lib/compiler_rt/sqrt.zig index ba07beb86e..8d43949f99 100644 --- a/lib/compiler_rt/sqrt.zig +++ b/lib/compiler_rt/sqrt.zig @@ -225,6 +225,17 @@ pub fn sqrtq(x: f128) callconv(.C) f128 { return sqrt(@floatCast(f64, x)); } +pub fn sqrtl(x: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __sqrth(x), + 32 => return sqrtf(x), + 64 => return sqrt(x), + 80 => return __sqrtx(x), + 128 => return sqrtq(x), + else => @compileError("unreachable"), + } +} + test "sqrtf" { const V = [_]f32{ 0.0, diff --git a/lib/compiler_rt/tan.zig b/lib/compiler_rt/tan.zig index d99f00b99e..d37022d918 100644 --- a/lib/compiler_rt/tan.zig +++ b/lib/compiler_rt/tan.zig @@ -96,6 +96,17 @@ pub fn tanq(x: f128) callconv(.C) f128 { return tan(@floatCast(f64, x)); } +pub fn tanl(x: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __tanh(x), + 32 => return tanf(x), + 64 => return tan(x), + 80 => return __tanx(x), + 128 => return tanq(x), + else => @compileError("unreachable"), + } +} + test "tan" { try expect(tan(@as(f32, 0.0)) == tanf(0.0)); try expect(tan(@as(f64, 0.0)) == tan(0.0)); diff --git a/lib/compiler_rt/trunc.zig b/lib/compiler_rt/trunc.zig index 5406f9a02d..d00df60d99 100644 --- a/lib/compiler_rt/trunc.zig +++ b/lib/compiler_rt/trunc.zig @@ -81,6 +81,17 @@ pub fn truncq(x: f128) callconv(.C) f128 { } } +pub fn truncl(x: c_longdouble) callconv(.C) c_longdouble { + switch (@typeInfo(c_longdouble).Float.bits) { + 16 => return __trunch(x), + 32 => return truncf(x), + 64 => return trunc(x), + 80 => return __truncx(x), + 128 => return truncq(x), + else => @compileError("unreachable"), + } +} + test "trunc32" { try expect(truncf(1.3) == 1.0); try expect(truncf(-1.3) == -1.0);