summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CGVtable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGVtable.cpp')
-rw-r--r--lib/CodeGen/CGVtable.cpp259
1 files changed, 192 insertions, 67 deletions
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index 7930f71..ae900d6 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -160,17 +160,19 @@ private:
// vtable for use in computing the initializers for the VTT.
llvm::DenseMap<CtorVtable_t, int64_t> &subAddressPoints;
+ /// AddressPoints - Address points for this vtable.
+ CGVtableInfo::AddressPointsMapTy& AddressPoints;
+
typedef CXXRecordDecl::method_iterator method_iter;
- const bool Extern;
const uint32_t LLVMPointerWidth;
Index_t extra;
typedef std::vector<std::pair<const CXXRecordDecl *, int64_t> > Path_t;
static llvm::DenseMap<CtorVtable_t, int64_t>&
AllocAddressPoint(CodeGenModule &cgm, const CXXRecordDecl *l,
const CXXRecordDecl *c) {
- CodeGenModule::AddrMap_t *&oref = cgm.AddressPoints[l];
+ CGVtableInfo::AddrMap_t *&oref = cgm.getVtableInfo().AddressPoints[l];
if (oref == 0)
- oref = new CodeGenModule::AddrMap_t;
+ oref = new CGVtableInfo::AddrMap_t;
llvm::DenseMap<CtorVtable_t, int64_t> *&ref = (*oref)[c];
if (ref == 0)
@@ -193,14 +195,15 @@ private:
public:
VtableBuilder(const CXXRecordDecl *MostDerivedClass,
const CXXRecordDecl *l, uint64_t lo, CodeGenModule &cgm,
- bool build)
+ bool build, CGVtableInfo::AddressPointsMapTy& AddressPoints)
: BuildVtable(build), MostDerivedClass(MostDerivedClass), LayoutClass(l),
LayoutOffset(lo), BLayout(cgm.getContext().getASTRecordLayout(l)),
rtti(0), VMContext(cgm.getModule().getContext()),CGM(cgm),
PureVirtualFn(0),
subAddressPoints(AllocAddressPoint(cgm, l, MostDerivedClass)),
- Extern(!l->isInAnonymousNamespace()),
- LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) {
+ AddressPoints(AddressPoints),
+ LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0))
+ {
Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
if (BuildVtable) {
QualType ClassType = CGM.getContext().getTagDeclType(MostDerivedClass);
@@ -213,7 +216,7 @@ public:
return VtableComponents;
}
- llvm::DenseMap<const CXXRecordDecl *, Index_t> &getVBIndex()
+ llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getVBIndex()
{ return VBIndex; }
SavedAdjustmentsVectorTy &getSavedAdjustments()
@@ -463,6 +466,7 @@ public:
RD->getNameAsCString(), Class->getNameAsCString(),
LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
+ AddressPoints[BaseSubobject(RD, Offset)] = AddressPoint;
// Now also add the address point for all our primary bases.
while (1) {
@@ -479,6 +483,7 @@ public:
RD->getNameAsCString(), Class->getNameAsCString(),
LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
+ AddressPoints[BaseSubobject(RD, Offset)] = AddressPoint;
}
}
@@ -827,7 +832,6 @@ bool VtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
MD->getNameAsString().c_str(), (int)-idx-3,
(int)VCalls[idx-1], Class->getNameAsCString()));
}
- VCall[GD] = idx;
int64_t NonVirtualAdjustment = NonVirtualOffset[GD];
int64_t VirtualAdjustment =
-((idx + extra + 2) * LLVMPointerWidth / 8);
@@ -844,6 +848,7 @@ bool VtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
SavedAdjustments.push_back(
std::make_pair(GD, std::make_pair(OGD, ThisAdjustment)));
}
+ VCall[GD] = idx;
return true;
}
@@ -1090,7 +1095,8 @@ CGVtableInfo::getAdjustments(GlobalDecl GD) {
if (!SavedAdjustmentRecords.insert(RD).second)
return 0;
- VtableBuilder b(RD, RD, 0, CGM, false);
+ AddressPointsMapTy AddressPoints;
+ VtableBuilder b(RD, RD, 0, CGM, false, AddressPoints);
D1(printf("vtable %s\n", RD->getNameAsCString()));
b.GenerateVtableForBase(RD);
b.GenerateVtableForVBases(RD);
@@ -1118,7 +1124,8 @@ int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
// FIXME: This seems expensive. Can we do a partial job to get
// just this data.
- VtableBuilder b(RD, RD, 0, CGM, false);
+ AddressPointsMapTy AddressPoints;
+ VtableBuilder b(RD, RD, 0, CGM, false, AddressPoints);
D1(printf("vtable %s\n", RD->getNameAsCString()));
b.GenerateVtableForBase(RD);
b.GenerateVtableForVBases(RD);
@@ -1139,7 +1146,7 @@ int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
uint64_t CGVtableInfo::getVtableAddressPoint(const CXXRecordDecl *RD) {
uint64_t AddressPoint =
- (*(*(CGM.AddressPoints[RD]))[RD])[std::make_pair(RD, 0)];
+ (*(*(CGM.getVtableInfo().AddressPoints[RD]))[RD])[std::make_pair(RD, 0)];
return AddressPoint;
}
@@ -1148,7 +1155,8 @@ llvm::GlobalVariable *
CGVtableInfo::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
bool GenerateDefinition,
const CXXRecordDecl *LayoutClass,
- const CXXRecordDecl *RD, uint64_t Offset) {
+ const CXXRecordDecl *RD, uint64_t Offset,
+ AddressPointsMapTy& AddressPoints) {
llvm::SmallString<256> OutName;
if (LayoutClass != RD)
CGM.getMangleContext().mangleCXXCtorVtable(LayoutClass, Offset / 8,
@@ -1158,8 +1166,10 @@ CGVtableInfo::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
llvm::StringRef Name = OutName.str();
llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
- if (GV == 0 || CGM.AddressPoints[LayoutClass] == 0 || GV->isDeclaration()) {
- VtableBuilder b(RD, LayoutClass, Offset, CGM, GenerateDefinition);
+ if (GV == 0 || CGM.getVtableInfo().AddressPoints[LayoutClass] == 0 ||
+ GV->isDeclaration()) {
+ VtableBuilder b(RD, LayoutClass, Offset, CGM, GenerateDefinition,
+ AddressPoints);
D1(printf("vtable %s\n", RD->getNameAsCString()));
// First comes the vtables for all the non-virtual bases...
@@ -1206,11 +1216,51 @@ class VTTBuilder {
/// BLayout - Layout for the most derived class that this vtable is being
/// built for.
const ASTRecordLayout &BLayout;
- CodeGenModule::AddrMap_t &AddressPoints;
+ CGVtableInfo::AddrMap_t &AddressPoints;
// vtbl - A pointer to the vtable for Class.
llvm::Constant *ClassVtbl;
llvm::LLVMContext &VMContext;
+ llvm::DenseMap<const CXXRecordDecl *, uint64_t> SubVTTIndicies;
+
+ bool GenerateDefinition;
+
+ llvm::DenseMap<BaseSubobject, llvm::Constant *> CtorVtables;
+ llvm::DenseMap<std::pair<const CXXRecordDecl *, BaseSubobject>, uint64_t>
+ CtorVtableAddressPoints;
+
+ llvm::Constant *getCtorVtable(const BaseSubobject &Base) {
+ if (!GenerateDefinition)
+ return 0;
+
+ llvm::Constant *&CtorVtable = CtorVtables[Base];
+ if (!CtorVtable) {
+ // Build the vtable.
+ CGVtableInfo::CtorVtableInfo Info
+ = CGM.getVtableInfo().getCtorVtable(Class, Base);
+
+ CtorVtable = Info.Vtable;
+
+ // Add the address points for this base.
+ for (CGVtableInfo::AddressPointsMapTy::const_iterator I =
+ Info.AddressPoints.begin(), E = Info.AddressPoints.end();
+ I != E; ++I) {
+ uint64_t &AddressPoint =
+ CtorVtableAddressPoints[std::make_pair(Base.getBase(), I->first)];
+
+ // Check if we already have the address points for this base.
+ if (AddressPoint)
+ break;
+
+ // Otherwise, insert it.
+ AddressPoint = I->second;
+ }
+ }
+
+ return CtorVtable;
+ }
+
+
/// BuildVtablePtr - Build up a referene to the given secondary vtable
llvm::Constant *BuildVtablePtr(llvm::Constant *Vtable,
const CXXRecordDecl *VtableClass,
@@ -1270,14 +1320,17 @@ class VTTBuilder {
// FIXME: Slightly too many of these for __ZTT8test8_B2
llvm::Constant *init;
if (BaseMorallyVirtual)
- init = BuildVtablePtr(vtbl, VtblClass, RD, Offset);
+ init = GenerateDefinition ?
+ BuildVtablePtr(vtbl, VtblClass, RD, Offset) : 0;
else {
- init = CGM.getVtableInfo().getCtorVtable(Class, Base, BaseOffset);
+ init = GenerateDefinition ?
+ getCtorVtable(BaseSubobject(Base, BaseOffset)) : 0;
subvtbl = init;
subVtblClass = Base;
- init = BuildVtablePtr(init, Class, Base, BaseOffset);
+ init = GenerateDefinition ?
+ BuildVtablePtr(init, Class, Base, BaseOffset) : 0;
}
Inits.push_back(init);
}
@@ -1296,14 +1349,16 @@ class VTTBuilder {
// First comes the primary virtual table pointer...
if (MorallyVirtual) {
- Vtable = ClassVtbl;
+ Vtable = GenerateDefinition ? ClassVtbl : 0;
VtableClass = Class;
} else {
- Vtable = CGM.getVtableInfo().getCtorVtable(Class, RD, Offset);
+ Vtable = GenerateDefinition ?
+ getCtorVtable(BaseSubobject(RD, Offset)) : 0;
VtableClass = RD;
}
- llvm::Constant *Init = BuildVtablePtr(Vtable, VtableClass, RD, Offset);
+ llvm::Constant *Init = GenerateDefinition ?
+ BuildVtablePtr(Vtable, VtableClass, RD, Offset) : 0;
Inits.push_back(Init);
// then the secondary VTTs....
@@ -1326,6 +1381,10 @@ class VTTBuilder {
continue;
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base);
+
+ // Remember the sub-VTT index.
+ SubVTTIndicies[Base] = Inits.size();
+
BuildVTT(Base, BaseOffset, MorallyVirtual);
}
}
@@ -1338,6 +1397,9 @@ class VTTBuilder {
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
if (i->isVirtual() && !SeenVBase.count(Base)) {
+ // Remember the sub-VTT index.
+ SubVTTIndicies[Base] = Inits.size();
+
SeenVBase.insert(Base);
uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
BuildVTT(Base, BaseOffset, true);
@@ -1348,15 +1410,18 @@ class VTTBuilder {
public:
VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c,
- CodeGenModule &cgm)
+ CodeGenModule &cgm, bool GenerateDefinition)
: Inits(inits), Class(c), CGM(cgm),
BLayout(cgm.getContext().getASTRecordLayout(c)),
- AddressPoints(*cgm.AddressPoints[c]),
- VMContext(cgm.getModule().getContext()) {
+ AddressPoints(*cgm.getVtableInfo().AddressPoints[c]),
+ VMContext(cgm.getModule().getContext()),
+ GenerateDefinition(GenerateDefinition) {
// First comes the primary virtual table pointer for the complete class...
ClassVtbl = CGM.getVtableInfo().getVtable(Class);
- Inits.push_back(BuildVtablePtr(ClassVtbl, Class, Class, 0));
+ llvm::Constant *Init = GenerateDefinition ?
+ BuildVtablePtr(ClassVtbl, Class, Class, 0) : 0;
+ Inits.push_back(Init);
// then the secondary VTTs...
SecondaryVTTs(Class);
@@ -1367,11 +1432,16 @@ public:
// and last, the virtual VTTs.
VirtualVTTs(Class);
}
+
+ llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getSubVTTIndicies() {
+ return SubVTTIndicies;
+ }
};
}
llvm::GlobalVariable *
CGVtableInfo::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
+ bool GenerateDefinition,
const CXXRecordDecl *RD) {
// Only classes that have virtual bases need a VTT.
if (RD->getNumVBases() == 0)
@@ -1381,23 +1451,36 @@ CGVtableInfo::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
CGM.getMangleContext().mangleCXXVTT(RD, OutName);
llvm::StringRef Name = OutName.str();
-
D1(printf("vtt %s\n", RD->getNameAsCString()));
- std::vector<llvm::Constant *> inits;
- VTTBuilder b(inits, RD, CGM);
+ llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
+ if (GV == 0 || GV->isDeclaration()) {
+ const llvm::Type *Int8PtrTy =
+ llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
- const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
- const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size());
-
- llvm::Constant *Init = llvm::ConstantArray::get(Type, inits);
-
- llvm::GlobalVariable *VTT =
- new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true,
- Linkage, Init, Name);
- CGM.setGlobalVisibility(VTT, RD);
+ std::vector<llvm::Constant *> inits;
+ VTTBuilder b(inits, RD, CGM, GenerateDefinition);
+
+ const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size());
+ llvm::Constant *Init = 0;
+ if (GenerateDefinition)
+ Init = llvm::ConstantArray::get(Type, inits);
+
+ llvm::GlobalVariable *OldGV = GV;
+ GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true,
+ Linkage, Init, Name);
+ CGM.setGlobalVisibility(GV, RD);
+
+ if (OldGV) {
+ GV->takeName(OldGV);
+ llvm::Constant *NewPtr =
+ llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
+ OldGV->replaceAllUsesWith(NewPtr);
+ OldGV->eraseFromParent();
+ }
+ }
- return VTT;
+ return GV;
}
void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
@@ -1408,28 +1491,44 @@ void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
return;
}
- Vtable = GenerateVtable(Linkage, /*GenerateDefinition=*/true, RD, RD, 0);
- GenerateVTT(Linkage, RD);
+ AddressPointsMapTy AddressPoints;
+ Vtable = GenerateVtable(Linkage, /*GenerateDefinition=*/true, RD, RD, 0,
+ AddressPoints);
+ GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD);
}
llvm::GlobalVariable *CGVtableInfo::getVtable(const CXXRecordDecl *RD) {
llvm::GlobalVariable *Vtable = Vtables.lookup(RD);
- if (!Vtable)
+ if (!Vtable) {
+ AddressPointsMapTy AddressPoints;
Vtable = GenerateVtable(llvm::GlobalValue::ExternalLinkage,
- /*GenerateDefinition=*/false, RD, RD, 0);
+ /*GenerateDefinition=*/false, RD, RD, 0,
+ AddressPoints);
+ }
return Vtable;
}
-llvm::GlobalVariable *
-CGVtableInfo::getCtorVtable(const CXXRecordDecl *LayoutClass,
- const CXXRecordDecl *RD, uint64_t Offset) {
- return GenerateVtable(llvm::GlobalValue::InternalLinkage,
- /*GenerateDefinition=*/true,
- LayoutClass, RD, Offset);
+CGVtableInfo::CtorVtableInfo
+CGVtableInfo::getCtorVtable(const CXXRecordDecl *RD,
+ const BaseSubobject &Base) {
+ CtorVtableInfo Info;
+
+ Info.Vtable = GenerateVtable(llvm::GlobalValue::InternalLinkage,
+ /*GenerateDefinition=*/true,
+ RD, Base.getBase(), Base.getBaseOffset(),
+ Info.AddressPoints);
+ return Info;
+}
+
+llvm::GlobalVariable *CGVtableInfo::getVTT(const CXXRecordDecl *RD) {
+ return GenerateVTT(llvm::GlobalValue::ExternalLinkage,
+ /*GenerateDefinition=*/false, RD);
+
}
+
void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
const CXXRecordDecl *RD = MD->getParent();
@@ -1445,28 +1544,10 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
// We don't have the right key function.
if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl())
return;
-
- // If the key function is a destructor, we only want to emit the vtable
- // once, so do it for the complete destructor.
- if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() != Dtor_Complete)
- return;
- } else {
- // If there is no key function, we only want to emit the vtable if we are
- // emitting a constructor.
- if (!isa<CXXConstructorDecl>(MD) || GD.getCtorType() != Ctor_Complete)
- return;
}
- llvm::GlobalVariable::LinkageTypes Linkage;
- if (RD->isInAnonymousNamespace() || !RD->hasLinkage())
- Linkage = llvm::GlobalVariable::InternalLinkage;
- else if (KeyFunction && !MD->isInlined())
- Linkage = llvm::GlobalVariable::ExternalLinkage;
- else
- Linkage = llvm::GlobalVariable::WeakODRLinkage;
-
// Emit the data.
- GenerateClassData(Linkage, RD);
+ GenerateClassData(CGM.getVtableLinkage(RD), RD);
for (CXXRecordDecl::method_iterator i = RD->method_begin(),
e = RD->method_end(); i != e; ++i) {
@@ -1481,3 +1562,47 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
}
}
+bool CGVtableInfo::needsVTTParameter(GlobalDecl GD) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
+ // We don't have any virtual bases, just return early.
+ if (!MD->getParent()->getNumVBases())
+ return false;
+
+ // Check if we have a base constructor.
+ if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
+ return true;
+
+ // Check if we have a base destructor.
+ if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
+ return true;
+
+ return false;
+}
+
+uint64_t CGVtableInfo::getSubVTTIndex(const CXXRecordDecl *RD,
+ const CXXRecordDecl *Base) {
+ ClassPairTy ClassPair(RD, Base);
+
+ SubVTTIndiciesTy::iterator I =
+ SubVTTIndicies.find(ClassPair);
+ if (I != SubVTTIndicies.end())
+ return I->second;
+
+ std::vector<llvm::Constant *> inits;
+ VTTBuilder Builder(inits, RD, CGM, /*GenerateDefinition=*/false);
+
+ for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
+ Builder.getSubVTTIndicies().begin(),
+ E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
+ // Insert all indices.
+ ClassPairTy ClassPair(RD, I->first);
+
+ SubVTTIndicies.insert(std::make_pair(ClassPair, I->second));
+ }
+
+ I = SubVTTIndicies.find(ClassPair);
+ assert(I != SubVTTIndicies.end() && "Did not find index!");
+
+ return I->second;
+}
OpenPOWER on IntegriCloud