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/CXXInheritance.h"
17 #include "clang/AST/RecordLayout.h"
18 #include "clang/Basic/TargetInfo.h"
19 #include "llvm/Support/Format.h"
20 #include <algorithm>
21 #include <cstdio>
22
23 using namespace clang;
24
25 #define DUMP_OVERRIDERS 0
26
VTTBuilder(ASTContext & Ctx,const CXXRecordDecl * MostDerivedClass,bool GenerateDefinition)27 VTTBuilder::VTTBuilder(ASTContext &Ctx,
28 const CXXRecordDecl *MostDerivedClass,
29 bool GenerateDefinition)
30 : Ctx(Ctx), MostDerivedClass(MostDerivedClass),
31 MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)),
32 GenerateDefinition(GenerateDefinition) {
33 // Lay out this VTT.
34 LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()),
35 /*BaseIsVirtual=*/false);
36 }
37
AddVTablePointer(BaseSubobject Base,uint64_t VTableIndex,const CXXRecordDecl * VTableClass)38 void VTTBuilder::AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex,
39 const CXXRecordDecl *VTableClass) {
40 // Store the vtable pointer index if we're generating the primary VTT.
41 if (VTableClass == MostDerivedClass) {
42 assert(!SecondaryVirtualPointerIndices.count(Base) &&
43 "A virtual pointer index already exists for this base subobject!");
44 SecondaryVirtualPointerIndices[Base] = VTTComponents.size();
45 }
46
47 if (!GenerateDefinition) {
48 VTTComponents.push_back(VTTComponent());
49 return;
50 }
51
52 VTTComponents.push_back(VTTComponent(VTableIndex, Base));
53 }
54
LayoutSecondaryVTTs(BaseSubobject Base)55 void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) {
56 const CXXRecordDecl *RD = Base.getBase();
57
58 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
59 E = RD->bases_end(); I != E; ++I) {
60
61 // Don't layout virtual bases.
62 if (I->isVirtual())
63 continue;
64
65 const CXXRecordDecl *BaseDecl =
66 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
67
68 const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
69 CharUnits BaseOffset = Base.getBaseOffset() +
70 Layout.getBaseClassOffset(BaseDecl);
71
72 // Layout the VTT for this base.
73 LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false);
74 }
75 }
76
77 void
LayoutSecondaryVirtualPointers(BaseSubobject Base,bool BaseIsMorallyVirtual,uint64_t VTableIndex,const CXXRecordDecl * VTableClass,VisitedVirtualBasesSetTy & VBases)78 VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
79 bool BaseIsMorallyVirtual,
80 uint64_t VTableIndex,
81 const CXXRecordDecl *VTableClass,
82 VisitedVirtualBasesSetTy &VBases) {
83 const CXXRecordDecl *RD = Base.getBase();
84
85 // We're not interested in bases that don't have virtual bases, and not
86 // morally virtual bases.
87 if (!RD->getNumVBases() && !BaseIsMorallyVirtual)
88 return;
89
90 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
91 E = RD->bases_end(); I != E; ++I) {
92 const CXXRecordDecl *BaseDecl =
93 cast<CXXRecordDecl>(I->getType()->getAs<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))
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
LayoutSecondaryVirtualPointers(BaseSubobject Base,uint64_t VTableIndex)146 VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
147 uint64_t VTableIndex) {
148 VisitedVirtualBasesSetTy VBases;
149 LayoutSecondaryVirtualPointers(Base, /*BaseIsMorallyVirtual=*/false,
150 VTableIndex, Base.getBase(), VBases);
151 }
152
LayoutVirtualVTTs(const CXXRecordDecl * RD,VisitedVirtualBasesSetTy & VBases)153 void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD,
154 VisitedVirtualBasesSetTy &VBases) {
155 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
156 E = RD->bases_end(); I != E; ++I) {
157 const CXXRecordDecl *BaseDecl =
158 cast<CXXRecordDecl>(I->getType()->getAs<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))
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
LayoutVTT(BaseSubobject Base,bool BaseIsVirtual)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