authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-11 23:02:06+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-14 16:26:50+02:00
log0013042cbd539cf7eb463483633e9f7aa2fa8067
tree4346a3276ec07b35e3d90df88a8c5528c1fd7f96
parent5572c67e73222716372762d30453cc44ca4339c0

llvm: correctly handle C ABI structs with f32/f64 alignment differences

Closes #13830

3 files changed, 37 insertions(+), 4 deletions(-)

src/arch/x86_64/abi.zig+21-2
...@@ -5,7 +5,19 @@ const assert = std.debug.assert;...@@ -5,7 +5,19 @@ const assert = std.debug.assert;
5const Register = @import("bits.zig").Register;5const Register = @import("bits.zig").Register;
6const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;6const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
77
8pub const Class = enum { integer, sse, sseup, x87, x87up, complex_x87, memory, none, win_i128 };8pub const Class = enum {
9 integer,
10 sse,
11 sseup,
12 x87,
13 x87up,
14 complex_x87,
15 memory,
16 none,
17 win_i128,
18 float,
19 float_combine,
20};
921
10pub fn classifyWindows(ty: Type, target: Target) Class {22pub fn classifyWindows(ty: Type, target: Target) Class {
11 // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-201723 // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017
...@@ -121,7 +133,11 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {...@@ -121,7 +133,11 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
121 }133 }
122 return result;134 return result;
123 },135 },
124 32, 64 => {136 32 => {
137 result[0] = .float;
138 return result;
139 },
140 64 => {
125 result[0] = .sse;141 result[0] = .sse;
126 return result;142 return result;
127 },143 },
...@@ -252,6 +268,9 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {...@@ -252,6 +268,9 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
252 combine: {268 combine: {
253 // "If both classes are equal, this is the resulting class."269 // "If both classes are equal, this is the resulting class."
254 if (result[result_i] == field_class[0]) {270 if (result[result_i] == field_class[0]) {
271 if (result[result_i] == .float) {
272 result[result_i] = .float_combine;
273 }
255 break :combine;274 break :combine;
256 }275 }
257276
src/codegen/llvm.zig+16
...@@ -10478,6 +10478,14 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {...@@ -10478,6 +10478,14 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
10478 llvm_types_buffer[llvm_types_index] = dg.context.doubleType();10478 llvm_types_buffer[llvm_types_index] = dg.context.doubleType();
10479 llvm_types_index += 1;10479 llvm_types_index += 1;
10480 },10480 },
10481 .float => {
10482 llvm_types_buffer[llvm_types_index] = dg.context.floatType();
10483 llvm_types_index += 1;
10484 },
10485 .float_combine => {
10486 llvm_types_buffer[llvm_types_index] = dg.context.floatType().vectorType(2);
10487 llvm_types_index += 1;
10488 },
10481 .x87 => {10489 .x87 => {
10482 if (llvm_types_index != 0 or classes[2] != .none) {10490 if (llvm_types_index != 0 or classes[2] != .none) {
10483 return dg.context.voidType();10491 return dg.context.voidType();
...@@ -10694,6 +10702,14 @@ const ParamTypeIterator = struct {...@@ -10694,6 +10702,14 @@ const ParamTypeIterator = struct {
10694 llvm_types_buffer[llvm_types_index] = dg.context.doubleType();10702 llvm_types_buffer[llvm_types_index] = dg.context.doubleType();
10695 llvm_types_index += 1;10703 llvm_types_index += 1;
10696 },10704 },
10705 .float => {
10706 llvm_types_buffer[llvm_types_index] = dg.context.floatType();
10707 llvm_types_index += 1;
10708 },
10709 .float_combine => {
10710 llvm_types_buffer[llvm_types_index] = dg.context.floatType().vectorType(2);
10711 llvm_types_index += 1;
10712 },
10697 .x87 => {10713 .x87 => {
10698 it.zig_index += 1;10714 it.zig_index += 1;
10699 it.llvm_index += 1;10715 it.llvm_index += 1;
test/c_abi/main.zig-2
...@@ -937,7 +937,6 @@ test "CFF: Zig returns to C" {...@@ -937,7 +937,6 @@ test "CFF: Zig returns to C" {
937 try expectOk(c_assert_ret_CFF());937 try expectOk(c_assert_ret_CFF());
938}938}
939test "CFF: C passes to Zig" {939test "CFF: C passes to Zig" {
940 if (builtin.cpu.arch == .x86_64 and builtin.mode != .Debug) return error.SkipZigTest;
941 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;940 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
942 if (comptime builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;941 if (comptime builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;
943 if (builtin.cpu.arch == .aarch64 and builtin.mode != .Debug) return error.SkipZigTest;942 if (builtin.cpu.arch == .aarch64 and builtin.mode != .Debug) return error.SkipZigTest;
...@@ -948,7 +947,6 @@ test "CFF: C passes to Zig" {...@@ -948,7 +947,6 @@ test "CFF: C passes to Zig" {
948 try expectOk(c_send_CFF());947 try expectOk(c_send_CFF());
949}948}
950test "CFF: C returns to Zig" {949test "CFF: C returns to Zig" {
951 if (builtin.cpu.arch == .x86_64 and builtin.mode != .Debug) return error.SkipZigTest;
952 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;950 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
953 if (builtin.cpu.arch == .aarch64 and builtin.mode != .Debug) return error.SkipZigTest;951 if (builtin.cpu.arch == .aarch64 and builtin.mode != .Debug) return error.SkipZigTest;
954 if (comptime builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;952 if (comptime builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;