From 0013042cbd539cf7eb463483633e9f7aa2fa8067 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 11 Jan 2023 23:02:06 +0200 Subject: [PATCH] llvm: correctly handle C ABI structs with f32/f64 alignment differences Closes #13830 --- src/arch/x86_64/abi.zig | 23 +++++++++++++++++++++-- src/codegen/llvm.zig | 16 ++++++++++++++++ test/c_abi/main.zig | 2 -- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/arch/x86_64/abi.zig b/src/arch/x86_64/abi.zig index 9fb0f795e3..35ac3dcb55 100644 --- a/src/arch/x86_64/abi.zig +++ b/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; } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 15ffe25ecd..8604c7d7f6 100644 --- a/src/codegen/llvm.zig +++ b/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; diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index 3bdb8c78a4..426651aa9e 100644 --- a/test/c_abi/main.zig +++ b/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;