r202097 - MS ABI: Return sret parameters when using inalloca

Reid Kleckner reid at kleckner.net
Mon Feb 24 16:59:15 PST 2014


Author: rnk
Date: Mon Feb 24 18:59:14 2014
New Revision: 202097

URL: http://llvm.org/viewvc/llvm-project?rev=202097&view=rev
Log:
MS ABI: Return sret parameters when using inalloca

Previously the X86 backend would look for the sret attribute and handle
this for us.  inalloca takes that all away, so we have to do the return
ourselves now.

Modified:
    cfe/trunk/include/clang/CodeGen/CGFunctionInfo.h
    cfe/trunk/lib/CodeGen/CGCall.cpp
    cfe/trunk/lib/CodeGen/TargetInfo.cpp
    cfe/trunk/test/CodeGenCXX/microsoft-abi-byval-sret.cpp

Modified: cfe/trunk/include/clang/CodeGen/CGFunctionInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/CodeGen/CGFunctionInfo.h?rev=202097&r1=202096&r2=202097&view=diff
==============================================================================
--- cfe/trunk/include/clang/CodeGen/CGFunctionInfo.h (original)
+++ cfe/trunk/include/clang/CodeGen/CGFunctionInfo.h Mon Feb 24 18:59:14 2014
@@ -191,6 +191,18 @@ public:
     return UIntData;
   }
 
+  /// \brief Return true if this field of an inalloca struct should be returned
+  /// to implement a struct return calling convention.
+  bool getInAllocaSRet() const {
+    assert(TheKind == InAlloca && "Invalid kind!");
+    return BoolData0;
+  }
+
+  void setInAllocaSRet(bool SRet) {
+    assert(TheKind == InAlloca && "Invalid kind!");
+    BoolData0 = SRet;
+  }
+
   void dump() const;
 };
 

Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=202097&r1=202096&r2=202097&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Mon Feb 24 18:59:14 2014
@@ -940,7 +940,15 @@ CodeGenTypes::GetFunctionType(const CGFu
     break;
 
   case ABIArgInfo::InAlloca:
-    resultType = llvm::Type::getVoidTy(getLLVMContext());
+    if (retAI.getInAllocaSRet()) {
+      // sret things on win32 aren't void, they return the sret pointer.
+      QualType ret = FI.getReturnType();
+      llvm::Type *ty = ConvertType(ret);
+      unsigned addressSpace = Context.getTargetAddressSpace(ret);
+      resultType = llvm::PointerType::get(ty, addressSpace);
+    } else {
+      resultType = llvm::Type::getVoidTy(getLLVMContext());
+    }
     break;
 
   case ABIArgInfo::Indirect: {
@@ -1779,7 +1787,17 @@ void CodeGenFunction::EmitFunctionEpilog
 
   switch (RetAI.getKind()) {
   case ABIArgInfo::InAlloca:
-    // Do nothing; aggregrates get evaluated directly into the destination.
+    // Aggregrates get evaluated directly into the destination.  Sometimes we
+    // need to return the sret value in a register, though.
+    assert(hasAggregateEvaluationKind(RetTy));
+    if (RetAI.getInAllocaSRet()) {
+      llvm::Function::arg_iterator EI = CurFn->arg_end();
+      --EI;
+      llvm::Value *ArgStruct = EI;
+      llvm::Value *SRet =
+          Builder.CreateStructGEP(ArgStruct, RetAI.getInAllocaFieldIndex());
+      RV = Builder.CreateLoad(SRet, "sret");
+    }
     break;
 
   case ABIArgInfo::Indirect: {

Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=202097&r1=202096&r2=202097&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Mon Feb 24 18:59:14 2014
@@ -1061,6 +1061,8 @@ void X86_32ABIInfo::rewriteWithInAlloca(
   if (Ret.isIndirect() && !Ret.getInReg()) {
     CanQualType PtrTy = getContext().getPointerType(FI.getReturnType());
     addFieldToArgStruct(FrameFields, StackOffset, Ret, PtrTy);
+    // On Windows, the hidden sret parameter is always returned in eax.
+    Ret.setInAllocaSRet(IsWin32StructABI);
   }
 
   // Skip the 'this' parameter in ecx.

Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-byval-sret.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-byval-sret.cpp?rev=202097&r1=202096&r2=202097&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-byval-sret.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-byval-sret.cpp Mon Feb 24 18:59:14 2014
@@ -14,13 +14,16 @@ A A::foo(A x) {
   return y;
 }
 
-// CHECK: define x86_thiscallcc void @"\01?foo at A@@QAE?AU1 at U1@@Z"
+// CHECK-LABEL: define x86_thiscallcc %struct.A* @"\01?foo at A@@QAE?AU1 at U1@@Z"
 // CHECK:       (%struct.A* %this, <{ %struct.A*, %struct.A }>* inalloca)
+// CHECK:   getelementptr inbounds <{ %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 0
+// CHECK:   load %struct.A**
+// CHECK:   ret %struct.A*
 
 int main() {
   A x;
   A y = x.foo(x);
 }
 
-// CHECK: call x86_thiscallcc void @"\01?foo at A@@QAE?AU1 at U1@@Z"
+// CHECK: call x86_thiscallcc %struct.A* @"\01?foo at A@@QAE?AU1 at U1@@Z"
 // CHECK:       (%struct.A* %{{[^,]*}}, <{ %struct.A*, %struct.A }>* inalloca %{{[^,]*}})





More information about the cfe-commits mailing list