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);