Correctly pass aggregates by reference when emitting thunks.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104778 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 0d6a70c..73cee3c 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -862,6 +862,36 @@
   }
 }
 
+RValue CodeGenFunction::EmitDelegateCallArg(const VarDecl *Param) {
+  // StartFunction converted the ABI-lowered parameter(s) into a
+  // local alloca.  We need to turn that into an r-value suitable
+  // for EmitCall.
+  llvm::Value *Local = GetAddrOfLocalVar(Param);
+
+  QualType ArgType = Param->getType();
+ 
+  // For the most part, we just need to load the alloca, except:
+  // 1) aggregate r-values are actually pointers to temporaries, and
+  // 2) references to aggregates are pointers directly to the aggregate.
+  // I don't know why references to non-aggregates are different here.
+  if (const ReferenceType *RefType = ArgType->getAs<ReferenceType>()) {
+    if (hasAggregateLLVMType(RefType->getPointeeType()))
+      return RValue::getAggregate(Local);
+
+    // Locals which are references to scalars are represented
+    // with allocas holding the pointer.
+    return RValue::get(Builder.CreateLoad(Local));
+  }
+
+  if (ArgType->isAnyComplexType())
+    return RValue::getComplex(LoadComplexFromAddr(Local, /*volatile*/ false));
+
+  if (hasAggregateLLVMType(ArgType))
+    return RValue::getAggregate(Local);
+
+  return RValue::get(EmitLoadOfScalar(Local, false, ArgType));
+}
+
 RValue CodeGenFunction::EmitCallArg(const Expr *E, QualType ArgType) {
   if (ArgType->isReferenceType())
     return EmitReferenceBindingToExpr(E);
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 587a68b..bebea54 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -1137,34 +1137,9 @@
 
   // Explicit arguments.
   for (; I != E; ++I) {
-    
     const VarDecl *Param = I->first;
     QualType ArgType = Param->getType(); // because we're passing it to itself
-
-    // StartFunction converted the ABI-lowered parameter(s) into a
-    // local alloca.  We need to turn that into an r-value suitable
-    // for EmitCall.
-    llvm::Value *Local = GetAddrOfLocalVar(Param);
-    RValue Arg;
- 
-    // For the most part, we just need to load the alloca, except:
-    // 1) aggregate r-values are actually pointers to temporaries, and
-    // 2) references to aggregates are pointers directly to the aggregate.
-    // I don't know why references to non-aggregates are different here.
-    if (ArgType->isReferenceType()) {
-      const ReferenceType *RefType = ArgType->getAs<ReferenceType>();
-      if (hasAggregateLLVMType(RefType->getPointeeType()))
-        Arg = RValue::getAggregate(Local);
-      else
-        // Locals which are references to scalars are represented
-        // with allocas holding the pointer.
-        Arg = RValue::get(Builder.CreateLoad(Local));
-    } else {
-      if (hasAggregateLLVMType(ArgType))
-        Arg = RValue::getAggregate(Local);
-      else
-        Arg = RValue::get(EmitLoadOfScalar(Local, false, ArgType));
-    }
+    RValue Arg = EmitDelegateCallArg(Param);
 
     DelegateArgs.push_back(std::make_pair(Arg, ArgType));
   }
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index 8bdd458..0f023e6 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -2641,14 +2641,7 @@
        E = MD->param_end(); I != E; ++I) {
     ParmVarDecl *Param = *I;
     QualType ArgType = Param->getType();
-    
-    // Load the argument corresponding to this parameter.
-    RValue Arg;
-    if (ArgType->isReferenceType() ||
-        (hasAggregateLLVMType(ArgType) && !ArgType->isAnyComplexType()))
-      Arg = RValue::get(Builder.CreateLoad(LocalDeclMap[Param]));
-    else
-      Arg = RValue::get(EmitLoadOfScalar(LocalDeclMap[Param], false, ArgType));
+    RValue Arg = EmitDelegateCallArg(Param);
     
     CallArgs.push_back(std::make_pair(Arg, ArgType));
   }
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 944aa48..ece275e 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -1302,6 +1302,11 @@
   /// EmitCallArg - Emit a single call argument.
   RValue EmitCallArg(const Expr *E, QualType ArgType);
 
+  /// EmitDelegateCallArg - We are performing a delegate call; that
+  /// is, the current function is delegating to another one.  Produce
+  /// a r-value suitable for passing the given parameter.
+  RValue EmitDelegateCallArg(const VarDecl *Param);
+
 private:
 
   void EmitReturnOfRValue(RValue RV, QualType Ty);