[cfe-commits] r88663 - in /cfe/trunk/lib/CodeGen: CGCXX.cpp CGVtable.cpp CGVtable.h
Anders Carlsson
andersca at mac.com
Fri Nov 13 09:08:56 PST 2009
Author: andersca
Date: Fri Nov 13 11:08:56 2009
New Revision: 88663
URL: http://llvm.org/viewvc/llvm-project?rev=88663&view=rev
Log:
Instead of storing CXXMethodDecls in the vtable builder, store GlobalDecls so we can represent both the complete and deleting destructors. Also, when encountering a destructor decl, emit entries for both the complete and deleting destructors. Mike, please review.
With this change, FileCheck builds and runs the clang test suite without failures!
Modified:
cfe/trunk/lib/CodeGen/CGCXX.cpp
cfe/trunk/lib/CodeGen/CGVtable.cpp
cfe/trunk/lib/CodeGen/CGVtable.h
Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=88663&r1=88662&r2=88663&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Fri Nov 13 11:08:56 2009
@@ -1011,7 +1011,7 @@
llvm::Value *&This, const llvm::Type *Ty) {
DD = cast<CXXDestructorDecl>(DD->getCanonicalDecl());
int64_t VtableIndex =
- CGM.getVtableInfo().getMethodVtableIndex(DD);
+ CGM.getVtableInfo().getMethodVtableIndex(GlobalDecl(DD, Type));
return ::BuildVirtualCall(*this, VtableIndex, This, Ty);
}
Modified: cfe/trunk/lib/CodeGen/CGVtable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVtable.cpp?rev=88663&r1=88662&r2=88663&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGVtable.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVtable.cpp Fri Nov 13 11:08:56 2009
@@ -45,19 +45,19 @@
CodeGenModule &CGM; // Per-module state.
/// Index - Maps a method decl into a vtable index. Useful for virtual
/// dispatch codegen.
- llvm::DenseMap<const CXXMethodDecl *, Index_t> Index;
- llvm::DenseMap<const CXXMethodDecl *, Index_t> VCall;
- llvm::DenseMap<const CXXMethodDecl *, Index_t> VCallOffset;
+ llvm::DenseMap<GlobalDecl, Index_t> Index;
+ llvm::DenseMap<GlobalDecl, Index_t> VCall;
+ llvm::DenseMap<GlobalDecl, Index_t> VCallOffset;
// This is the offset to the nearest virtual base
- llvm::DenseMap<const CXXMethodDecl *, Index_t> NonVirtualOffset;
+ llvm::DenseMap<GlobalDecl, Index_t> NonVirtualOffset;
llvm::DenseMap<const CXXRecordDecl *, Index_t> VBIndex;
- typedef llvm::DenseMap<const CXXMethodDecl *, int> Pures_t;
+ typedef llvm::DenseMap<GlobalDecl, int> Pures_t;
Pures_t Pures;
typedef std::pair<Index_t, Index_t> CallOffset;
- typedef llvm::DenseMap<const CXXMethodDecl *, CallOffset> Thunks_t;
+ typedef llvm::DenseMap<GlobalDecl, CallOffset> Thunks_t;
Thunks_t Thunks;
- typedef llvm::DenseMap<const CXXMethodDecl *,
+ typedef llvm::DenseMap<GlobalDecl,
std::pair<std::pair<CallOffset, CallOffset>,
CanQualType> > CovariantThunks_t;
CovariantThunks_t CovariantThunks;
@@ -94,7 +94,7 @@
cxa_pure = wrap(CGM.CreateRuntimeFunction(FTy, "__cxa_pure_virtual"));
}
- llvm::DenseMap<const CXXMethodDecl *, Index_t> &getIndex() { return Index; }
+ llvm::DenseMap<GlobalDecl, Index_t> &getIndex() { return Index; }
llvm::DenseMap<const CXXRecordDecl *, Index_t> &getVBIndex()
{ return VBIndex; }
@@ -205,9 +205,11 @@
return 0;
}
- bool OverrideMethod(const CXXMethodDecl *MD, llvm::Constant *m,
+ bool OverrideMethod(GlobalDecl GD, llvm::Constant *m,
bool MorallyVirtual, Index_t OverrideOffset,
Index_t Offset, int64_t CurrentVBaseOffset) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
const bool isPure = MD->isPure();
typedef CXXMethodDecl::method_iterator meth_iter;
// FIXME: Should OverrideOffset's be Offset?
@@ -220,9 +222,16 @@
for (meth_iter mi = MD->begin_overridden_methods(),
e = MD->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 = OMD;
+
llvm::Constant *om;
- om = CGM.GetAddrOfFunction(OMD, Ptr8Ty);
+ om = WrapAddrOf(OGD);
om = llvm::ConstantExpr::getBitCast(om, Ptr8Ty);
for (Index_t i = 0, e = submethods.size();
@@ -245,32 +254,32 @@
Index_t nv = getNVOffset(oret, ret)/8;
ReturnOffset = std::make_pair(nv, getVbaseOffset(oret, ret));
}
- Index[MD] = i;
+ Index[GD] = i;
submethods[i] = m;
if (isPure)
- Pures[MD] = 1;
- Pures.erase(OMD);
- Thunks.erase(OMD);
- if (MorallyVirtual || VCall.count(OMD)) {
- Index_t &idx = VCall[OMD];
+ Pures[GD] = 1;
+ Pures.erase(OGD);
+ Thunks.erase(OGD);
+ if (MorallyVirtual || VCall.count(OGD)) {
+ Index_t &idx = VCall[OGD];
if (idx == 0) {
- NonVirtualOffset[MD] = -OverrideOffset/8 + CurrentVBaseOffset/8;
- VCallOffset[MD] = OverrideOffset/8;
+ NonVirtualOffset[GD] = -OverrideOffset/8 + CurrentVBaseOffset/8;
+ VCallOffset[GD] = OverrideOffset/8;
idx = VCalls.size()+1;
VCalls.push_back(0);
D1(printf(" vcall for %s at %d with delta %d most derived %s\n",
MD->getNameAsCString(), (int)-idx-3, (int)VCalls[idx-1],
Class->getNameAsCString()));
} else {
- NonVirtualOffset[MD] = NonVirtualOffset[OMD];
- VCallOffset[MD] = VCallOffset[OMD];
- VCalls[idx-1] = -VCallOffset[OMD] + OverrideOffset/8;
+ NonVirtualOffset[GD] = NonVirtualOffset[OGD];
+ VCallOffset[GD] = VCallOffset[OGD];
+ VCalls[idx-1] = -VCallOffset[OGD] + OverrideOffset/8;
D1(printf(" vcall patch for %s at %d with delta %d most derived %s\n",
MD->getNameAsCString(), (int)-idx-3, (int)VCalls[idx-1],
Class->getNameAsCString()));
}
- VCall[MD] = idx;
- int64_t O = NonVirtualOffset[MD];
+ VCall[GD] = idx;
+ int64_t O = NonVirtualOffset[GD];
int v = -((idx+extra+2)*LLVMPointerWidth/8);
// Optimize out virtual adjustments of 0.
if (VCalls[idx-1] == 0)
@@ -279,26 +288,26 @@
// FIXME: Do we always have to build a covariant thunk to save oret,
// which is the containing virtual base class?
if (ReturnOffset.first || ReturnOffset.second)
- CovariantThunks[MD] = std::make_pair(std::make_pair(ThisOffset,
+ CovariantThunks[GD] = std::make_pair(std::make_pair(ThisOffset,
ReturnOffset),
oret);
else if (!isPure && (ThisOffset.first || ThisOffset.second))
- Thunks[MD] = ThisOffset;
+ Thunks[GD] = ThisOffset;
return true;
}
// FIXME: finish off
- int64_t O = VCallOffset[OMD] - OverrideOffset/8;
+ int64_t O = VCallOffset[OGD] - OverrideOffset/8;
if (O || ReturnOffset.first || ReturnOffset.second) {
CallOffset ThisOffset = std::make_pair(O, 0);
if (ReturnOffset.first || ReturnOffset.second)
- CovariantThunks[MD] = std::make_pair(std::make_pair(ThisOffset,
+ CovariantThunks[GD] = std::make_pair(std::make_pair(ThisOffset,
ReturnOffset),
oret);
else if (!isPure)
- Thunks[MD] = ThisOffset;
+ Thunks[GD] = ThisOffset;
}
return true;
}
@@ -310,9 +319,10 @@
void InstallThunks() {
for (Thunks_t::iterator i = Thunks.begin(), e = Thunks.end();
i != e; ++i) {
- const CXXMethodDecl *MD = i->first;
+ GlobalDecl GD = i->first;
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
assert(!MD->isPure() && "Trying to thunk a pure");
- Index_t idx = Index[MD];
+ Index_t idx = Index[GD];
Index_t nv_O = i->second.first;
Index_t v_O = i->second.second;
submethods[idx] = CGM.BuildThunk(MD, Extern, nv_O, v_O);
@@ -321,10 +331,11 @@
for (CovariantThunks_t::iterator i = CovariantThunks.begin(),
e = CovariantThunks.end();
i != e; ++i) {
- const CXXMethodDecl *MD = i->first;
+ GlobalDecl GD = i->first;
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
if (MD->isPure())
continue;
- Index_t idx = Index[MD];
+ Index_t idx = Index[GD];
Index_t nv_t = i->second.first.first.first;
Index_t v_t = i->second.first.first.second;
Index_t nv_r = i->second.first.second.first;
@@ -335,16 +346,18 @@
CovariantThunks.clear();
for (Pures_t::iterator i = Pures.begin(), e = Pures.end();
i != e; ++i) {
- const CXXMethodDecl *MD = i->first;
- Index_t idx = Index[MD];
+ GlobalDecl GD = i->first;
+ Index_t idx = Index[GD];
submethods[idx] = cxa_pure;
}
Pures.clear();
}
- llvm::Constant *WrapAddrOf(const CXXMethodDecl *MD) {
+ llvm::Constant *WrapAddrOf(GlobalDecl GD) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD))
- return wrap(CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete));
+ return wrap(CGM.GetAddrOfCXXDestructor(Dtor, GD.getDtorType()));
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
const llvm::Type *Ty =
@@ -362,38 +375,51 @@
int64_t OverrideOffset = i->second;
for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
++mi) {
- if (!mi->isVirtual())
+ const CXXMethodDecl *MD = *mi;
+
+ if (!MD->isVirtual())
continue;
- const CXXMethodDecl *MD = *mi;
- llvm::Constant *m = WrapAddrOf(MD);
- OverrideMethod(MD, m, MorallyVirtual, OverrideOffset, Offset,
- CurrentVBaseOffset);
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
+ // Override both the complete and the deleting destructor.
+ GlobalDecl CompDtor(DD, Dtor_Complete);
+ OverrideMethod(CompDtor, WrapAddrOf(CompDtor), MorallyVirtual,
+ OverrideOffset, Offset, CurrentVBaseOffset);
+
+ GlobalDecl DeletingDtor(DD, Dtor_Deleting);
+ OverrideMethod(DeletingDtor, WrapAddrOf(DeletingDtor), MorallyVirtual,
+ OverrideOffset, Offset, CurrentVBaseOffset);
+ } else {
+ OverrideMethod(MD, WrapAddrOf(MD), MorallyVirtual, OverrideOffset,
+ Offset, CurrentVBaseOffset);
+ }
}
}
}
- void AddMethod(const CXXMethodDecl *MD, bool MorallyVirtual, Index_t Offset,
+ void AddMethod(const GlobalDecl GD, bool MorallyVirtual, Index_t Offset,
bool ForVirtualBase, int64_t CurrentVBaseOffset) {
- llvm::Constant *m = WrapAddrOf(MD);
+ llvm::Constant *m = WrapAddrOf(GD);
// If we can find a previously allocated slot for this, reuse it.
- if (OverrideMethod(MD, m, MorallyVirtual, Offset, Offset,
+ if (OverrideMethod(GD, m, MorallyVirtual, Offset, Offset,
CurrentVBaseOffset))
return;
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
// else allocate a new slot.
- Index[MD] = submethods.size();
+ Index[GD] = submethods.size();
submethods.push_back(m);
D1(printf(" vfn for %s at %d\n", MD->getNameAsCString(), (int)Index[MD]));
if (MD->isPure())
- Pures[MD] = 1;
+ Pures[GD] = 1;
if (MorallyVirtual) {
- VCallOffset[MD] = Offset/8;
- Index_t &idx = VCall[MD];
+ VCallOffset[GD] = Offset/8;
+ Index_t &idx = VCall[GD];
// Allocate the first one, after that, we reuse the previous one.
if (idx == 0) {
- NonVirtualOffset[MD] = CurrentVBaseOffset/8 - Offset/8;
+ NonVirtualOffset[GD] = CurrentVBaseOffset/8 - Offset/8;
idx = VCalls.size()+1;
VCalls.push_back(0);
D1(printf(" vcall for %s at %d with delta %d\n",
@@ -406,10 +432,22 @@
Index_t Offset, bool RDisVirtualBase,
int64_t CurrentVBaseOffset) {
for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
- ++mi)
- if (mi->isVirtual())
- AddMethod(*mi, MorallyVirtual, Offset, RDisVirtualBase,
+ ++mi) {
+ const CXXMethodDecl *MD = *mi;
+ if (!MD->isVirtual())
+ continue;
+
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
+ // For destructors, add both the complete and the deleting destructor
+ // to the vtable.
+ AddMethod(GlobalDecl(DD, Dtor_Complete), MorallyVirtual, Offset,
+ RDisVirtualBase, CurrentVBaseOffset);
+ AddMethod(GlobalDecl(DD, Dtor_Deleting), MorallyVirtual, Offset,
+ RDisVirtualBase, CurrentVBaseOffset);
+ } else
+ AddMethod(MD, MorallyVirtual, Offset, RDisVirtualBase,
CurrentVBaseOffset);
+ }
}
void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
@@ -663,14 +701,12 @@
return CGM.getVtableInfo().getVirtualBaseOffsetIndex(D, B);
}
-int64_t CGVtableInfo::getMethodVtableIndex(const CXXMethodDecl *MD) {
- MD = MD->getCanonicalDecl();
-
- MethodVtableIndicesTy::iterator I = MethodVtableIndices.find(MD);
+int64_t CGVtableInfo::getMethodVtableIndex(GlobalDecl GD) {
+ MethodVtableIndicesTy::iterator I = MethodVtableIndices.find(GD);
if (I != MethodVtableIndices.end())
return I->second;
- const CXXRecordDecl *RD = MD->getParent();
+ const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
std::vector<llvm::Constant *> methods;
// FIXME: This seems expensive. Can we do a partial job to get
@@ -683,7 +719,7 @@
MethodVtableIndices.insert(b.getIndex().begin(),
b.getIndex().end());
- I = MethodVtableIndices.find(MD);
+ I = MethodVtableIndices.find(GD);
assert(I != MethodVtableIndices.end() && "Did not find index!");
return I->second;
}
Modified: cfe/trunk/lib/CodeGen/CGVtable.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVtable.h?rev=88663&r1=88662&r2=88663&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGVtable.h (original)
+++ cfe/trunk/lib/CodeGen/CGVtable.h Fri Nov 13 11:08:56 2009
@@ -15,6 +15,7 @@
#define CLANG_CODEGEN_CGVTABLE_H
#include "llvm/ADT/DenseMap.h"
+#include "GlobalDecl.h"
namespace clang {
class CXXMethodDecl;
@@ -28,7 +29,7 @@
/// MethodVtableIndices - Contains the index (relative to the vtable address
/// point) where the function pointer for a virtual function is stored.
- typedef llvm::DenseMap<const CXXMethodDecl *, int64_t> MethodVtableIndicesTy;
+ typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVtableIndicesTy;
MethodVtableIndicesTy MethodVtableIndices;
typedef std::pair<const CXXRecordDecl *,
@@ -47,7 +48,7 @@
/// getMethodVtableIndex - Return the index (relative to the vtable address
/// point) where the function pointer for the given virtual function is
/// stored.
- int64_t getMethodVtableIndex(const CXXMethodDecl *MD);
+ int64_t getMethodVtableIndex(GlobalDecl GD);
/// getVirtualBaseOffsetIndex - Return the index (relative to the vtable
/// address point) where the offset of the virtual base that contains the
More information about the cfe-commits
mailing list