}
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();
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);
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()) {
CodeGenFunction(*this).GenerateCovariantThunk(Fn, GD, Extern, CoAdj);
}
}
- BuildThunksForVirtualRecursive(GD, OGD);
}
}
public:
/// Index_t - Vtable index type.
typedef uint64_t Index_t;
+ typedef std::vector<std::pair<GlobalDecl,
+ std::pair<GlobalDecl, ThunkAdjustment> > >
+ SavedAdjustmentsVectorTy;
private:
// VtableComponents - The components of the vtable being built.
typedef llvm::DenseMap<uint64_t, ThunkAdjustment> ThisAdjustmentsMapTy;
ThisAdjustmentsMapTy ThisAdjustments;
- typedef std::vector<std::pair<std::pair<GlobalDecl, GlobalDecl>,
- ThunkAdjustment> > SavedThisAdjustmentsVectorTy;
- SavedThisAdjustmentsVectorTy SavedThisAdjustments;
+ SavedAdjustmentsVectorTy SavedAdjustments;
/// BaseReturnTypes - Contains the base return types of methods who have been
/// overridden with methods whose return types require adjustment. Used for
llvm::DenseMap<const CXXRecordDecl *, Index_t> &getVBIndex()
{ return VBIndex; }
- SavedThisAdjustmentsVectorTy &getSavedThisAdjustments()
- { return SavedThisAdjustments; }
+ SavedAdjustmentsVectorTy &getSavedAdjustments()
+ { return SavedAdjustments; }
llvm::Constant *wrap(Index_t i) {
llvm::Constant *m;
D1(printf(" vfn for %s at %d\n", MD->getNameAsString().c_str(),
(int)Index[GD]));
+
+ VCallOffset[GD] = Offset/8;
if (MorallyVirtual) {
- VCallOffset[GD] = Offset/8;
Index_t &idx = VCall[GD];
// Allocate the first one, after that, we reuse the previous one.
if (idx == 0) {
if (!isPure && !ThisAdjustment.isEmpty()) {
ThisAdjustments[Index] = ThisAdjustment;
- SavedThisAdjustments.push_back(std::make_pair(std::make_pair(GD, OGD),
- ThisAdjustment));
+ SavedAdjustments.push_back(
+ std::make_pair(GD, std::make_pair(OGD, ThisAdjustment)));
}
return true;
}
- // FIXME: finish off
- int64_t NonVirtualAdjustment = VCallOffset[OGD] - OverrideOffset/8;
+ int64_t NonVirtualAdjustment = -VCallOffset[OGD] + OverrideOffset/8;
if (NonVirtualAdjustment) {
ThunkAdjustment ThisAdjustment(NonVirtualAdjustment, 0);
if (!isPure) {
ThisAdjustments[Index] = ThisAdjustment;
- SavedThisAdjustments.push_back(std::make_pair(std::make_pair(GD, OGD),
- ThisAdjustment));
+ SavedAdjustments.push_back(
+ std::make_pair(GD, std::make_pair(OGD, ThisAdjustment)));
}
}
return true;
return I->second;
}
-ThunkAdjustment CGVtableInfo::getThisAdjustment(GlobalDecl GD,
- GlobalDecl OGD) {
- SavedThisAdjustmentsTy::iterator I =
- SavedThisAdjustments.find(std::make_pair(GD, OGD));
- if (I != SavedThisAdjustments.end())
- return I->second;
+CGVtableInfo::AdjustmentVectorTy*
+CGVtableInfo::getAdjustments(GlobalDecl GD) {
+ SavedAdjustmentsTy::iterator I = SavedAdjustments.find(GD);
+ if (I != SavedAdjustments.end())
+ return &I->second;
const CXXRecordDecl *RD = cast<CXXRecordDecl>(GD.getDecl()->getDeclContext());
- if (!SavedThisAdjustmentRecords.insert(RD).second)
- return ThunkAdjustment();
+ if (!SavedAdjustmentRecords.insert(RD).second)
+ return 0;
VtableBuilder b(RD, RD, 0, CGM, false);
D1(printf("vtable %s\n", RD->getNameAsCString()));
b.GenerateVtableForBase(RD);
b.GenerateVtableForVBases(RD);
-
- SavedThisAdjustments.insert(b.getSavedThisAdjustments().begin(),
- b.getSavedThisAdjustments().end());
- I = SavedThisAdjustments.find(std::make_pair(GD, OGD));
- if (I != SavedThisAdjustments.end())
- return I->second;
+ for (VtableBuilder::SavedAdjustmentsVectorTy::iterator
+ i = b.getSavedAdjustments().begin(),
+ e = b.getSavedAdjustments().end(); i != e; i++)
+ SavedAdjustments[i->first].push_back(i->second);
+
+ I = SavedAdjustments.find(GD);
+ if (I != SavedAdjustments.end())
+ return &I->second;
- return ThunkAdjustment();
+ return 0;
}
int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
for (CXXRecordDecl::method_iterator i = RD->method_begin(),
e = RD->method_end(); i != e; ++i) {
- if ((*i)->isVirtual() && (*i)->hasInlineBody()) {
+ if ((*i)->isVirtual() && ((*i)->hasInlineBody() || (*i)->isImplicit())) {
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(*i)) {
CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Complete));
CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Deleting));
};
class CGVtableInfo {
+public:
+ typedef std::vector<std::pair<GlobalDecl, ThunkAdjustment> >
+ AdjustmentVectorTy;
+
+private:
CodeGenModule &CGM;
/// MethodVtableIndices - Contains the index (relative to the vtable address
/// pointers in the vtable for a given record decl.
llvm::DenseMap<const CXXRecordDecl *, uint64_t> NumVirtualFunctionPointers;
- typedef llvm::DenseMap<std::pair<GlobalDecl, GlobalDecl>,
- ThunkAdjustment> SavedThisAdjustmentsTy;
- SavedThisAdjustmentsTy SavedThisAdjustments;
- llvm::DenseSet<const CXXRecordDecl*> SavedThisAdjustmentRecords;
+ typedef llvm::DenseMap<GlobalDecl, AdjustmentVectorTy> SavedAdjustmentsTy;
+ SavedAdjustmentsTy SavedAdjustments;
+ llvm::DenseSet<const CXXRecordDecl*> SavedAdjustmentRecords;
/// getNumVirtualFunctionPointers - Return the number of virtual function
/// pointers in the vtable for a given record decl.
int64_t getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
const CXXRecordDecl *VBase);
- ThunkAdjustment getThisAdjustment(GlobalDecl GD, GlobalDecl OGD);
+ AdjustmentVectorTy *getAdjustments(GlobalDecl GD);
/// getVtableAddressPoint - returns the address point of the vtable for the
/// given record decl.