1 //===- VTTBuilder.cpp - C++ VTT layout builder ----------------------------===// 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 #include "clang/AST/VTTBuilder.h" 15 #include "clang/AST/ASTContext.h" 16 #include "clang/AST/BaseSubobject.h" 17 #include "clang/AST/CharUnits.h" 18 #include "clang/AST/Decl.h" 19 #include "clang/AST/DeclCXX.h" 20 #include "clang/AST/RecordLayout.h" 21 #include "clang/AST/Type.h" 22 #include "clang/Basic/LLVM.h" 23 #include "llvm/Support/Casting.h" 24 #include <cassert> 25 #include <cstdint> 26 27 using namespace clang; 28 29 #define DUMP_OVERRIDERS 0 30 31 VTTBuilder::VTTBuilder(ASTContext &Ctx, 32 const CXXRecordDecl *MostDerivedClass, 33 bool GenerateDefinition) 34 : Ctx(Ctx), MostDerivedClass(MostDerivedClass), 35 MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)), 36 GenerateDefinition(GenerateDefinition) { 37 // Lay out this VTT. 38 LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()), 39 /*BaseIsVirtual=*/false); 40 } 41 42 void VTTBuilder::AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex, 43 const CXXRecordDecl *VTableClass) { 44 // Store the vtable pointer index if we're generating the primary VTT. 45 if (VTableClass == MostDerivedClass) { 46 assert(!SecondaryVirtualPointerIndices.count(Base) && 47 "A virtual pointer index already exists for this base subobject!"); 48 SecondaryVirtualPointerIndices[Base] = VTTComponents.size(); 49 } 50 51 if (!GenerateDefinition) { 52 VTTComponents.push_back(VTTComponent()); 53 return; 54 } 55 56 VTTComponents.push_back(VTTComponent(VTableIndex, Base)); 57 } 58 59 void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) { 60 const CXXRecordDecl *RD = Base.getBase(); 61 62 for (const auto &I : RD->bases()) { 63 // Don't layout virtual bases. 64 if (I.isVirtual()) 65 continue; 66 67 const auto *BaseDecl = 68 cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); 69 70 const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); 71 CharUnits BaseOffset = Base.getBaseOffset() + 72 Layout.getBaseClassOffset(BaseDecl); 73 74 // Layout the VTT for this base. 75 LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false); 76 } 77 } 78 79 void 80 VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, 81 bool BaseIsMorallyVirtual, 82 uint64_t VTableIndex, 83 const CXXRecordDecl *VTableClass, 84 VisitedVirtualBasesSetTy &VBases) { 85 const CXXRecordDecl *RD = Base.getBase(); 86 87 // We're not interested in bases that don't have virtual bases, and not 88 // morally virtual bases. 89 if (!RD->getNumVBases() && !BaseIsMorallyVirtual) 90 return; 91 92 for (const auto &I : RD->bases()) { 93 const auto *BaseDecl = 94 cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); 95 96 // Itanium C++ ABI 2.6.2: 97 // Secondary virtual pointers are present for all bases with either 98 // virtual bases or virtual function declarations overridden along a 99 // virtual path. 100 // 101 // If the base class is not dynamic, we don't want to add it, nor any 102 // of its base classes. 103 if (!BaseDecl->isDynamicClass()) 104 continue; 105 106 bool BaseDeclIsMorallyVirtual = BaseIsMorallyVirtual; 107 bool BaseDeclIsNonVirtualPrimaryBase = false; 108 CharUnits BaseOffset; 109 if (I.isVirtual()) { 110 // Ignore virtual bases that we've already visited. 111 if (!VBases.insert(BaseDecl).second) 112 continue; 113 114 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); 115 BaseDeclIsMorallyVirtual = true; 116 } else { 117 const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); 118 119 BaseOffset = Base.getBaseOffset() + 120 Layout.getBaseClassOffset(BaseDecl); 121 122 if (!Layout.isPrimaryBaseVirtual() && 123 Layout.getPrimaryBase() == BaseDecl) 124 BaseDeclIsNonVirtualPrimaryBase = true; 125 } 126 127 // Itanium C++ ABI 2.6.2: 128 // Secondary virtual pointers: for each base class X which (a) has virtual 129 // bases or is reachable along a virtual path from D, and (b) is not a 130 // non-virtual primary base, the address of the virtual table for X-in-D 131 // or an appropriate construction virtual table. 132 if (!BaseDeclIsNonVirtualPrimaryBase && 133 (BaseDecl->getNumVBases() || BaseDeclIsMorallyVirtual)) { 134 // Add the vtable pointer. 135 AddVTablePointer(BaseSubobject(BaseDecl, BaseOffset), VTableIndex, 136 VTableClass); 137 } 138 139 // And lay out the secondary virtual pointers for the base class. 140 LayoutSecondaryVirtualPointers(BaseSubobject(BaseDecl, BaseOffset), 141 BaseDeclIsMorallyVirtual, VTableIndex, 142 VTableClass, VBases); 143 } 144 } 145 146 void 147 VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, 148 uint64_t VTableIndex) { 149 VisitedVirtualBasesSetTy VBases; 150 LayoutSecondaryVirtualPointers(Base, /*BaseIsMorallyVirtual=*/false, 151 VTableIndex, Base.getBase(), VBases); 152 } 153 154 void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD, 155 VisitedVirtualBasesSetTy &VBases) { 156 for (const auto &I : RD->bases()) { 157 const auto *BaseDecl = 158 cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); 159 160 // Check if this is a virtual base. 161 if (I.isVirtual()) { 162 // Check if we've seen this base before. 163 if (!VBases.insert(BaseDecl).second) 164 continue; 165 166 CharUnits BaseOffset = 167 MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); 168 169 LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true); 170 } 171 172 // We only need to layout virtual VTTs for this base if it actually has 173 // virtual bases. 174 if (BaseDecl->getNumVBases()) 175 LayoutVirtualVTTs(BaseDecl, VBases); 176 } 177 } 178 179 void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) { 180 const CXXRecordDecl *RD = Base.getBase(); 181 182 // Itanium C++ ABI 2.6.2: 183 // An array of virtual table addresses, called the VTT, is declared for 184 // each class type that has indirect or direct virtual base classes. 185 if (RD->getNumVBases() == 0) 186 return; 187 188 bool IsPrimaryVTT = Base.getBase() == MostDerivedClass; 189 190 if (!IsPrimaryVTT) { 191 // Remember the sub-VTT index. 192 SubVTTIndicies[Base] = VTTComponents.size(); 193 } 194 195 uint64_t VTableIndex = VTTVTables.size(); 196 VTTVTables.push_back(VTTVTable(Base, BaseIsVirtual)); 197 198 // Add the primary vtable pointer. 199 AddVTablePointer(Base, VTableIndex, RD); 200 201 // Add the secondary VTTs. 202 LayoutSecondaryVTTs(Base); 203 204 // Add the secondary virtual pointers. 205 LayoutSecondaryVirtualPointers(Base, VTableIndex); 206 207 // If this is the primary VTT, we want to lay out virtual VTTs as well. 208 if (IsPrimaryVTT) { 209 VisitedVirtualBasesSetTy VBases; 210 LayoutVirtualVTTs(Base.getBase(), VBases); 211 } 212 } 213