diff options
author | John McCall <rjmccall@apple.com> | 2010-05-26 22:34:26 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-05-26 22:34:26 +0000 |
commit | 2736071ea3a46f90e65c93418961611d96c10ab9 (patch) | |
tree | 02cc651ea6a90418c76fa7a7a7adf9b118faa73b /lib/CodeGen/CGCall.cpp | |
parent | 12e131385e892e3723483a1081a89bcad29c8a84 (diff) |
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
Diffstat (limited to 'lib/CodeGen/CGCall.cpp')
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 0d6a70c64d..73cee3c10d 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -862,6 +862,36 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, } } +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); |