Commit 0013042cbd

Veikka Tuominen <git@vexu.eu>
2023-01-11 22:02:06
llvm: correctly handle C ABI structs with f32/f64 alignment differences
Closes #13830
1 parent 5572c67
Changed files (3)
src
arch
x86_64
codegen
test
c_abi
src/arch/x86_64/abi.zig
@@ -5,7 +5,19 @@ const assert = std.debug.assert;
 const Register = @import("bits.zig").Register;
 const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
 
-pub const Class = enum { integer, sse, sseup, x87, x87up, complex_x87, memory, none, win_i128 };
+pub const Class = enum {
+    integer,
+    sse,
+    sseup,
+    x87,
+    x87up,
+    complex_x87,
+    memory,
+    none,
+    win_i128,
+    float,
+    float_combine,
+};
 
 pub fn classifyWindows(ty: Type, target: Target) Class {
     // 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 {
                 }
                 return result;
             },
-            32, 64 => {
+            32 => {
+                result[0] = .float;
+                return result;
+            },
+            64 => {
                 result[0] = .sse;
                 return result;
             },
@@ -252,6 +268,9 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
                     combine: {
                         // "If both classes are equal, this is the resulting class."
                         if (result[result_i] == field_class[0]) {
+                            if (result[result_i] == .float) {
+                                result[result_i] = .float_combine;
+                            }
                             break :combine;
                         }
 
src/codegen/llvm.zig
@@ -10478,6 +10478,14 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
                                     llvm_types_buffer[llvm_types_index] = dg.context.doubleType();
                                     llvm_types_index += 1;
                                 },
+                                .float => {
+                                    llvm_types_buffer[llvm_types_index] = dg.context.floatType();
+                                    llvm_types_index += 1;
+                                },
+                                .float_combine => {
+                                    llvm_types_buffer[llvm_types_index] = dg.context.floatType().vectorType(2);
+                                    llvm_types_index += 1;
+                                },
                                 .x87 => {
                                     if (llvm_types_index != 0 or classes[2] != .none) {
                                         return dg.context.voidType();
@@ -10694,6 +10702,14 @@ const ParamTypeIterator = struct {
                                         llvm_types_buffer[llvm_types_index] = dg.context.doubleType();
                                         llvm_types_index += 1;
                                     },
+                                    .float => {
+                                        llvm_types_buffer[llvm_types_index] = dg.context.floatType();
+                                        llvm_types_index += 1;
+                                    },
+                                    .float_combine => {
+                                        llvm_types_buffer[llvm_types_index] = dg.context.floatType().vectorType(2);
+                                        llvm_types_index += 1;
+                                    },
                                     .x87 => {
                                         it.zig_index += 1;
                                         it.llvm_index += 1;
test/c_abi/main.zig
@@ -937,7 +937,6 @@ test "CFF: Zig returns to C" {
     try expectOk(c_assert_ret_CFF());
 }
 test "CFF: C passes to Zig" {
-    if (builtin.cpu.arch == .x86_64 and builtin.mode != .Debug) return error.SkipZigTest;
     if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
     if (comptime builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;
     if (builtin.cpu.arch == .aarch64 and builtin.mode != .Debug) return error.SkipZigTest;
@@ -948,7 +947,6 @@ test "CFF: C passes to Zig" {
     try expectOk(c_send_CFF());
 }
 test "CFF: C returns to Zig" {
-    if (builtin.cpu.arch == .x86_64 and builtin.mode != .Debug) return error.SkipZigTest;
     if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
     if (builtin.cpu.arch == .aarch64 and builtin.mode != .Debug) return error.SkipZigTest;
     if (comptime builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;