]> granicus.if.org Git - clang/commitdiff
Make functions returning a struct indirectly evaluate the returned struct
authorEli Friedman <eli.friedman@gmail.com>
Fri, 4 Dec 2009 02:43:40 +0000 (02:43 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Fri, 4 Dec 2009 02:43:40 +0000 (02:43 +0000)
directly into the sret pointer. This is an optimization in C, but is required
for correctness in C++ for classes with a non-trivial copy constructor.

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

lib/CodeGen/CGCall.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h

index decc73c6d458c4bb9fd86d442c6cde74e1488fac..62a5792d27db3e1051d2fa8a1d9716de3092a6bb 100644 (file)
@@ -764,7 +764,7 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
         ComplexPairTy RT = LoadComplexFromAddr(ReturnValue, false);
         StoreComplexToAddr(RT, CurFn->arg_begin(), false);
       } else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
-        EmitAggregateCopy(CurFn->arg_begin(), ReturnValue, RetTy);
+        // Do nothing; aggregrates get evaluated directly into the destination.
       } else {
         EmitStoreOfScalar(Builder.CreateLoad(ReturnValue), CurFn->arg_begin(),
                           false, RetTy);
index 1e952f9a7dbfd7d405d0e07bb330cd8a1761bef0..88f02a9738cfb640b66a390331b7ab286de133ef 100644 (file)
@@ -179,9 +179,6 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
     AllocaInsertPt->setName("allocapt");
 
   ReturnBlock = createBasicBlock("return");
-  ReturnValue = 0;
-  if (!RetTy->isVoidType())
-    ReturnValue = CreateTempAlloca(ConvertType(RetTy), "retval");
 
   Builder.SetInsertPoint(EntryBB);
 
@@ -204,6 +201,19 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
 
   // FIXME: Leaked.
   CurFnInfo = &CGM.getTypes().getFunctionInfo(FnRetTy, Args);
+
+  if (RetTy->isVoidType()) {
+    // Void type; nothing to return.
+    ReturnValue = 0;
+  } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
+             hasAggregateLLVMType(CurFnInfo->getReturnType())) {
+    // Indirect aggregate return; emit returned value directly into sret slot.
+    // This reduces code size, and is also affects correctness in C++.
+    ReturnValue = CurFn->arg_begin();
+  } else {
+    ReturnValue = CreateTempAlloca(ConvertType(RetTy), "retval");
+  }
+
   EmitFunctionProlog(*CurFnInfo, CurFn, Args);
 
   // If any of the arguments have a variably modified type, make sure to
index 0838cf0f8148b0866554ad133510db06ebe887d9..bf791abfbc8505f1b6aa9a0d22521634fddb5ba9 100644 (file)
@@ -92,7 +92,7 @@ public:
   llvm::BasicBlock *ReturnBlock;
   /// ReturnValue - The temporary alloca to hold the return value. This is null
   /// iff the function has no return value.
-  llvm::Instruction *ReturnValue;
+  llvm::Value *ReturnValue;
 
   /// AllocaInsertPoint - This is an instruction in the entry block before which
   /// we prefer to insert allocas.