aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGCXX.cpp
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2009-12-07 23:56:34 +0000
committerEli Friedman <eli.friedman@gmail.com>2009-12-07 23:56:34 +0000
commitb455f0e74be0144ab9738ef574d07bd661959525 (patch)
treefe85af62b94205320c712f6347a48604ecee9075 /lib/CodeGen/CGCXX.cpp
parentcce3d4f9812182ed4e551b7cf0fc86576be8d9c5 (diff)
A bunch more thunk fixes from misc testing.
(Yes, I do intend to commit some tests for this.) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90818 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGCXX.cpp')
-rw-r--r--lib/CodeGen/CGCXX.cpp46
1 files changed, 26 insertions, 20 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 77bee48b58..d82f935971 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -1030,23 +1030,14 @@ CodeGenModule::GetAddrOfCovariantThunk(GlobalDecl GD,
}
void CodeGenModule::BuildThunksForVirtual(GlobalDecl GD) {
- BuildThunksForVirtualRecursive(GD, GD);
-}
-
-void
-CodeGenModule::BuildThunksForVirtualRecursive(GlobalDecl GD,
- GlobalDecl BaseOGD) {
+ CGVtableInfo::AdjustmentVectorTy *AdjPtr = getVtableInfo().getAdjustments(GD);
+ if (!AdjPtr)
+ return;
+ CGVtableInfo::AdjustmentVectorTy &Adj = *AdjPtr;
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
- const CXXMethodDecl *BaseOMD = cast<CXXMethodDecl>(BaseOGD.getDecl());
- for (CXXMethodDecl::method_iterator mi = BaseOMD->begin_overridden_methods(),
- e = BaseOMD->end_overridden_methods();
- mi != e; ++mi) {
- GlobalDecl OGD;
- const CXXMethodDecl *OMD = *mi;
- if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(OMD))
- OGD = GlobalDecl(DD, GD.getDtorType());
- else
- OGD = GlobalDecl(OMD);
+ for (unsigned i = 0; i < Adj.size(); i++) {
+ GlobalDecl OGD = Adj[i].first;
+ const CXXMethodDecl *OMD = cast<CXXMethodDecl>(OGD.getDecl());
QualType nc_oret = OMD->getType()->getAs<FunctionType>()->getResultType();
CanQualType oret = getContext().getCanonicalType(nc_oret);
QualType nc_ret = MD->getType()->getAs<FunctionType>()->getResultType();
@@ -1059,8 +1050,7 @@ CodeGenModule::BuildThunksForVirtualRecursive(GlobalDecl GD,
CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
ReturnAdjustment = ComputeThunkAdjustment(D, B);
}
- ThunkAdjustment ThisAdjustment =
- getVtableInfo().getThisAdjustment(GD, OGD);
+ ThunkAdjustment ThisAdjustment = Adj[i].second;
bool Extern = !cast<CXXRecordDecl>(OMD->getDeclContext())->isInAnonymousNamespace();
if (!ReturnAdjustment.isEmpty() || !ThisAdjustment.isEmpty()) {
CovariantThunkAdjustment CoAdj(ThisAdjustment, ReturnAdjustment);
@@ -1070,7 +1060,24 @@ CodeGenModule::BuildThunksForVirtualRecursive(GlobalDecl GD,
else
FnConst = GetAddrOfThunk(GD, ThisAdjustment);
if (!isa<llvm::Function>(FnConst)) {
- assert(0 && "Figure out how to handle incomplete-type cases!");
+ llvm::Constant *SubExpr =
+ cast<llvm::ConstantExpr>(FnConst)->getOperand(0);
+ llvm::Function *OldFn = cast<llvm::Function>(SubExpr);
+ std::string Name = OldFn->getNameStr();
+ GlobalDeclMap.erase(UniqueMangledName(Name.data(),
+ Name.data() + Name.size() + 1));
+ llvm::Constant *NewFnConst;
+ if (!ReturnAdjustment.isEmpty())
+ NewFnConst = GetAddrOfCovariantThunk(GD, CoAdj);
+ else
+ NewFnConst = GetAddrOfThunk(GD, ThisAdjustment);
+ llvm::Function *NewFn = cast<llvm::Function>(NewFnConst);
+ NewFn->takeName(OldFn);
+ llvm::Constant *NewPtrForOldDecl =
+ llvm::ConstantExpr::getBitCast(NewFn, OldFn->getType());
+ OldFn->replaceAllUsesWith(NewPtrForOldDecl);
+ OldFn->eraseFromParent();
+ FnConst = NewFn;
}
llvm::Function *Fn = cast<llvm::Function>(FnConst);
if (Fn->isDeclaration()) {
@@ -1085,7 +1092,6 @@ CodeGenModule::BuildThunksForVirtualRecursive(GlobalDecl GD,
CodeGenFunction(*this).GenerateCovariantThunk(Fn, GD, Extern, CoAdj);
}
}
- BuildThunksForVirtualRecursive(GD, OGD);
}
}