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