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