authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-08 19:29:21-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-05-08 19:29:21-04:00
logd7f8368da86241f47e97257e737b6fb14bf5f773
tree260d9d2d3aa68a96d1ea7594234fae0c3b90640e
parentea3f5905f0635d0c0cb3983ba5ca6c92859e9d81
parentcd019ee502d6792c1615b0fab10827db419beab4
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11609 from ziglang/win-compiler-rt

compiler-rt: avoid symbol collisions with Windows libc

23 files changed, 271 insertions(+), 24 deletions(-)

lib/compiler_rt.zig+27-24
......@@ -724,25 +724,25 @@ comptime {
724724 @export(_aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage });
725725 }
726726
727 mathExport("ceil", @import("./compiler_rt/ceil.zig"), true);
728 mathExport("cos", @import("./compiler_rt/cos.zig"), true);
729 mathExport("exp", @import("./compiler_rt/exp.zig"), true);
730 mathExport("exp2", @import("./compiler_rt/exp2.zig"), true);
731 mathExport("fabs", @import("./compiler_rt/fabs.zig"), true);
732 mathExport("floor", @import("./compiler_rt/floor.zig"), true);
733 mathExport("fma", @import("./compiler_rt/fma.zig"), true);
734 mathExport("fmax", @import("./compiler_rt/fmax.zig"), true);
735 mathExport("fmin", @import("./compiler_rt/fmin.zig"), true);
736 mathExport("fmod", @import("./compiler_rt/fmod.zig"), true);
737 mathExport("log", @import("./compiler_rt/log.zig"), true);
738 mathExport("log10", @import("./compiler_rt/log10.zig"), true);
739 mathExport("log2", @import("./compiler_rt/log2.zig"), true);
740 mathExport("round", @import("./compiler_rt/round.zig"), true);
741 mathExport("sin", @import("./compiler_rt/sin.zig"), true);
742 mathExport("sincos", @import("./compiler_rt/sincos.zig"), true);
743 mathExport("sqrt", @import("./compiler_rt/sqrt.zig"), true);
744 mathExport("tan", @import("./compiler_rt/tan.zig"), false);
745 mathExport("trunc", @import("./compiler_rt/trunc.zig"), true);
727 mathExport("ceil", @import("./compiler_rt/ceil.zig"));
728 mathExport("cos", @import("./compiler_rt/cos.zig"));
729 mathExport("exp", @import("./compiler_rt/exp.zig"));
730 mathExport("exp2", @import("./compiler_rt/exp2.zig"));
731 mathExport("fabs", @import("./compiler_rt/fabs.zig"));
732 mathExport("floor", @import("./compiler_rt/floor.zig"));
733 mathExport("fma", @import("./compiler_rt/fma.zig"));
734 mathExport("fmax", @import("./compiler_rt/fmax.zig"));
735 mathExport("fmin", @import("./compiler_rt/fmin.zig"));
736 mathExport("fmod", @import("./compiler_rt/fmod.zig"));
737 mathExport("log", @import("./compiler_rt/log.zig"));
738 mathExport("log10", @import("./compiler_rt/log10.zig"));
739 mathExport("log2", @import("./compiler_rt/log2.zig"));
740 mathExport("round", @import("./compiler_rt/round.zig"));
741 mathExport("sin", @import("./compiler_rt/sin.zig"));
742 mathExport("sincos", @import("./compiler_rt/sincos.zig"));
743 mathExport("sqrt", @import("./compiler_rt/sqrt.zig"));
744 mathExport("tan", @import("./compiler_rt/tan.zig"));
745 mathExport("trunc", @import("./compiler_rt/trunc.zig"));
746746
747747 if (arch.isSPARC()) {
748748 // SPARC systems use a different naming scheme
......@@ -825,7 +825,7 @@ comptime {
825825 }
826826}
827827
828inline fn mathExport(double_name: []const u8, comptime import: type, is_standard: bool) void {
828inline fn mathExport(double_name: []const u8, comptime import: type) void {
829829 const half_name = "__" ++ double_name ++ "h";
830830 const half_fn = @field(import, half_name);
831831 const float_name = double_name ++ "f";
......@@ -853,9 +853,12 @@ inline fn mathExport(double_name: []const u8, comptime import: type, is_standard
853853 .{ f128, quad_fn },
854854 };
855855
856 // Weak aliases don't work on Windows, so we avoid exporting the `l` alias
857 // on this platform for functions we know will collide.
858 if (builtin.os.tag != .windows or !builtin.link_libc or !is_standard) {
856 if (builtin.os.tag == .windows) {
857 // Weak aliases don't work on Windows, so we have to provide the 'l' variants
858 // as additional function definitions that jump to the real definition.
859 const long_double_fn = @field(import, long_double_name);
860 @export(long_double_fn, .{ .name = long_double_name, .linkage = linkage });
861 } else {
859862 inline for (pairs) |pair| {
860863 const F = pair[0];
861864 const func = pair[1];
......@@ -865,7 +868,7 @@ inline fn mathExport(double_name: []const u8, comptime import: type, is_standard
865868 }
866869 }
867870
868 if (is_ppc and is_standard) {
871 if (is_ppc) {
869872 // LLVM PPC backend lowers f128 ops with the suffix `f128` instead of `l`.
870873 @export(quad_fn, .{ .name = double_name ++ "f128", .linkage = linkage });
871874 }
lib/compiler_rt/ceil.zig+11
......@@ -111,6 +111,17 @@ pub fn ceilq(x: f128) callconv(.C) f128 {
111111 }
112112}
113113
114pub fn ceill(x: c_longdouble) callconv(.C) c_longdouble {
115 switch (@typeInfo(c_longdouble).Float.bits) {
116 16 => return __ceilh(x),
117 32 => return ceilf(x),
118 64 => return ceil(x),
119 80 => return __ceilx(x),
120 128 => return ceilq(x),
121 else => @compileError("unreachable"),
122 }
123}
124
114125test "ceil32" {
115126 try expect(ceilf(1.3) == 2.0);
116127 try expect(ceilf(-1.3) == -1.0);
lib/compiler_rt/cos.zig+11
......@@ -107,6 +107,17 @@ pub fn cosq(a: f128) callconv(.C) f128 {
107107 return cos(@floatCast(f64, a));
108108}
109109
110pub fn cosl(x: c_longdouble) callconv(.C) c_longdouble {
111 switch (@typeInfo(c_longdouble).Float.bits) {
112 16 => return __cosh(x),
113 32 => return cosf(x),
114 64 => return cos(x),
115 80 => return __cosx(x),
116 128 => return cosq(x),
117 else => @compileError("unreachable"),
118 }
119}
120
110121test "cos32" {
111122 const epsilon = 0.00001;
112123
lib/compiler_rt/exp.zig+11
......@@ -182,6 +182,17 @@ pub fn expq(a: f128) callconv(.C) f128 {
182182 return exp(@floatCast(f64, a));
183183}
184184
185pub fn expl(x: c_longdouble) callconv(.C) c_longdouble {
186 switch (@typeInfo(c_longdouble).Float.bits) {
187 16 => return __exph(x),
188 32 => return expf(x),
189 64 => return exp(x),
190 80 => return __expx(x),
191 128 => return expq(x),
192 else => @compileError("unreachable"),
193 }
194}
195
185196test "exp32" {
186197 const epsilon = 0.000001;
187198
lib/compiler_rt/exp2.zig+11
......@@ -149,6 +149,17 @@ pub fn exp2q(x: f128) callconv(.C) f128 {
149149 return exp2(@floatCast(f64, x));
150150}
151151
152pub fn exp2l(x: c_longdouble) callconv(.C) c_longdouble {
153 switch (@typeInfo(c_longdouble).Float.bits) {
154 16 => return __exp2h(x),
155 32 => return exp2f(x),
156 64 => return exp2(x),
157 80 => return __exp2x(x),
158 128 => return exp2q(x),
159 else => @compileError("unreachable"),
160 }
161}
162
152163const exp2ft = [_]f64{
153164 0x1.6a09e667f3bcdp-1,
154165 0x1.7a11473eb0187p-1,
lib/compiler_rt/fabs.zig+11
......@@ -20,6 +20,17 @@ pub fn fabsq(a: f128) callconv(.C) f128 {
2020 return generic_fabs(a);
2121}
2222
23pub fn fabsl(x: c_longdouble) callconv(.C) c_longdouble {
24 switch (@typeInfo(c_longdouble).Float.bits) {
25 16 => return __fabsh(x),
26 32 => return fabsf(x),
27 64 => return fabs(x),
28 80 => return __fabsx(x),
29 128 => return fabsq(x),
30 else => @compileError("unreachable"),
31 }
32}
33
2334inline fn generic_fabs(x: anytype) @TypeOf(x) {
2435 const T = @TypeOf(x);
2536 const TBits = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
lib/compiler_rt/floor.zig+11
......@@ -141,6 +141,17 @@ pub fn floorq(x: f128) callconv(.C) f128 {
141141 }
142142}
143143
144pub fn floorl(x: c_longdouble) callconv(.C) c_longdouble {
145 switch (@typeInfo(c_longdouble).Float.bits) {
146 16 => return __floorh(x),
147 32 => return floorf(x),
148 64 => return floor(x),
149 80 => return __floorx(x),
150 128 => return floorq(x),
151 else => @compileError("unreachable"),
152 }
153}
154
144155test "floor16" {
145156 try expect(__floorh(1.3) == 1.0);
146157 try expect(__floorh(-1.3) == -2.0);
lib/compiler_rt/fma.zig+11
......@@ -135,6 +135,17 @@ pub fn fmaq(x: f128, y: f128, z: f128) callconv(.C) f128 {
135135 }
136136}
137137
138pub fn fmal(x: c_longdouble, y: c_longdouble, z: c_longdouble) callconv(.C) c_longdouble {
139 switch (@typeInfo(c_longdouble).Float.bits) {
140 16 => return __fmah(x, y, z),
141 32 => return fmaf(x, y, z),
142 64 => return fma(x, y, z),
143 80 => return __fmax(x, y, z),
144 128 => return fmaq(x, y, z),
145 else => @compileError("unreachable"),
146 }
147}
148
138149const dd = struct {
139150 hi: f64,
140151 lo: f64,
lib/compiler_rt/fmax.zig+11
......@@ -21,6 +21,17 @@ pub fn fmaxq(x: f128, y: f128) callconv(.C) f128 {
2121 return generic_fmax(f128, x, y);
2222}
2323
24pub fn fmaxl(x: c_longdouble, y: c_longdouble) callconv(.C) c_longdouble {
25 switch (@typeInfo(c_longdouble).Float.bits) {
26 16 => return __fmaxh(x, y),
27 32 => return fmaxf(x, y),
28 64 => return fmax(x, y),
29 80 => return __fmaxx(x, y),
30 128 => return fmaxq(x, y),
31 else => @compileError("unreachable"),
32 }
33}
34
2435inline fn generic_fmax(comptime T: type, x: T, y: T) T {
2536 if (math.isNan(x))
2637 return y;
lib/compiler_rt/fmin.zig+11
......@@ -21,6 +21,17 @@ pub fn fminq(x: f128, y: f128) callconv(.C) f128 {
2121 return generic_fmin(f128, x, y);
2222}
2323
24pub fn fminl(x: c_longdouble, y: c_longdouble) callconv(.C) c_longdouble {
25 switch (@typeInfo(c_longdouble).Float.bits) {
26 16 => return __fminh(x, y),
27 32 => return fminf(x, y),
28 64 => return fmin(x, y),
29 80 => return __fminx(x, y),
30 128 => return fminq(x, y),
31 else => @compileError("unreachable"),
32 }
33}
34
2435inline fn generic_fmin(comptime T: type, x: T, y: T) T {
2536 if (math.isNan(x))
2637 return y;
lib/compiler_rt/fmod.zig+11
......@@ -237,6 +237,17 @@ pub fn fmodq(a: f128, b: f128) callconv(.C) f128 {
237237 return amod;
238238}
239239
240pub fn fmodl(a: c_longdouble, b: c_longdouble) callconv(.C) c_longdouble {
241 switch (@typeInfo(c_longdouble).Float.bits) {
242 16 => return __fmodh(a, b),
243 32 => return fmodf(a, b),
244 64 => return fmod(a, b),
245 80 => return __fmodx(a, b),
246 128 => return fmodq(a, b),
247 else => @compileError("unreachable"),
248 }
249}
250
240251inline fn generic_fmod(comptime T: type, x: T, y: T) T {
241252 @setRuntimeSafety(false);
242253
lib/compiler_rt/log.zig+11
......@@ -131,6 +131,17 @@ pub fn logq(a: f128) callconv(.C) f128 {
131131 return log(@floatCast(f64, a));
132132}
133133
134pub fn logl(x: c_longdouble) callconv(.C) c_longdouble {
135 switch (@typeInfo(c_longdouble).Float.bits) {
136 16 => return __logh(x),
137 32 => return logf(x),
138 64 => return log(x),
139 80 => return __logx(x),
140 128 => return logq(x),
141 else => @compileError("unreachable"),
142 }
143}
144
134145test "ln32" {
135146 const epsilon = 0.000001;
136147
lib/compiler_rt/log10.zig+11
......@@ -159,6 +159,17 @@ pub fn log10q(a: f128) callconv(.C) f128 {
159159 return log10(@floatCast(f64, a));
160160}
161161
162pub fn log10l(x: c_longdouble) callconv(.C) c_longdouble {
163 switch (@typeInfo(c_longdouble).Float.bits) {
164 16 => return __log10h(x),
165 32 => return log10f(x),
166 64 => return log10(x),
167 80 => return __log10x(x),
168 128 => return log10q(x),
169 else => @compileError("unreachable"),
170 }
171}
172
162173test "log10_32" {
163174 const epsilon = 0.000001;
164175
lib/compiler_rt/log2.zig+11
......@@ -150,6 +150,17 @@ pub fn log2q(a: f128) callconv(.C) f128 {
150150 return math.log2(a);
151151}
152152
153pub fn log2l(x: c_longdouble) callconv(.C) c_longdouble {
154 switch (@typeInfo(c_longdouble).Float.bits) {
155 16 => return __log2h(x),
156 32 => return log2f(x),
157 64 => return log2(x),
158 80 => return __log2x(x),
159 128 => return log2q(x),
160 else => @compileError("unreachable"),
161 }
162}
163
153164test "log2_32" {
154165 const epsilon = 0.000001;
155166
lib/compiler_rt/round.zig+11
......@@ -123,6 +123,17 @@ pub fn roundq(x_: f128) callconv(.C) f128 {
123123 }
124124}
125125
126pub fn roundl(x: c_longdouble) callconv(.C) c_longdouble {
127 switch (@typeInfo(c_longdouble).Float.bits) {
128 16 => return __roundh(x),
129 32 => return roundf(x),
130 64 => return round(x),
131 80 => return __roundx(x),
132 128 => return roundq(x),
133 else => @compileError("unreachable"),
134 }
135}
136
126137test "round32" {
127138 try expect(roundf(1.3) == 1.0);
128139 try expect(roundf(-1.3) == -1.0);
lib/compiler_rt/sin.zig+11
......@@ -111,6 +111,17 @@ pub fn sinq(x: f128) callconv(.C) f128 {
111111 return sin(@floatCast(f64, x));
112112}
113113
114pub fn sinl(x: c_longdouble) callconv(.C) c_longdouble {
115 switch (@typeInfo(c_longdouble).Float.bits) {
116 16 => return __sinh(x),
117 32 => return sinf(x),
118 64 => return sin(x),
119 80 => return __sinx(x),
120 128 => return sinq(x),
121 else => @compileError("unreachable"),
122 }
123}
124
114125test "sin32" {
115126 const epsilon = 0.00001;
116127
lib/compiler_rt/sincos.zig+11
......@@ -181,6 +181,17 @@ pub fn sincosq(x: f128, r_sin: *f128, r_cos: *f128) callconv(.C) void {
181181 r_cos.* = small_cos;
182182}
183183
184pub fn sincosl(x: c_longdouble, r_sin: *c_longdouble, r_cos: *c_longdouble) callconv(.C) void {
185 switch (@typeInfo(c_longdouble).Float.bits) {
186 16 => return __sincosh(x, r_sin, r_cos),
187 32 => return sincosf(x, r_sin, r_cos),
188 64 => return sincos(x, r_sin, r_cos),
189 80 => return __sincosx(x, r_sin, r_cos),
190 128 => return sincosq(x, r_sin, r_cos),
191 else => @compileError("unreachable"),
192 }
193}
194
184195const rem_pio2_generic = @compileError("TODO");
185196
186197/// Ported from musl sincosl.c. Needs the following dependencies to be complete:
lib/compiler_rt/sqrt.zig+11
......@@ -225,6 +225,17 @@ pub fn sqrtq(x: f128) callconv(.C) f128 {
225225 return sqrt(@floatCast(f64, x));
226226}
227227
228pub fn sqrtl(x: c_longdouble) callconv(.C) c_longdouble {
229 switch (@typeInfo(c_longdouble).Float.bits) {
230 16 => return __sqrth(x),
231 32 => return sqrtf(x),
232 64 => return sqrt(x),
233 80 => return __sqrtx(x),
234 128 => return sqrtq(x),
235 else => @compileError("unreachable"),
236 }
237}
238
228239test "sqrtf" {
229240 const V = [_]f32{
230241 0.0,
lib/compiler_rt/tan.zig+11
......@@ -96,6 +96,17 @@ pub fn tanq(x: f128) callconv(.C) f128 {
9696 return tan(@floatCast(f64, x));
9797}
9898
99pub fn tanl(x: c_longdouble) callconv(.C) c_longdouble {
100 switch (@typeInfo(c_longdouble).Float.bits) {
101 16 => return __tanh(x),
102 32 => return tanf(x),
103 64 => return tan(x),
104 80 => return __tanx(x),
105 128 => return tanq(x),
106 else => @compileError("unreachable"),
107 }
108}
109
99110test "tan" {
100111 try expect(tan(@as(f32, 0.0)) == tanf(0.0));
101112 try expect(tan(@as(f64, 0.0)) == tan(0.0));
lib/compiler_rt/trunc.zig+11
......@@ -81,6 +81,17 @@ pub fn truncq(x: f128) callconv(.C) f128 {
8181 }
8282}
8383
84pub fn truncl(x: c_longdouble) callconv(.C) c_longdouble {
85 switch (@typeInfo(c_longdouble).Float.bits) {
86 16 => return __trunch(x),
87 32 => return truncf(x),
88 64 => return trunc(x),
89 80 => return __truncx(x),
90 128 => return truncq(x),
91 else => @compileError("unreachable"),
92 }
93}
94
8495test "trunc32" {
8596 try expect(truncf(1.3) == 1.0);
8697 try expect(truncf(-1.3) == -1.0);
src/Sema.zig+9
......@@ -18673,6 +18673,15 @@ fn coerceInMemoryAllowed(
1867318673 }
1867418674 }
1867518675
18676 // Differently-named floats with the same number of bits.
18677 if (dest_ty.zigTypeTag() == .Float and src_ty.zigTypeTag() == .Float) {
18678 const dest_bits = dest_ty.floatBits(target);
18679 const src_bits = src_ty.floatBits(target);
18680 if (dest_bits == src_bits) {
18681 return .ok;
18682 }
18683 }
18684
1867618685 // Pointers / Pointer-like Optionals
1867718686 var dest_buf: Type.Payload.ElemType = undefined;
1867818687 var src_buf: Type.Payload.ElemType = undefined;
src/stage1/ir.cpp+6
......@@ -4480,6 +4480,12 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
44804480 return result;
44814481 }
44824482
4483 if (wanted_type->id == ZigTypeIdFloat && actual_type->id == ZigTypeIdFloat) {
4484 if (wanted_type->data.floating.bit_count == actual_type->data.floating.bit_count) {
4485 return result;
4486 }
4487 }
4488
44834489 if (wanted_type->id == ZigTypeIdVector && actual_type->id == ZigTypeIdVector) {
44844490 if (actual_type->data.vector.len != wanted_type->data.vector.len) {
44854491 result.id = ConstCastResultIdVectorLength;
test/behavior/cast.zig+20
......@@ -1426,3 +1426,23 @@ test "pointer to empty struct literal to mutable slice" {
14261426 var x: []i32 = &.{};
14271427 try expect(x.len == 0);
14281428}
1429
1430test "coerce between pointers of compatible differently-named floats" {
1431 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1432 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1433 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1434 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1435
1436 const F = switch (@typeInfo(c_longdouble).Float.bits) {
1437 16 => f16,
1438 32 => f32,
1439 64 => f64,
1440 80 => f80,
1441 128 => f128,
1442 else => @compileError("unreachable"),
1443 };
1444 var f1: F = 12.34;
1445 var f2: *c_longdouble = &f1;
1446 f2.* += 1;
1447 try expect(f1 == @as(F, 12.34) + 1);
1448}