https://github.com/henrybw created https://github.com/llvm/llvm-project/pull/157365
The MSVC ABI almost always returns vector types directly, but on x86 and x86_64, there seems to be a special case for member functions, which return vector types indirectly. Fixes #104. >From 8f42b86f8d487b9f488a7cf7ec5d0e127f736b12 Mon Sep 17 00:00:00 2001 From: Henry Baba-Weiss <henry.babawe...@gmail.com> Date: Sun, 7 Sep 2025 14:16:16 -0700 Subject: [PATCH] [clang][CodeGen][MSVC] Return vector types from methods indirectly The MSVC ABI almost always returns vector types directly, but on x86 and x86_64, there seems to be a special case for member functions, which return vector types indirectly. Fixes #104. --- clang/docs/ReleaseNotes.rst | 3 ++ clang/lib/CodeGen/MicrosoftCXXABI.cpp | 23 +++++++----- .../CodeGenCXX/microsoft-abi-vector-types.cpp | 36 +++++++++++++++++++ 3 files changed, 53 insertions(+), 9 deletions(-) create mode 100644 clang/test/CodeGenCXX/microsoft-abi-vector-types.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d1ef91b7e7c14..1be917221aa2c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -90,6 +90,9 @@ C++ Specific Potentially Breaking Changes ABI Changes in This Version --------------------------- +- Fixed Microsoft calling convention for returning vector types from C++ member + functions. Such vector types should be returned indirectly. (GH#104) + AST Dumping Potentially Breaking Changes ---------------------------------------- - How nested name specifiers are dumped and printed changes, keeping track of clang AST changes. diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 88f0648660965..2d76eebcecd08 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1168,15 +1168,20 @@ static bool isTrivialForMSVC(const CXXRecordDecl *RD, QualType Ty, } bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI) const { - const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl(); - if (!RD) - return false; - - bool isTrivialForABI = RD->canPassInRegisters() && - isTrivialForMSVC(RD, FI.getReturnType(), CGM); - - // MSVC always returns structs indirectly from C++ instance methods. - bool isIndirectReturn = !isTrivialForABI || FI.isInstanceMethod(); + bool isIndirectReturn = false; + if (const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl()) { + bool isTrivialForABI = RD->canPassInRegisters() && + isTrivialForMSVC(RD, FI.getReturnType(), CGM); + + // MSVC always returns structs indirectly from C++ instance methods. + isIndirectReturn = !isTrivialForABI || FI.isInstanceMethod(); + } else if (isa<VectorType>(FI.getReturnType())) { + // On x86, MSVC seems to only return vector types indirectly from non- + // vectorcall C++ instance methods. + isIndirectReturn = + CGM.getTarget().getTriple().isX86() && FI.isInstanceMethod() && + FI.getCallingConvention() != llvm::CallingConv::X86_VectorCall; + } if (isIndirectReturn) { CharUnits Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType()); diff --git a/clang/test/CodeGenCXX/microsoft-abi-vector-types.cpp b/clang/test/CodeGenCXX/microsoft-abi-vector-types.cpp new file mode 100644 index 0000000000000..e046fb4bb3169 --- /dev/null +++ b/clang/test/CodeGenCXX/microsoft-abi-vector-types.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -ffreestanding -emit-llvm %s -o - -triple=i686-pc-windows-msvc | FileCheck %s +// RUN: %clang_cc1 -ffreestanding -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc | FileCheck %s + +// To match the MSVC ABI, vector types must be returned indirectly from member +// functions (as long as they do not use the vectorcall calling convention), +// but must be returned directly everywhere else. + +#include <xmmintrin.h> + +struct Foo { + __m128 method_m128(); + __m128 __vectorcall vectorcall_method_m128(); +}; + +__m128 Foo::method_m128() { + return __m128{}; +// GH104 +// CHECK: store <4 x float> +// CHECK: ret void +} + +__m128 __vectorcall Foo::vectorcall_method_m128() { + return __m128{}; +// CHECK: ret <4 x float> +} + +__m128 func_m128() { + return __m128{}; +// CHECK: ret <4 x float> +} + +__m128 __vectorcall vectorcall_func_m128() { + return __m128{}; +// CHECK: ret <4 x float> +} + _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits