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