diff options
-rw-r--r-- | include/clang/AST/VTTBuilder.h | 176 | ||||
-rw-r--r-- | lib/AST/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/AST/VTTBuilder.cpp | 212 | ||||
-rw-r--r-- | lib/CodeGen/CGVTT.cpp | 338 |
4 files changed, 390 insertions, 337 deletions
diff --git a/include/clang/AST/VTTBuilder.h b/include/clang/AST/VTTBuilder.h new file mode 100644 index 0000000000..6756dd1e99 --- /dev/null +++ b/include/clang/AST/VTTBuilder.h @@ -0,0 +1,176 @@ +//===--- VTTBuilder.h - C++ VTT layout builder --------------------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code dealing with generation of the layout of virtual table +// tables (VTT). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_VTTBUILDER_H +#define LLVM_CLANG_AST_VTTBUILDER_H + +#include "clang/AST/BaseSubobject.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/GlobalDecl.h" +#include "clang/AST/RecordLayout.h" +#include "clang/Basic/ABI.h" +#include "llvm/ADT/SetVector.h" +#include <utility> + +namespace clang { + +class VTTVTable { + llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> BaseAndIsVirtual; + CharUnits BaseOffset; + +public: + VTTVTable() {} + VTTVTable(const CXXRecordDecl *Base, CharUnits BaseOffset, bool BaseIsVirtual) + : BaseAndIsVirtual(Base, BaseIsVirtual), BaseOffset(BaseOffset) {} + VTTVTable(BaseSubobject Base, bool BaseIsVirtual) + : BaseAndIsVirtual(Base.getBase(), BaseIsVirtual), + BaseOffset(Base.getBaseOffset()) {} + + const CXXRecordDecl *getBase() const { + return BaseAndIsVirtual.getPointer(); + } + + CharUnits getBaseOffset() const { + return BaseOffset; + } + + bool isVirtual() const { + return BaseAndIsVirtual.getInt(); + } + + BaseSubobject getBaseSubobject() const { + return BaseSubobject(getBase(), getBaseOffset()); + } +}; + +struct VTTComponent { + uint64_t VTableIndex; + BaseSubobject VTableBase; + + VTTComponent() {} + VTTComponent(uint64_t VTableIndex, BaseSubobject VTableBase) + : VTableIndex(VTableIndex), VTableBase(VTableBase) {} +}; + +/// VTT builder - Class for building VTT layout information. +class VTTBuilder { + + ASTContext &Ctx; + + /// MostDerivedClass - The most derived class for which we're building this + /// vtable. + const CXXRecordDecl *MostDerivedClass; + + typedef SmallVector<VTTVTable, 64> VTTVTablesVectorTy; + + /// VTTVTables - The VTT vtables. + VTTVTablesVectorTy VTTVTables; + + typedef SmallVector<VTTComponent, 64> VTTComponentsVectorTy; + + /// VTTComponents - The VTT components. + VTTComponentsVectorTy VTTComponents; + + /// MostDerivedClassLayout - the AST record layout of the most derived class. + const ASTRecordLayout &MostDerivedClassLayout; + + typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy; + + typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy; + + /// SubVTTIndicies - The sub-VTT indices for the bases of the most derived + /// class. + llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndicies; + + /// SecondaryVirtualPointerIndices - The secondary virtual pointer indices of + /// all subobjects of the most derived class. + llvm::DenseMap<BaseSubobject, uint64_t> SecondaryVirtualPointerIndices; + + /// GenerateDefinition - Whether the VTT builder should generate LLVM IR for + /// the VTT. + bool GenerateDefinition; + + /// AddVTablePointer - Add a vtable pointer to the VTT currently being built. + /// + /// \param AddressPoints - If the vtable is a construction vtable, this has + /// the address points for it. + void AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex, + const CXXRecordDecl *VTableClass); + + /// LayoutSecondaryVTTs - Lay out the secondary VTTs of the given base + /// subobject. + void LayoutSecondaryVTTs(BaseSubobject Base); + + /// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers + /// for the given base subobject. + /// + /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base + /// or a direct or indirect base of a virtual base. + /// + /// \param AddressPoints - If the vtable is a construction vtable, this has + /// the address points for it. + void LayoutSecondaryVirtualPointers(BaseSubobject Base, + bool BaseIsMorallyVirtual, + uint64_t VTableIndex, + const CXXRecordDecl *VTableClass, + VisitedVirtualBasesSetTy &VBases); + + /// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers + /// for the given base subobject. + /// + /// \param AddressPoints - If the vtable is a construction vtable, this has + /// the address points for it. + void LayoutSecondaryVirtualPointers(BaseSubobject Base, + uint64_t VTableIndex); + + /// LayoutVirtualVTTs - Lay out the VTTs for the virtual base classes of the + /// given record decl. + void LayoutVirtualVTTs(const CXXRecordDecl *RD, + VisitedVirtualBasesSetTy &VBases); + + /// LayoutVTT - Will lay out the VTT for the given subobject, including any + /// secondary VTTs, secondary virtual pointers and virtual VTTs. + void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual); + +public: + VTTBuilder(ASTContext &Ctx, const CXXRecordDecl *MostDerivedClass, + bool GenerateDefinition); + + // getVTTComponents - Returns a reference to the VTT components. + const VTTComponentsVectorTy &getVTTComponents() const { + return VTTComponents; + } + + // getVTTVTables - Returns a reference to the VTT vtables. + const VTTVTablesVectorTy &getVTTVTables() const { + return VTTVTables; + } + + /// getSubVTTIndicies - Returns a reference to the sub-VTT indices. + const llvm::DenseMap<BaseSubobject, uint64_t> &getSubVTTIndicies() const { + return SubVTTIndicies; + } + + /// getSecondaryVirtualPointerIndices - Returns a reference to the secondary + /// virtual pointer indices. + const llvm::DenseMap<BaseSubobject, uint64_t> & + getSecondaryVirtualPointerIndices() const { + return SecondaryVirtualPointerIndices; + } + +}; + +} + +#endif diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 945b8a64d8..eefdb447d3 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -46,6 +46,7 @@ add_clang_library(clangAST Type.cpp TypeLoc.cpp TypePrinter.cpp + VTTBuilder.cpp ) add_dependencies(clangAST ClangARMNeon ClangAttrClasses ClangAttrList diff --git a/lib/AST/VTTBuilder.cpp b/lib/AST/VTTBuilder.cpp new file mode 100644 index 0000000000..f5ff624cf0 --- /dev/null +++ b/lib/AST/VTTBuilder.cpp @@ -0,0 +1,212 @@ +//===--- VTTBuilder.cpp - C++ VTT layout builder --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code dealing with generation of the layout of virtual table +// tables (VTT). +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/VTTBuilder.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/RecordLayout.h" +#include "clang/Basic/TargetInfo.h" +#include "llvm/Support/Format.h" +#include <algorithm> +#include <cstdio> + +using namespace clang; + +#define DUMP_OVERRIDERS 0 + +VTTBuilder::VTTBuilder(ASTContext &Ctx, + const CXXRecordDecl *MostDerivedClass, + bool GenerateDefinition) + : Ctx(Ctx), MostDerivedClass(MostDerivedClass), + MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)), + GenerateDefinition(GenerateDefinition) { + // Lay out this VTT. + LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()), + /*BaseIsVirtual=*/false); +} + +void VTTBuilder::AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex, + const CXXRecordDecl *VTableClass) { + // Store the vtable pointer index if we're generating the primary VTT. + if (VTableClass == MostDerivedClass) { + assert(!SecondaryVirtualPointerIndices.count(Base) && + "A virtual pointer index already exists for this base subobject!"); + SecondaryVirtualPointerIndices[Base] = VTTComponents.size(); + } + + if (!GenerateDefinition) { + VTTComponents.push_back(VTTComponent()); + return; + } + + VTTComponents.push_back(VTTComponent(VTableIndex, Base)); +} + +void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) { + const CXXRecordDecl *RD = Base.getBase(); + + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + + // Don't layout virtual bases. + if (I->isVirtual()) + continue; + + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); + CharUnits BaseOffset = Base.getBaseOffset() + + Layout.getBaseClassOffset(BaseDecl); + + // Layout the VTT for this base. + LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false); + } +} + +void +VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, + bool BaseIsMorallyVirtual, + uint64_t VTableIndex, + const CXXRecordDecl *VTableClass, + VisitedVirtualBasesSetTy &VBases) { + const CXXRecordDecl *RD = Base.getBase(); + + // We're not interested in bases that don't have virtual bases, and not + // morally virtual bases. + if (!RD->getNumVBases() && !BaseIsMorallyVirtual) + return; + + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + // Itanium C++ ABI 2.6.2: + // Secondary virtual pointers are present for all bases with either + // virtual bases or virtual function declarations overridden along a + // virtual path. + // + // If the base class is not dynamic, we don't want to add it, nor any + // of its base classes. + if (!BaseDecl->isDynamicClass()) + continue; + + bool BaseDeclIsMorallyVirtual = BaseIsMorallyVirtual; + bool BaseDeclIsNonVirtualPrimaryBase = false; + CharUnits BaseOffset; + if (I->isVirtual()) { + // Ignore virtual bases that we've already visited. + if (!VBases.insert(BaseDecl)) + continue; + + BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); + BaseDeclIsMorallyVirtual = true; + } else { + const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); + + BaseOffset = Base.getBaseOffset() + + Layout.getBaseClassOffset(BaseDecl); + + if (!Layout.isPrimaryBaseVirtual() && + Layout.getPrimaryBase() == BaseDecl) + BaseDeclIsNonVirtualPrimaryBase = true; + } + + // Itanium C++ ABI 2.6.2: + // Secondary virtual pointers: for each base class X which (a) has virtual + // bases or is reachable along a virtual path from D, and (b) is not a + // non-virtual primary base, the address of the virtual table for X-in-D + // or an appropriate construction virtual table. + if (!BaseDeclIsNonVirtualPrimaryBase && + (BaseDecl->getNumVBases() || BaseDeclIsMorallyVirtual)) { + // Add the vtable pointer. + AddVTablePointer(BaseSubobject(BaseDecl, BaseOffset), VTableIndex, + VTableClass); + } + + // And lay out the secondary virtual pointers for the base class. + LayoutSecondaryVirtualPointers(BaseSubobject(BaseDecl, BaseOffset), + BaseDeclIsMorallyVirtual, VTableIndex, + VTableClass, VBases); + } +} + +void +VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, + uint64_t VTableIndex) { + VisitedVirtualBasesSetTy VBases; + LayoutSecondaryVirtualPointers(Base, /*BaseIsMorallyVirtual=*/false, + VTableIndex, Base.getBase(), VBases); +} + +void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD, + VisitedVirtualBasesSetTy &VBases) { + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + // Check if this is a virtual base. + if (I->isVirtual()) { + // Check if we've seen this base before. + if (!VBases.insert(BaseDecl)) + continue; + + CharUnits BaseOffset = + MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); + + LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true); + } + + // We only need to layout virtual VTTs for this base if it actually has + // virtual bases. + if (BaseDecl->getNumVBases()) + LayoutVirtualVTTs(BaseDecl, VBases); + } +} + +void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) { + const CXXRecordDecl *RD = Base.getBase(); + + // 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. + if (RD->getNumVBases() == 0) + return; + + bool IsPrimaryVTT = Base.getBase() == MostDerivedClass; + + if (!IsPrimaryVTT) { + // Remember the sub-VTT index. + SubVTTIndicies[Base] = VTTComponents.size(); + } + + uint64_t VTableIndex = VTTVTables.size(); + VTTVTables.push_back(VTTVTable(Base, BaseIsVirtual)); + + // Add the primary vtable pointer. + AddVTablePointer(Base, VTableIndex, RD); + + // Add the secondary VTTs. + LayoutSecondaryVTTs(Base); + + // Add the secondary virtual pointers. + LayoutSecondaryVirtualPointers(Base, VTableIndex); + + // If this is the primary VTT, we want to lay out virtual VTTs as well. + if (IsPrimaryVTT) { + VisitedVirtualBasesSetTy VBases; + LayoutVirtualVTTs(Base.getBase(), VBases); + } +} diff --git a/lib/CodeGen/CGVTT.cpp b/lib/CodeGen/CGVTT.cpp index 0e02ff312b..c7d1083cc2 100644 --- a/lib/CodeGen/CGVTT.cpp +++ b/lib/CodeGen/CGVTT.cpp @@ -14,170 +14,12 @@ #include "CodeGenModule.h" #include "CGCXXABI.h" #include "clang/AST/RecordLayout.h" +#include "clang/AST/VTTBuilder.h" using namespace clang; using namespace CodeGen; #define D1(x) -namespace { - -class VTTVTable { - llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> BaseAndIsVirtual; - CharUnits BaseOffset; - -public: - VTTVTable() {} - VTTVTable(const CXXRecordDecl *Base, CharUnits BaseOffset, bool BaseIsVirtual) - : BaseAndIsVirtual(Base, BaseIsVirtual), BaseOffset(BaseOffset) {} - VTTVTable(BaseSubobject Base, bool BaseIsVirtual) - : BaseAndIsVirtual(Base.getBase(), BaseIsVirtual), - BaseOffset(Base.getBaseOffset()) {} - - const CXXRecordDecl *getBase() const { - return BaseAndIsVirtual.getPointer(); - } - - CharUnits getBaseOffset() const { - return BaseOffset; - } - - bool isVirtual() const { - return BaseAndIsVirtual.getInt(); - } - - BaseSubobject getBaseSubobject() const { - return BaseSubobject(getBase(), getBaseOffset()); - } -}; - -struct VTTComponent { - uint64_t VTableIndex; - BaseSubobject VTableBase; - - VTTComponent() {} - VTTComponent(uint64_t VTableIndex, BaseSubobject VTableBase) - : VTableIndex(VTableIndex), VTableBase(VTableBase) {} -}; - -/// VTT builder - Class for building VTT layout information. -class VTTBuilder { - - ASTContext &Ctx; - - /// MostDerivedClass - The most derived class for which we're building this - /// vtable. - const CXXRecordDecl *MostDerivedClass; - - typedef SmallVector<VTTVTable, 64> VTTVTablesVectorTy; - - /// VTTVTables - The VTT vtables. - VTTVTablesVectorTy VTTVTables; - - typedef SmallVector<VTTComponent, 64> VTTComponentsVectorTy; - - /// VTTComponents - The VTT components. - VTTComponentsVectorTy VTTComponents; - - /// MostDerivedClassLayout - the AST record layout of the most derived class. - const ASTRecordLayout &MostDerivedClassLayout; - - typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy; - - typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy; - - /// SubVTTIndicies - The sub-VTT indices for the bases of the most derived - /// class. - llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndicies; - - /// SecondaryVirtualPointerIndices - The secondary virtual pointer indices of - /// all subobjects of the most derived class. - llvm::DenseMap<BaseSubobject, uint64_t> SecondaryVirtualPointerIndices; - - /// GenerateDefinition - Whether the VTT builder should generate LLVM IR for - /// the VTT. - bool GenerateDefinition; - - /// AddVTablePointer - Add a vtable pointer to the VTT currently being built. - /// - /// \param AddressPoints - If the vtable is a construction vtable, this has - /// the address points for it. - void AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex, - const CXXRecordDecl *VTableClass); - - /// LayoutSecondaryVTTs - Lay out the secondary VTTs of the given base - /// subobject. - void LayoutSecondaryVTTs(BaseSubobject Base); - - /// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers - /// for the given base subobject. - /// - /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base - /// or a direct or indirect base of a virtual base. - /// - /// \param AddressPoints - If the vtable is a construction vtable, this has - /// the address points for it. - void LayoutSecondaryVirtualPointers(BaseSubobject Base, - bool BaseIsMorallyVirtual, - uint64_t VTableIndex, - const CXXRecordDecl *VTableClass, - VisitedVirtualBasesSetTy &VBases); - - /// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers - /// for the given base subobject. - /// - /// \param AddressPoints - If the vtable is a construction vtable, this has - /// the address points for it. - void LayoutSecondaryVirtualPointers(BaseSubobject Base, - uint64_t VTableIndex); - - /// LayoutVirtualVTTs - Lay out the VTTs for the virtual base classes of the - /// given record decl. - void LayoutVirtualVTTs(const CXXRecordDecl *RD, - VisitedVirtualBasesSetTy &VBases); - - /// LayoutVTT - Will lay out the VTT for the given subobject, including any - /// secondary VTTs, secondary virtual pointers and virtual VTTs. - void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual); - -public: - VTTBuilder(ASTContext &Ctx, const CXXRecordDecl *MostDerivedClass, - bool GenerateDefinition); - - // getVTTComponents - Returns a reference to the VTT components. - const VTTComponentsVectorTy &getVTTComponents() const { - return VTTComponents; - } - - // getVTTVTables - Returns a reference to the VTT vtables. - const VTTVTablesVectorTy &getVTTVTables() const { - return VTTVTables; - } - - /// getSubVTTIndicies - Returns a reference to the sub-VTT indices. - const llvm::DenseMap<BaseSubobject, uint64_t> &getSubVTTIndicies() const { - return SubVTTIndicies; - } - - /// getSecondaryVirtualPointerIndices - Returns a reference to the secondary - /// virtual pointer indices. - const llvm::DenseMap<BaseSubobject, uint64_t> & - getSecondaryVirtualPointerIndices() const { - return SecondaryVirtualPointerIndices; - } - -}; - -VTTBuilder::VTTBuilder(ASTContext &Ctx, - const CXXRecordDecl *MostDerivedClass, - bool GenerateDefinition) - : Ctx(Ctx), MostDerivedClass(MostDerivedClass), - MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)), - GenerateDefinition(GenerateDefinition) { - // Lay out this VTT. - LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()), - /*BaseIsVirtual=*/false); -} - llvm::Constant *GetAddrOfVTTVTable(CodeGenVTables &CGVT, const CXXRecordDecl *MostDerivedClass, const VTTVTable &VTable, @@ -197,184 +39,6 @@ llvm::Constant *GetAddrOfVTTVTable(CodeGenVTables &CGVT, AddressPoints); } -void VTTBuilder::AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex, - const CXXRecordDecl *VTableClass) { - // Store the vtable pointer index if we're generating the primary VTT. - if (VTableClass == MostDerivedClass) { - assert(!SecondaryVirtualPointerIndices.count(Base) && - "A virtual pointer index already exists for this base subobject!"); - SecondaryVirtualPointerIndices[Base] = VTTComponents.size(); - } - - if (!GenerateDefinition) { - VTTComponents.push_back(VTTComponent()); - return; - } - - VTTComponents.push_back(VTTComponent(VTableIndex, Base)); -} - -void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) { - const CXXRecordDecl *RD = Base.getBase(); - - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - - // Don't layout virtual bases. - if (I->isVirtual()) - continue; - - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - - const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); - CharUnits BaseOffset = Base.getBaseOffset() + - Layout.getBaseClassOffset(BaseDecl); - - // Layout the VTT for this base. - LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false); - } -} - -void -VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, - bool BaseIsMorallyVirtual, - uint64_t VTableIndex, - const CXXRecordDecl *VTableClass, - VisitedVirtualBasesSetTy &VBases) { - const CXXRecordDecl *RD = Base.getBase(); - - // We're not interested in bases that don't have virtual bases, and not - // morally virtual bases. - if (!RD->getNumVBases() && !BaseIsMorallyVirtual) - return; - - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - - // Itanium C++ ABI 2.6.2: - // Secondary virtual pointers are present for all bases with either - // virtual bases or virtual function declarations overridden along a - // virtual path. - // - // If the base class is not dynamic, we don't want to add it, nor any - // of its base classes. - if (!BaseDecl->isDynamicClass()) - continue; - - bool BaseDeclIsMorallyVirtual = BaseIsMorallyVirtual; - bool BaseDeclIsNonVirtualPrimaryBase = false; - CharUnits BaseOffset; - if (I->isVirtual()) { - // Ignore virtual bases that we've already visited. - if (!VBases.insert(BaseDecl)) - continue; - - BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); - BaseDeclIsMorallyVirtual = true; - } else { - const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); - - BaseOffset = Base.getBaseOffset() + - Layout.getBaseClassOffset(BaseDecl); - - if (!Layout.isPrimaryBaseVirtual() && - Layout.getPrimaryBase() == BaseDecl) - BaseDeclIsNonVirtualPrimaryBase = true; - } - - // Itanium C++ ABI 2.6.2: - // Secondary virtual pointers: for each base class X which (a) has virtual - // bases or is reachable along a virtual path from D, and (b) is not a - // non-virtual primary base, the address of the virtual table for X-in-D - // or an appropriate construction virtual table. - if (!BaseDeclIsNonVirtualPrimaryBase && - (BaseDecl->getNumVBases() || BaseDeclIsMorallyVirtual)) { - // Add the vtable pointer. - AddVTablePointer(BaseSubobject(BaseDecl, BaseOffset), VTableIndex, - VTableClass); - } - - // And lay out the secondary virtual pointers for the base class. - LayoutSecondaryVirtualPointers(BaseSubobject(BaseDecl, BaseOffset), - BaseDeclIsMorallyVirtual, VTableIndex, - VTableClass, VBases); - } -} - -void -VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, - uint64_t VTableIndex) { - VisitedVirtualBasesSetTy VBases; - LayoutSecondaryVirtualPointers(Base, /*BaseIsMorallyVirtual=*/false, - VTableIndex, Base.getBase(), VBases); -} - -void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD, - VisitedVirtualBasesSetTy &VBases) { - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - - // Check if this is a virtual base. - if (I->isVirtual()) { - // Check if we've seen this base before. - if (!VBases.insert(BaseDecl)) - continue; - - CharUnits BaseOffset = - MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); - - LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true); - } - - // We only need to layout virtual VTTs for this base if it actually has - // virtual bases. - if (BaseDecl->getNumVBases()) - LayoutVirtualVTTs(BaseDecl, VBases); - } -} - -void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) { - const CXXRecordDecl *RD = Base.getBase(); - - // 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. - if (RD->getNumVBases() == 0) - return; - - bool IsPrimaryVTT = Base.getBase() == MostDerivedClass; - - if (!IsPrimaryVTT) { - // Remember the sub-VTT index. - SubVTTIndicies[Base] = VTTComponents.size(); - } - - uint64_t VTableIndex = VTTVTables.size(); - VTTVTables.push_back(VTTVTable(Base, BaseIsVirtual)); - - // Add the primary vtable pointer. - AddVTablePointer(Base, VTableIndex, RD); - - // Add the secondary VTTs. - LayoutSecondaryVTTs(Base); - - // Add the secondary virtual pointers. - LayoutSecondaryVirtualPointers(Base, VTableIndex); - - // If this is the primary VTT, we want to lay out virtual VTTs as well. - if (IsPrimaryVTT) { - VisitedVirtualBasesSetTy VBases; - LayoutVirtualVTTs(Base.getBase(), VBases); - } -} - -} - void CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT, llvm::GlobalVariable::LinkageTypes Linkage, |