]> granicus.if.org Git - clang/commitdiff
MS ABI: Fix __fastcall methods that return structs
authorReid Kleckner <reid@kleckner.net>
Thu, 10 Jul 2014 01:58:55 +0000 (01:58 +0000)
committerReid Kleckner <reid@kleckner.net>
Thu, 10 Jul 2014 01:58:55 +0000 (01:58 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@212669 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/TargetInfo.cpp
test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp

index 44e001ceb6dcb97ec4a6b5edb09cde134614c6a4..be2d5b38c6154e6e47456f019b3f33c4bb6b65a0 100644 (file)
@@ -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()) {
index 2f8a66ea8e8778d4d521f3512da9ec05fc94d483..da58c461dcc09c1220de083c7105c8989ee4e395 100644 (file)
@@ -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)