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

Closes #13830
This commit is contained in:
Veikka Tuominen 2023-01-11 23:02:06 +02:00
parent 5572c67e73
commit 0013042cbd
3 changed files with 37 additions and 4 deletions

View File

@ -5,7 +5,19 @@ const assert = std.debug.assert;
const Register = @import("bits.zig").Register; const Register = @import("bits.zig").Register;
const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; 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 { pub fn classifyWindows(ty: Type, target: Target) Class {
// https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017 // 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; return result;
}, },
32, 64 => { 32 => {
result[0] = .float;
return result;
},
64 => {
result[0] = .sse; result[0] = .sse;
return result; return result;
}, },
@ -252,6 +268,9 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
combine: { combine: {
// "If both classes are equal, this is the resulting class." // "If both classes are equal, this is the resulting class."
if (result[result_i] == field_class[0]) { if (result[result_i] == field_class[0]) {
if (result[result_i] == .float) {
result[result_i] = .float_combine;
}
break :combine; break :combine;
} }

View File

@ -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_buffer[llvm_types_index] = dg.context.doubleType();
llvm_types_index += 1; 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 => { .x87 => {
if (llvm_types_index != 0 or classes[2] != .none) { if (llvm_types_index != 0 or classes[2] != .none) {
return dg.context.voidType(); return dg.context.voidType();
@ -10694,6 +10702,14 @@ const ParamTypeIterator = struct {
llvm_types_buffer[llvm_types_index] = dg.context.doubleType(); llvm_types_buffer[llvm_types_index] = dg.context.doubleType();
llvm_types_index += 1; 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 => { .x87 => {
it.zig_index += 1; it.zig_index += 1;
it.llvm_index += 1; it.llvm_index += 1;

View File

@ -937,7 +937,6 @@ test "CFF: Zig returns to C" {
try expectOk(c_assert_ret_CFF()); try expectOk(c_assert_ret_CFF());
} }
test "CFF: C passes to Zig" { 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 (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) 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; 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()); try expectOk(c_send_CFF());
} }
test "CFF: C returns to Zig" { 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 == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
if (builtin.cpu.arch == .aarch64 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; if (comptime builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;