Skip to content

[clang] Pass fp128 indirectly and return in xmm0 on Windows #115052

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 6, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions clang/lib/CodeGen/Targets/X86.cpp
Original file line number Diff line number Diff line change
@@ -3390,6 +3390,9 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,

case BuiltinType::Int128:
case BuiltinType::UInt128:
case BuiltinType::Float128:
// 128-bit float and integer types share the same ABI.

// If it's a parameter type, the normal ABI rule is that arguments larger
// than 8 bytes are passed indirectly. GCC follows it. We follow it too,
// even though it isn't particularly efficient.
@@ -3400,6 +3403,8 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,

// Mingw64 GCC returns i128 in XMM0. Coerce to v2i64 to handle that.
// Clang matches them for compatibility.
// NOTE: GCC actually returns f128 indirectly but will hopefully change.
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054#c8.
return ABIArgInfo::getDirect(llvm::FixedVectorType::get(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment right here implies GCC returns i128 in XMM0. Are we sure f128 will always be passed indirectly? Going with a straightforward interpretation of the ABI as documented by Microsoft implies it should be passed indirectly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GCC currently always passes and returns f128 indirectly on MinGW. Reading https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170 makes me think that it would actually be more accurate to pass indirectly but return in XMM0, similar to what i128 is doing - I brought this up in my most recent comment at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054 (disregard the top post, I was originally asking GCC to pass in XMM which wasn't correct).

What would be best to do here?

llvm::Type::getInt64Ty(getVMContext()), 2));

19 changes: 19 additions & 0 deletions clang/test/CodeGen/win-fp128.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -o - %s \
// RUN: | FileCheck %s --check-prefix=CHECK-GNU64
// __float128 is unsupported on MSVC

__float128 fp128_ret(void) { return 0; }
// CHECK-GNU64: define dso_local <2 x i64> @fp128_ret()

__float128 fp128_args(__float128 a, __float128 b) { return a * b; }
// CHECK-GNU64: define dso_local <2 x i64> @fp128_args(ptr noundef %0, ptr noundef %1)

void fp128_vararg(int a, ...) {
// CHECK-GNU64-LABEL: define dso_local void @fp128_vararg
__builtin_va_list ap;
__builtin_va_start(ap, a);
__float128 i = __builtin_va_arg(ap, __float128);
// CHECK-GNU64: load ptr, ptr
// CHECK-GNU64: load fp128, ptr
__builtin_va_end(ap);
}