10b57cec5SDimitry Andric //===- VTTBuilder.h - C++ VTT layout builder --------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This contains code dealing with generation of the layout of virtual table 100b57cec5SDimitry Andric // tables (VTT). 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #ifndef LLVM_CLANG_AST_VTTBUILDER_H 150b57cec5SDimitry Andric #define LLVM_CLANG_AST_VTTBUILDER_H 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "clang/AST/BaseSubobject.h" 180b57cec5SDimitry Andric #include "clang/AST/CharUnits.h" 190b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 200b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 210b57cec5SDimitry Andric #include "llvm/ADT/PointerIntPair.h" 220b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 230b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 240b57cec5SDimitry Andric #include <cstdint> 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric namespace clang { 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric class ASTContext; 290b57cec5SDimitry Andric class ASTRecordLayout; 300b57cec5SDimitry Andric class CXXRecordDecl; 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric class VTTVTable { 330b57cec5SDimitry Andric llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> BaseAndIsVirtual; 340b57cec5SDimitry Andric CharUnits BaseOffset; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric public: 370b57cec5SDimitry Andric VTTVTable() = default; VTTVTable(const CXXRecordDecl * Base,CharUnits BaseOffset,bool BaseIsVirtual)380b57cec5SDimitry Andric VTTVTable(const CXXRecordDecl *Base, CharUnits BaseOffset, bool BaseIsVirtual) 390b57cec5SDimitry Andric : BaseAndIsVirtual(Base, BaseIsVirtual), BaseOffset(BaseOffset) {} VTTVTable(BaseSubobject Base,bool BaseIsVirtual)400b57cec5SDimitry Andric VTTVTable(BaseSubobject Base, bool BaseIsVirtual) 410b57cec5SDimitry Andric : BaseAndIsVirtual(Base.getBase(), BaseIsVirtual), 420b57cec5SDimitry Andric BaseOffset(Base.getBaseOffset()) {} 430b57cec5SDimitry Andric getBase()440b57cec5SDimitry Andric const CXXRecordDecl *getBase() const { 450b57cec5SDimitry Andric return BaseAndIsVirtual.getPointer(); 460b57cec5SDimitry Andric } 470b57cec5SDimitry Andric getBaseOffset()480b57cec5SDimitry Andric CharUnits getBaseOffset() const { 490b57cec5SDimitry Andric return BaseOffset; 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric isVirtual()520b57cec5SDimitry Andric bool isVirtual() const { 530b57cec5SDimitry Andric return BaseAndIsVirtual.getInt(); 540b57cec5SDimitry Andric } 550b57cec5SDimitry Andric getBaseSubobject()560b57cec5SDimitry Andric BaseSubobject getBaseSubobject() const { 570b57cec5SDimitry Andric return BaseSubobject(getBase(), getBaseOffset()); 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric }; 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric struct VTTComponent { 620b57cec5SDimitry Andric uint64_t VTableIndex; 630b57cec5SDimitry Andric BaseSubobject VTableBase; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric VTTComponent() = default; VTTComponentVTTComponent660b57cec5SDimitry Andric VTTComponent(uint64_t VTableIndex, BaseSubobject VTableBase) 670b57cec5SDimitry Andric : VTableIndex(VTableIndex), VTableBase(VTableBase) {} 680b57cec5SDimitry Andric }; 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric /// Class for building VTT layout information. 710b57cec5SDimitry Andric class VTTBuilder { 720b57cec5SDimitry Andric ASTContext &Ctx; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric /// The most derived class for which we're building this vtable. 750b57cec5SDimitry Andric const CXXRecordDecl *MostDerivedClass; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric using VTTVTablesVectorTy = SmallVector<VTTVTable, 64>; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric /// The VTT vtables. 800b57cec5SDimitry Andric VTTVTablesVectorTy VTTVTables; 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric using VTTComponentsVectorTy = SmallVector<VTTComponent, 64>; 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric /// The VTT components. 850b57cec5SDimitry Andric VTTComponentsVectorTy VTTComponents; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric /// The AST record layout of the most derived class. 880b57cec5SDimitry Andric const ASTRecordLayout &MostDerivedClassLayout; 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric using VisitedVirtualBasesSetTy = llvm::SmallPtrSet<const CXXRecordDecl *, 4>; 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric using AddressPointsMapTy = llvm::DenseMap<BaseSubobject, uint64_t>; 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric /// The sub-VTT indices for the bases of the most derived class. 95*0fca6ea1SDimitry Andric llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndices; 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric /// The secondary virtual pointer indices of all subobjects of 980b57cec5SDimitry Andric /// the most derived class. 990b57cec5SDimitry Andric llvm::DenseMap<BaseSubobject, uint64_t> SecondaryVirtualPointerIndices; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric /// Whether the VTT builder should generate LLVM IR for the VTT. 1020b57cec5SDimitry Andric bool GenerateDefinition; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric /// Add a vtable pointer to the VTT currently being built. 1050b57cec5SDimitry Andric void AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex, 1060b57cec5SDimitry Andric const CXXRecordDecl *VTableClass); 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric /// Lay out the secondary VTTs of the given base subobject. 1090b57cec5SDimitry Andric void LayoutSecondaryVTTs(BaseSubobject Base); 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric /// Lay out the secondary virtual pointers for the given base 1120b57cec5SDimitry Andric /// subobject. 1130b57cec5SDimitry Andric /// 1140b57cec5SDimitry Andric /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base 1150b57cec5SDimitry Andric /// or a direct or indirect base of a virtual base. 1160b57cec5SDimitry Andric void LayoutSecondaryVirtualPointers(BaseSubobject Base, 1170b57cec5SDimitry Andric bool BaseIsMorallyVirtual, 1180b57cec5SDimitry Andric uint64_t VTableIndex, 1190b57cec5SDimitry Andric const CXXRecordDecl *VTableClass, 1200b57cec5SDimitry Andric VisitedVirtualBasesSetTy &VBases); 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric /// Lay out the secondary virtual pointers for the given base 1230b57cec5SDimitry Andric /// subobject. 1240b57cec5SDimitry Andric void LayoutSecondaryVirtualPointers(BaseSubobject Base, 1250b57cec5SDimitry Andric uint64_t VTableIndex); 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric /// Lay out the VTTs for the virtual base classes of the given 1280b57cec5SDimitry Andric /// record declaration. 1290b57cec5SDimitry Andric void LayoutVirtualVTTs(const CXXRecordDecl *RD, 1300b57cec5SDimitry Andric VisitedVirtualBasesSetTy &VBases); 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric /// Lay out the VTT for the given subobject, including any 1330b57cec5SDimitry Andric /// secondary VTTs, secondary virtual pointers and virtual VTTs. 1340b57cec5SDimitry Andric void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual); 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric public: 1370b57cec5SDimitry Andric VTTBuilder(ASTContext &Ctx, const CXXRecordDecl *MostDerivedClass, 1380b57cec5SDimitry Andric bool GenerateDefinition); 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric // Returns a reference to the VTT components. getVTTComponents()1410b57cec5SDimitry Andric const VTTComponentsVectorTy &getVTTComponents() const { 1420b57cec5SDimitry Andric return VTTComponents; 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric // Returns a reference to the VTT vtables. getVTTVTables()1460b57cec5SDimitry Andric const VTTVTablesVectorTy &getVTTVTables() const { 1470b57cec5SDimitry Andric return VTTVTables; 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric /// Returns a reference to the sub-VTT indices. getSubVTTIndices()151*0fca6ea1SDimitry Andric const llvm::DenseMap<BaseSubobject, uint64_t> &getSubVTTIndices() const { 152*0fca6ea1SDimitry Andric return SubVTTIndices; 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric /// Returns a reference to the secondary virtual pointer indices. 1560b57cec5SDimitry Andric const llvm::DenseMap<BaseSubobject, uint64_t> & getSecondaryVirtualPointerIndices()1570b57cec5SDimitry Andric getSecondaryVirtualPointerIndices() const { 1580b57cec5SDimitry Andric return SecondaryVirtualPointerIndices; 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric }; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric } // namespace clang 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric #endif // LLVM_CLANG_AST_VTTBUILDER_H 165