From 677539d0afe90fe8ec6fde19d156c1e2b0d4046a Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Thu, 10 Jul 2014 01:58:55 +0000 Subject: [PATCH] MS ABI: Fix __fastcall methods that return structs The sret paramater consumes the register after the implicit 'this' parameter, as with other calling conventions. Fixes PR20278, which turned out to be very easy. llvm-svn: 212669 --- clang/lib/CodeGen/TargetInfo.cpp | 10 +++++++++- clang/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp | 9 +++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 44e001c..be2d5b3 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -957,8 +957,16 @@ void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI) const { else State.FreeRegs = DefaultNumRegisterParameters; - if (!getCXXABI().classifyReturnType(FI)) + if (!getCXXABI().classifyReturnType(FI)) { FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), State); + } else if (FI.getReturnInfo().isIndirect()) { + // The C++ ABI is not aware of register usage, so we have to check if the + // return value was sret and put it in a register ourselves if appropriate. + if (State.FreeRegs) { + --State.FreeRegs; // The sret parameter consumes a register. + FI.getReturnInfo().setInReg(true); + } + } bool UsedInAlloca = false; for (auto &I : FI.arguments()) { diff --git a/clang/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp b/clang/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp index 2f8a66e..da58c46 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp @@ -33,3 +33,12 @@ int main() { // CHECK: call void {{.*}} @"\01?variadic_sret@C@@QAA?AUS@@PBDZZ" // CHECK: call void @"\01?cdecl_sret@C@@QAA?AUS@@XZ" // CHECK: call void @"\01?byval_and_sret@C@@QAA?AUS@@U2@@Z" + +// __fastcall has similar issues. +struct A { + S __fastcall f(int x); +}; +S A::f(int x) { + return S(); +} +// CHECK-LABEL: define x86_fastcallcc void @"\01?f@A@@QAI?AUS@@H@Z"(%struct.A* inreg %this, %struct.S* inreg noalias sret %agg.result, i32 %x) -- 2.7.4