aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2023-01-14 21:42:29 +0200
committerGitHub <noreply@github.com>2023-01-14 21:42:29 +0200
commitbb15e4057c9c8bb22084990de475ab10a44592c0 (patch)
treec1dcacddfc3ff184bd924405db0759ae2625280f /src
parent18191b80b6381eb41adb4354a243190865801212 (diff)
parent0013042cbd539cf7eb463483633e9f7aa2fa8067 (diff)
downloadzig-bb15e4057c9c8bb22084990de475ab10a44592c0.tar.gz
zig-bb15e4057c9c8bb22084990de475ab10a44592c0.zip
Merge pull request #14271 from Vexu/c-abi
float related C ABI fixes
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86_64/abi.zig39
-rw-r--r--src/codegen/llvm.zig42
2 files changed, 63 insertions, 18 deletions
diff --git a/src/arch/x86_64/abi.zig b/src/arch/x86_64/abi.zig
index 54c08e4aa9..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
@@ -112,7 +124,20 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
return result;
},
.Float => switch (ty.floatBits(target)) {
- 16, 32, 64 => {
+ 16 => {
+ if (ctx == .other) {
+ result[0] = .memory;
+ } else {
+ // TODO clang doesn't allow __fp16 as .ret or .arg
+ result[0] = .sse;
+ }
+ return result;
+ },
+ 32 => {
+ result[0] = .float;
+ return result;
+ },
+ 64 => {
result[0] = .sse;
return result;
},
@@ -120,11 +145,15 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
// "Arguments of types__float128, _Decimal128 and__m128 are
// split into two halves. The least significant ones belong
// to class SSE, the most significant one to class SSEUP."
+ if (ctx == .other) {
+ result[0] = .memory;
+ return result;
+ }
result[0] = .sse;
result[1] = .sseup;
return result;
},
- else => {
+ 80 => {
// "The 64-bit mantissa of arguments of type long double
// belongs to classX87, the 16-bit exponent plus 6 bytes
// of padding belongs to class X87UP."
@@ -132,6 +161,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
result[1] = .x87up;
return result;
},
+ else => unreachable,
},
.Vector => {
const elem_ty = ty.childType();
@@ -238,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 bca116f18f..8604c7d7f6 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -10395,7 +10395,12 @@ fn firstParamSRet(fn_info: Type.Payload.Function.Data, target: std.Target) bool
.mips, .mipsel => return false,
.x86_64 => switch (target.os.tag) {
.windows => return x86_64_abi.classifyWindows(fn_info.return_type, target) == .memory,
- else => return x86_64_abi.classifySystemV(fn_info.return_type, target, .ret)[0] == .memory,
+ else => {
+ const class = x86_64_abi.classifySystemV(fn_info.return_type, target, .ret);
+ if (class[0] == .memory) return true;
+ if (class[0] == .x87 and class[2] != .none) return true;
+ return false;
+ },
},
.wasm32 => return wasm_c_abi.classifyType(fn_info.return_type, target)[0] == .indirect,
.aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type, target) == .memory,
@@ -10469,22 +10474,26 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
llvm_types_buffer[llvm_types_index] = dg.context.intType(64);
llvm_types_index += 1;
},
- .sse => {
+ .sse, .sseup => {
llvm_types_buffer[llvm_types_index] = dg.context.doubleType();
llvm_types_index += 1;
},
- .sseup => {
- llvm_types_buffer[llvm_types_index] = dg.context.doubleType();
+ .float => {
+ llvm_types_buffer[llvm_types_index] = dg.context.floatType();
llvm_types_index += 1;
},
- .x87 => {
- llvm_types_buffer[llvm_types_index] = dg.context.x86FP80Type();
+ .float_combine => {
+ llvm_types_buffer[llvm_types_index] = dg.context.floatType().vectorType(2);
llvm_types_index += 1;
},
- .x87up => {
+ .x87 => {
+ if (llvm_types_index != 0 or classes[2] != .none) {
+ return dg.context.voidType();
+ }
llvm_types_buffer[llvm_types_index] = dg.context.x86FP80Type();
llvm_types_index += 1;
},
+ .x87up => continue,
.complex_x87 => {
@panic("TODO");
},
@@ -10689,22 +10698,25 @@ const ParamTypeIterator = struct {
llvm_types_buffer[llvm_types_index] = dg.context.intType(64);
llvm_types_index += 1;
},
- .sse => {
+ .sse, .sseup => {
llvm_types_buffer[llvm_types_index] = dg.context.doubleType();
llvm_types_index += 1;
},
- .sseup => {
- llvm_types_buffer[llvm_types_index] = dg.context.doubleType();
+ .float => {
+ llvm_types_buffer[llvm_types_index] = dg.context.floatType();
llvm_types_index += 1;
},
- .x87 => {
- llvm_types_buffer[llvm_types_index] = dg.context.x86FP80Type();
+ .float_combine => {
+ llvm_types_buffer[llvm_types_index] = dg.context.floatType().vectorType(2);
llvm_types_index += 1;
},
- .x87up => {
- llvm_types_buffer[llvm_types_index] = dg.context.x86FP80Type();
- llvm_types_index += 1;
+ .x87 => {
+ it.zig_index += 1;
+ it.llvm_index += 1;
+ it.byval_attr = true;
+ return .byref;
},
+ .x87up => unreachable,
.complex_x87 => {
@panic("TODO");
},