1 //===- VTTBuilder.h - C++ VTT layout builder --------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This contains code dealing with generation of the layout of virtual table 10 // tables (VTT). 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_AST_VTTBUILDER_H 15 #define LLVM_CLANG_AST_VTTBUILDER_H 16 17 #include "clang/AST/BaseSubobject.h" 18 #include "clang/AST/CharUnits.h" 19 #include "clang/Basic/LLVM.h" 20 #include "llvm/ADT/DenseMap.h" 21 #include "llvm/ADT/PointerIntPair.h" 22 #include "llvm/ADT/SmallPtrSet.h" 23 #include "llvm/ADT/SmallVector.h" 24 #include <cstdint> 25 26 namespace clang { 27 28 class ASTContext; 29 class ASTRecordLayout; 30 class CXXRecordDecl; 31 32 class VTTVTable { 33 llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> BaseAndIsVirtual; 34 CharUnits BaseOffset; 35 36 public: 37 VTTVTable() = default; VTTVTable(const CXXRecordDecl * Base,CharUnits BaseOffset,bool BaseIsVirtual)38 VTTVTable(const CXXRecordDecl *Base, CharUnits BaseOffset, bool BaseIsVirtual) 39 : BaseAndIsVirtual(Base, BaseIsVirtual), BaseOffset(BaseOffset) {} VTTVTable(BaseSubobject Base,bool BaseIsVirtual)40 VTTVTable(BaseSubobject Base, bool BaseIsVirtual) 41 : BaseAndIsVirtual(Base.getBase(), BaseIsVirtual), 42 BaseOffset(Base.getBaseOffset()) {} 43 getBase()44 const CXXRecordDecl *getBase() const { 45 return BaseAndIsVirtual.getPointer(); 46 } 47 getBaseOffset()48 CharUnits getBaseOffset() const { 49 return BaseOffset; 50 } 51 isVirtual()52 bool isVirtual() const { 53 return BaseAndIsVirtual.getInt(); 54 } 55 getBaseSubobject()56 BaseSubobject getBaseSubobject() const { 57 return BaseSubobject(getBase(), getBaseOffset()); 58 } 59 }; 60 61 struct VTTComponent { 62 uint64_t VTableIndex; 63 BaseSubobject VTableBase; 64 65 VTTComponent() = default; VTTComponentVTTComponent66 VTTComponent(uint64_t VTableIndex, BaseSubobject VTableBase) 67 : VTableIndex(VTableIndex), VTableBase(VTableBase) {} 68 }; 69 70 /// Class for building VTT layout information. 71 class VTTBuilder { 72 ASTContext &Ctx; 73 74 /// The most derived class for which we're building this vtable. 75 const CXXRecordDecl *MostDerivedClass; 76 77 using VTTVTablesVectorTy = SmallVector<VTTVTable, 64>; 78 79 /// The VTT vtables. 80 VTTVTablesVectorTy VTTVTables; 81 82 using VTTComponentsVectorTy = SmallVector<VTTComponent, 64>; 83 84 /// The VTT components. 85 VTTComponentsVectorTy VTTComponents; 86 87 /// The AST record layout of the most derived class. 88 const ASTRecordLayout &MostDerivedClassLayout; 89 90 using VisitedVirtualBasesSetTy = llvm::SmallPtrSet<const CXXRecordDecl *, 4>; 91 92 using AddressPointsMapTy = llvm::DenseMap<BaseSubobject, uint64_t>; 93 94 /// The sub-VTT indices for the bases of the most derived class. 95 llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndices; 96 97 /// The secondary virtual pointer indices of all subobjects of 98 /// the most derived class. 99 llvm::DenseMap<BaseSubobject, uint64_t> SecondaryVirtualPointerIndices; 100 101 /// Whether the VTT builder should generate LLVM IR for the VTT. 102 bool GenerateDefinition; 103 104 /// Add a vtable pointer to the VTT currently being built. 105 void AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex, 106 const CXXRecordDecl *VTableClass); 107 108 /// Lay out the secondary VTTs of the given base subobject. 109 void LayoutSecondaryVTTs(BaseSubobject Base); 110 111 /// Lay out the secondary virtual pointers for the given base 112 /// subobject. 113 /// 114 /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base 115 /// or a direct or indirect base of a virtual base. 116 void LayoutSecondaryVirtualPointers(BaseSubobject Base, 117 bool BaseIsMorallyVirtual, 118 uint64_t VTableIndex, 119 const CXXRecordDecl *VTableClass, 120 VisitedVirtualBasesSetTy &VBases); 121 122 /// Lay out the secondary virtual pointers for the given base 123 /// subobject. 124 void LayoutSecondaryVirtualPointers(BaseSubobject Base, 125 uint64_t VTableIndex); 126 127 /// Lay out the VTTs for the virtual base classes of the given 128 /// record declaration. 129 void LayoutVirtualVTTs(const CXXRecordDecl *RD, 130 VisitedVirtualBasesSetTy &VBases); 131 132 /// Lay out the VTT for the given subobject, including any 133 /// secondary VTTs, secondary virtual pointers and virtual VTTs. 134 void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual); 135 136 public: 137 VTTBuilder(ASTContext &Ctx, const CXXRecordDecl *MostDerivedClass, 138 bool GenerateDefinition); 139 140 // Returns a reference to the VTT components. getVTTComponents()141 const VTTComponentsVectorTy &getVTTComponents() const { 142 return VTTComponents; 143 } 144 145 // Returns a reference to the VTT vtables. getVTTVTables()146 const VTTVTablesVectorTy &getVTTVTables() const { 147 return VTTVTables; 148 } 149 150 /// Returns a reference to the sub-VTT indices. getSubVTTIndices()151 const llvm::DenseMap<BaseSubobject, uint64_t> &getSubVTTIndices() const { 152 return SubVTTIndices; 153 } 154 155 /// Returns a reference to the secondary virtual pointer indices. 156 const llvm::DenseMap<BaseSubobject, uint64_t> & getSecondaryVirtualPointerIndices()157 getSecondaryVirtualPointerIndices() const { 158 return SecondaryVirtualPointerIndices; 159 } 160 }; 161 162 } // namespace clang 163 164 #endif // LLVM_CLANG_AST_VTTBUILDER_H 165