llvm::DenseMap<std::pair<const CXXRecordDecl *, BaseSubobject>, uint64_t>
CtorVtableAddressPoints;
- llvm::Constant *getCtorVtable(const BaseSubobject &Base) {
+ llvm::Constant *getCtorVtable(const BaseSubobject &Base,
+ bool BaseIsVirtual) {
if (!GenerateDefinition)
return 0;
if (!CtorVtable) {
// Build the vtable.
CGVtableInfo::CtorVtableInfo Info
- = CGM.getVtableInfo().getCtorVtable(Class, Base);
+ = CGM.getVtableInfo().getCtorVtable(Class, Base, BaseIsVirtual);
CtorVtable = Info.Vtable;
if (BaseMorallyVirtual || VtblClass == Class)
init = BuildVtablePtr(vtbl, VtblClass, Base, BaseOffset);
else {
- init = getCtorVtable(BaseSubobject(Base, BaseOffset));
+ init = getCtorVtable(BaseSubobject(Base, BaseOffset), i->isVirtual());
subvtbl = init;
subVtblClass = Base;
/// BuiltVTT - Add the VTT to Inits. Offset is the offset in bits to the
/// currnet object we're working on.
- void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool MorallyVirtual) {
+ void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool BaseIsVirtual,
+ bool MorallyVirtual) {
// Itanium C++ ABI 2.6.2:
// An array of virtual table addresses, called the VTT, is declared for
// each class type that has indirect or direct virtual base classes.
Vtable = ClassVtbl;
VtableClass = Class;
} else {
- Vtable = getCtorVtable(BaseSubobject(RD, Offset));
+ Vtable = getCtorVtable(BaseSubobject(RD, Offset),
+ /*IsVirtual=*/BaseIsVirtual);
VtableClass = RD;
}
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base);
- BuildVTT(Base, BaseOffset, MorallyVirtual);
+ BuildVTT(Base, BaseOffset, /*BaseIsVirtual=*/false, MorallyVirtual);
}
}
if (i->isVirtual() && !SeenVBase.count(Base)) {
SeenVBase.insert(Base);
uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
- BuildVTT(Base, BaseOffset, false);
+ BuildVTT(Base, BaseOffset, /*BaseIsVirtual=*/true, false);
}
VirtualVTTs(Base);
}
CGVtableInfo::CtorVtableInfo
CGVtableInfo::getCtorVtable(const CXXRecordDecl *RD,
- const BaseSubobject &Base) {
+ const BaseSubobject &Base, bool BaseIsVirtual) {
CtorVtableInfo Info;
Info.Vtable = GenerateVtable(llvm::GlobalValue::InternalLinkage,
/*GenerateDefinition=*/true,
RD, Base.getBase(), Base.getBaseOffset(),
- Info.AddressPoints);
+ BaseIsVirtual, Info.AddressPoints);
return Info;
}
/// holds the offset from the layout class to the most derived class.
const uint64_t MostDerivedClassOffset;
+ /// MostDerivedClassIsVirtual - Whether the most derived class is a virtual
+ /// base. (This only makes sense when building a construction vtable).
+ bool MostDerivedClassIsVirtual;
+
/// LayoutClass - The class we're using for layout information. Will be
/// different than the most derived class if we're building a construction
/// vtable.
void AddMethods(BaseSubobject Base, BaseSubobject FirstBaseInPrimaryBaseChain,
PrimaryBasesSetVectorTy &PrimaryBases);
- // LayoutVtable - Layout the vtable for the most derived class, including its
+ // LayoutVtable - Layout the vtable for the given base class, including its
// secondary vtables and any vtables for virtual bases.
void LayoutVtable();
public:
VtableBuilder(CGVtableInfo &VtableInfo, const CXXRecordDecl *MostDerivedClass,
- uint64_t MostDerivedClassOffset,
+ uint64_t MostDerivedClassOffset, bool MostDerivedClassIsVirtual,
const CXXRecordDecl *LayoutClass)
: VtableInfo(VtableInfo), MostDerivedClass(MostDerivedClass),
- MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass),
- Context(MostDerivedClass->getASTContext()), Overriders(MostDerivedClass) {
+ MostDerivedClassOffset(MostDerivedClassOffset),
+ MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
+ LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()),
+ Overriders(MostDerivedClass) {
LayoutVtable();
}
void VtableBuilder::LayoutVtable() {
LayoutPrimaryAndAndSecondaryVtables(BaseSubobject(MostDerivedClass, 0),
- /*BaseIsVirtual=*/false);
+ MostDerivedClassIsVirtual);
VisitedVirtualBasesSetTy VBases;
bool GenerateDefinition,
const CXXRecordDecl *LayoutClass,
const CXXRecordDecl *RD, uint64_t Offset,
+ bool IsVirtual,
AddressPointsMapTy& AddressPoints) {
if (GenerateDefinition) {
if (LayoutClass == RD) {
- VtableBuilder Builder(*this, RD, Offset, LayoutClass);
+ assert(!IsVirtual &&
+ "Can't only have a virtual base in construction vtables!");
+ VtableBuilder Builder(*this, RD, Offset,
+ /*MostDerivedClassIsVirtual=*/false,
+ LayoutClass);
if (CGM.getLangOptions().DumpVtableLayouts)
Builder.dumpLayout(llvm::errs());
} else if (CGM.getLangOptions().DumpVtableLayouts) {
// We only build construction vtables when dumping vtable layouts for now.
- VtableBuilder Builder(*this, RD, Offset, LayoutClass);
+ VtableBuilder Builder(*this, RD, Offset,
+ /*MostDerivedClassIsVirtual=*/IsVirtual,
+ LayoutClass);
Builder.dumpLayout(llvm::errs());
}
}
AddressPointsMapTy AddressPoints;
Vtable = GenerateVtable(Linkage, /*GenerateDefinition=*/true, RD, RD, 0,
+ /*IsVirtual=*/false,
AddressPoints);
GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD);
}
AddressPointsMapTy AddressPoints;
Vtable = GenerateVtable(llvm::GlobalValue::ExternalLinkage,
/*GenerateDefinition=*/false, RD, RD, 0,
- AddressPoints);
+ /*IsVirtual=*/false, AddressPoints);
}
return Vtable;
llvm::GlobalVariable *
GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
bool GenerateDefinition, const CXXRecordDecl *LayoutClass,
- const CXXRecordDecl *RD, uint64_t Offset,
+ const CXXRecordDecl *RD, uint64_t Offset, bool IsVirtual,
AddressPointsMapTy& AddressPoints);
llvm::GlobalVariable *GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
};
CtorVtableInfo getCtorVtable(const CXXRecordDecl *RD,
- const BaseSubobject &Base);
+ const BaseSubobject &Base,
+ bool BaseIsVirtual);
llvm::GlobalVariable *getVTT(const CXXRecordDecl *RD);