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