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 | |
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
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 30 | ||||
-rw-r--r-- | lib/CodeGen/CGClass.cpp | 27 | ||||
-rw-r--r-- | lib/CodeGen/CGVTables.cpp | 9 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 5 | ||||
-rw-r--r-- | test/CodeGenCXX/thunks.cpp | 18 |
5 files changed, 55 insertions, 34 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); diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 587a68beb2..bebea549f9 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -1137,34 +1137,9 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, // 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 8bdd4588d4..0f023e63ae 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -2641,14 +2641,7 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD, 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 944aa48044..ece275e762 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1302,6 +1302,11 @@ public: /// 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); diff --git a/test/CodeGenCXX/thunks.cpp b/test/CodeGenCXX/thunks.cpp index b6e18e6e01..79ca709f47 100644 --- a/test/CodeGenCXX/thunks.cpp +++ b/test/CodeGenCXX/thunks.cpp @@ -218,6 +218,24 @@ namespace Test7 { void testD() { D d; } } +namespace Test8 { + struct NonPOD { ~NonPOD(); int x, y, z; }; + struct A { virtual void foo(); }; + struct B { virtual void bar(NonPOD); }; + struct C : A, B { virtual void bar(NonPOD); static void helper(NonPOD); }; + + // CHECK: define void @_ZN5Test81C6helperENS_6NonPODE([[NONPODTYPE:%.*]]* + void C::helper(NonPOD var) {} + + // CHECK: define void @_ZThn8_N5Test81C3barENS_6NonPODE( + // CHECK-NOT: load [[NONPODTYPE]]* + // CHECK-NOT: memcpy + // CHECK: ret void + void C::bar(NonPOD var) {} +} + +/**** The following has to go at the end of the file ****/ + // This is from Test5: // CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv // CHECK: define internal void @_ZThn8_N12_GLOBAL__N_11C1fEv( |