diff options
| -rw-r--r-- | lib/compiler_rt.zig | 51 | ||||
| -rw-r--r-- | lib/compiler_rt/ceil.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/cos.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/exp.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/exp2.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/fabs.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/floor.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/fma.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/fmax.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/fmin.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/fmod.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/log.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/log10.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/log2.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/round.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/sin.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/sincos.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/sqrt.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/tan.zig | 11 | ||||
| -rw-r--r-- | lib/compiler_rt/trunc.zig | 11 | ||||
| -rw-r--r-- | src/Sema.zig | 9 | ||||
| -rw-r--r-- | src/stage1/ir.cpp | 6 | ||||
| -rw-r--r-- | test/behavior/cast.zig | 20 |
23 files changed, 271 insertions, 24 deletions
diff --git a/lib/compiler_rt.zig b/lib/compiler_rt.zig index 638bbcc695..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"), true); - 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("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("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("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, is_standard: 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, is_standard .{ 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 !is_standard) { + 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]; @@ -865,7 +868,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 }); } 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); 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 2f4e0aa0e7..62834e564d 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); +} |
