authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-04-10 18:47:14-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-04-10 18:47:14-04:00
loga71bfc249d3f814d7d659fe5cf4cb582483e8938
tree0b1b26bbb96a02eebbd05dbe9cf16fd06412d8d6
parent52934851f2b7a5cb28a08beafa1ec1aa24a3a4cb

compiler-rt: better way to do the ABI required on Windows

This removes the compiler_rt.setXmm0 hack. Instead, for the functions that use i128 or u128 in their parameter and return types, we use `@Vector(2, u64)` which generates the LLVM IR `<2 x i64>` type that matches what Clang generates for `typedef int ti_int __attribute__ ((mode (TI)))` when targeting Windows x86_64.

9 files changed, 24 insertions(+), 31 deletions(-)

src/codegen.cpp+1-1
...@@ -424,7 +424,7 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) {...@@ -424,7 +424,7 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) {
424}424}
425425
426static void maybe_export_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) {426static void maybe_export_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) {
427 if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows) {427 if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows && g->is_dynamic) {
428 LLVMSetDLLStorageClass(global_value, LLVMDLLExportStorageClass);428 LLVMSetDLLStorageClass(global_value, LLVMDLLExportStorageClass);
429 }429 }
430}430}
std/special/compiler_rt.zig+2-11
...@@ -160,6 +160,8 @@ comptime {...@@ -160,6 +160,8 @@ comptime {
160 @export("__chkstk", __chkstk, strong_linkage);160 @export("__chkstk", __chkstk, strong_linkage);
161 @export("___chkstk_ms", ___chkstk_ms, linkage);161 @export("___chkstk_ms", ___chkstk_ms, linkage);
162 }162 }
163 // The "ti" functions must use @Vector(2, u64) parameter types to adhere to the ABI
164 // that LLVM expects compiler-rt to have.
163 @export("__divti3", @import("compiler_rt/divti3.zig").__divti3_windows_x86_64, linkage);165 @export("__divti3", @import("compiler_rt/divti3.zig").__divti3_windows_x86_64, linkage);
164 @export("__modti3", @import("compiler_rt/modti3.zig").__modti3_windows_x86_64, linkage);166 @export("__modti3", @import("compiler_rt/modti3.zig").__modti3_windows_x86_64, linkage);
165 @export("__multi3", @import("compiler_rt/multi3.zig").__multi3_windows_x86_64, linkage);167 @export("__multi3", @import("compiler_rt/multi3.zig").__multi3_windows_x86_64, linkage);
...@@ -198,17 +200,6 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn...@@ -198,17 +200,6 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn
198 }200 }
199}201}
200202
201pub fn setXmm0(comptime T: type, value: T) void {
202 comptime assert(builtin.arch == builtin.Arch.x86_64);
203 const aligned_value: T align(16) = value;
204 asm volatile (
205 \\movaps (%[ptr]), %%xmm0
206 :
207 : [ptr] "r" (&aligned_value)
208 : "xmm0"
209 );
210}
211
212extern fn __udivdi3(a: u64, b: u64) u64 {203extern fn __udivdi3(a: u64, b: u64) u64 {
213 @setRuntimeSafety(is_test);204 @setRuntimeSafety(is_test);
214 return __udivmoddi4(a, b, null);205 return __udivmoddi4(a, b, null);
std/special/compiler_rt/divti3.zig+3-3
...@@ -16,9 +16,9 @@ pub extern fn __divti3(a: i128, b: i128) i128 {...@@ -16,9 +16,9 @@ pub extern fn __divti3(a: i128, b: i128) i128 {
16 return (@bitCast(i128, r) ^ s) -% s;16 return (@bitCast(i128, r) ^ s) -% s;
17}17}
1818
19pub extern fn __divti3_windows_x86_64(a: *const i128, b: *const i128) void {19const v128 = @Vector(2, u64);
20 @setRuntimeSafety(builtin.is_test);20pub extern fn __divti3_windows_x86_64(a: v128, b: v128) v128 {
21 compiler_rt.setXmm0(i128, __divti3(a.*, b.*));21 return @bitCast(v128, @inlineCall(__divti3, @bitCast(i128, a), @bitCast(i128, b)));
22}22}
2323
24test "import divti3" {24test "import divti3" {
std/special/compiler_rt/modti3.zig+3-3
...@@ -20,9 +20,9 @@ pub extern fn __modti3(a: i128, b: i128) i128 {...@@ -20,9 +20,9 @@ pub extern fn __modti3(a: i128, b: i128) i128 {
20 return (@bitCast(i128, r) ^ s_a) -% s_a; // negate if s == -120 return (@bitCast(i128, r) ^ s_a) -% s_a; // negate if s == -1
21}21}
2222
23pub extern fn __modti3_windows_x86_64(a: *const i128, b: *const i128) void {23const v128 = @Vector(2, u64);
24 @setRuntimeSafety(builtin.is_test);24pub extern fn __modti3_windows_x86_64(a: v128, b: v128) v128 {
25 compiler_rt.setXmm0(i128, __modti3(a.*, b.*));25 return @bitCast(v128, @inlineCall(__modti3, @bitCast(i128, a), @bitCast(i128, b)));
26}26}
2727
28test "import modti3" {28test "import modti3" {
std/special/compiler_rt/muloti4.zig+3-3
...@@ -44,9 +44,9 @@ pub extern fn __muloti4(a: i128, b: i128, overflow: *c_int) i128 {...@@ -44,9 +44,9 @@ pub extern fn __muloti4(a: i128, b: i128, overflow: *c_int) i128 {
44 return r;44 return r;
45}45}
4646
47pub extern fn __muloti4_windows_x86_64(a: *const i128, b: *const i128, overflow: *c_int) void {47const v128 = @Vector(2, u64);
48 @setRuntimeSafety(builtin.is_test);48pub extern fn __muloti4_windows_x86_64(a: v128, b: v128, overflow: *c_int) v128 {
49 compiler_rt.setXmm0(i128, __muloti4(a.*, b.*, overflow));49 return @bitCast(v128, @inlineCall(__muloti4, @bitCast(i128, a), @bitCast(i128, b), overflow));
50}50}
5151
52test "import muloti4" {52test "import muloti4" {
std/special/compiler_rt/multi3.zig+3-3
...@@ -14,9 +14,9 @@ pub extern fn __multi3(a: i128, b: i128) i128 {...@@ -14,9 +14,9 @@ pub extern fn __multi3(a: i128, b: i128) i128 {
14 return r.all;14 return r.all;
15}15}
1616
17pub extern fn __multi3_windows_x86_64(a: *const i128, b: *const i128) void {17const v128 = @Vector(2, u64);
18 @setRuntimeSafety(builtin.is_test);18pub extern fn __multi3_windows_x86_64(a: v128, b: v128) v128 {
19 compiler_rt.setXmm0(i128, __multi3(a.*, b.*));19 return @bitCast(v128, @inlineCall(__multi3, @bitCast(i128, a), @bitCast(i128, b)));
20}20}
2121
22fn __mulddi3(a: u64, b: u64) i128 {22fn __mulddi3(a: u64, b: u64) i128 {
std/special/compiler_rt/udivmodti4.zig+3-2
...@@ -7,9 +7,10 @@ pub extern fn __udivmodti4(a: u128, b: u128, maybe_rem: ?*u128) u128 {...@@ -7,9 +7,10 @@ pub extern fn __udivmodti4(a: u128, b: u128, maybe_rem: ?*u128) u128 {
7 return udivmod(u128, a, b, maybe_rem);7 return udivmod(u128, a, b, maybe_rem);
8}8}
99
10pub extern fn __udivmodti4_windows_x86_64(a: *const u128, b: *const u128, maybe_rem: ?*u128) void {10const v128 = @Vector(2, u64);
11pub extern fn __udivmodti4_windows_x86_64(a: v128, b: v128, maybe_rem: ?*u128) v128 {
11 @setRuntimeSafety(builtin.is_test);12 @setRuntimeSafety(builtin.is_test);
12 compiler_rt.setXmm0(u128, udivmod(u128, a.*, b.*, maybe_rem));13 return @bitCast(v128, udivmod(u128, @bitCast(u128, a), @bitCast(u128, b), maybe_rem));
13}14}
1415
15test "import udivmodti4" {16test "import udivmodti4" {
std/special/compiler_rt/udivti3.zig+3-2
...@@ -6,7 +6,8 @@ pub extern fn __udivti3(a: u128, b: u128) u128 {...@@ -6,7 +6,8 @@ pub extern fn __udivti3(a: u128, b: u128) u128 {
6 return udivmodti4.__udivmodti4(a, b, null);6 return udivmodti4.__udivmodti4(a, b, null);
7}7}
88
9pub extern fn __udivti3_windows_x86_64(a: *const u128, b: *const u128) void {9const v128 = @Vector(2, u64);
10pub extern fn __udivti3_windows_x86_64(a: v128, b: v128) v128 {
10 @setRuntimeSafety(builtin.is_test);11 @setRuntimeSafety(builtin.is_test);
11 udivmodti4.__udivmodti4_windows_x86_64(a, b, null);12 return udivmodti4.__udivmodti4_windows_x86_64(a, b, null);
12}13}
std/special/compiler_rt/umodti3.zig+3-3
...@@ -9,7 +9,7 @@ pub extern fn __umodti3(a: u128, b: u128) u128 {...@@ -9,7 +9,7 @@ pub extern fn __umodti3(a: u128, b: u128) u128 {
9 return r;9 return r;
10}10}
1111
12pub extern fn __umodti3_windows_x86_64(a: *const u128, b: *const u128) void {12const v128 = @Vector(2, u64);
13 @setRuntimeSafety(builtin.is_test);13pub extern fn __umodti3_windows_x86_64(a: v128, b: v128) v128 {
14 compiler_rt.setXmm0(u128, __umodti3(a.*, b.*));14 return @bitCast(v128, @inlineCall(__umodti3, @bitCast(u128, a), @bitCast(u128, b)));
15}15}