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