From 6986d2aca900bdda30f541baf9b06fb29688fe97 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 1 May 2024 14:39:24 -0700 Subject: [PATCH] x86_64 sysv C ABI: fix f128 param and return types Clang 17 passed struct{f128} parameters using rdi and rax, while Clang 18 matches GCC 13.2 behavior, passing them using xmm0. This commit makes Zig's LLVM backend match Clang 18 and GCC 13.2. The commit deletes a hack in x86_64/abi.zig which miscategorized f128 as "memory" which obviously disagreed with the spec. --- src/arch/x86_64/CodeGen.zig | 2 +- src/arch/x86_64/abi.zig | 4 ---- src/codegen/llvm.zig | 20 ++++++++++++++++++-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 7faf3d6d50..cc6e014080 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -14318,7 +14318,7 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo else => { const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, self.target.*, .other), .none); assert(std.mem.indexOfNone(abi.Class, classes, &.{ - .integer, .sse, .memory, .float, .float_combine, + .integer, .sse, .sseup, .memory, .float, .float_combine, }) == null); const abi_size = ty.abiSize(mod); if (abi_size < 4 or diff --git a/src/arch/x86_64/abi.zig b/src/arch/x86_64/abi.zig index 8c81ad9ed2..0ae69eb09c 100644 --- a/src/arch/x86_64/abi.zig +++ b/src/arch/x86_64/abi.zig @@ -170,10 +170,6 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: std.Target, ctx: Context) [8 // "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 == .field) { - result[0] = .memory; - return result; - } result[0] = .sse; result[1] = .sseup; return result; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 877b2365c8..2d3c7de2e2 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -11167,10 +11167,18 @@ fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.E types_buffer[types_index] = .i64; types_index += 1; }, - .sse, .sseup => { + .sse => { types_buffer[types_index] = .double; types_index += 1; }, + .sseup => { + if (types_buffer[types_index - 1] == .double) { + types_buffer[types_index - 1] = .fp128; + } else { + types_buffer[types_index] = .double; + types_index += 1; + } + }, .float => { types_buffer[types_index] = .float; types_index += 1; @@ -11454,10 +11462,18 @@ const ParamTypeIterator = struct { types_buffer[types_index] = .i64; types_index += 1; }, - .sse, .sseup => { + .sse => { types_buffer[types_index] = .double; types_index += 1; }, + .sseup => { + if (types_buffer[types_index - 1] == .double) { + types_buffer[types_index - 1] = .fp128; + } else { + types_buffer[types_index] = .double; + types_index += 1; + } + }, .float => { types_buffer[types_index] = .float; types_index += 1;