clang 20.0.0git
VTTBuilder.cpp
Go to the documentation of this file.
1//===- VTTBuilder.cpp - C++ VTT layout builder ----------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code dealing with generation of the layout of virtual table
10// tables (VTT).
11//
12//===----------------------------------------------------------------------===//
13
17#include "clang/AST/CharUnits.h"
18#include "clang/AST/Decl.h"
19#include "clang/AST/DeclCXX.h"
21#include "clang/AST/Type.h"
22#include "clang/Basic/LLVM.h"
23#include <cassert>
24#include <cstdint>
25
26using namespace clang;
27
28#define DUMP_OVERRIDERS 0
29
31 const CXXRecordDecl *MostDerivedClass,
32 bool GenerateDefinition)
33 : Ctx(Ctx), MostDerivedClass(MostDerivedClass),
34 MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)),
35 GenerateDefinition(GenerateDefinition) {
36 // Lay out this VTT.
37 LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()),
38 /*BaseIsVirtual=*/false);
39}
40
41void VTTBuilder::AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex,
42 const CXXRecordDecl *VTableClass) {
43 // Store the vtable pointer index if we're generating the primary VTT.
44 if (VTableClass == MostDerivedClass) {
45 assert(!SecondaryVirtualPointerIndices.count(Base) &&
46 "A virtual pointer index already exists for this base subobject!");
47 SecondaryVirtualPointerIndices[Base] = VTTComponents.size();
48 }
49
50 if (!GenerateDefinition) {
51 VTTComponents.push_back(VTTComponent());
52 return;
53 }
54
55 VTTComponents.push_back(VTTComponent(VTableIndex, Base));
56}
57
58void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) {
59 const CXXRecordDecl *RD = Base.getBase();
60
61 for (const auto &I : RD->bases()) {
62 // Don't layout virtual bases.
63 if (I.isVirtual())
64 continue;
65
66 const auto *BaseDecl =
67 cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
68
69 const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
70 CharUnits BaseOffset = Base.getBaseOffset() +
71 Layout.getBaseClassOffset(BaseDecl);
72
73 // Layout the VTT for this base.
74 LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false);
75 }
76}
77
78void
79VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
80 bool BaseIsMorallyVirtual,
81 uint64_t VTableIndex,
82 const CXXRecordDecl *VTableClass,
83 VisitedVirtualBasesSetTy &VBases) {
84 const CXXRecordDecl *RD = Base.getBase();
85
86 // We're not interested in bases that don't have virtual bases, and not
87 // morally virtual bases.
88 if (!RD->getNumVBases() && !BaseIsMorallyVirtual)
89 return;
90
91 for (const auto &I : RD->bases()) {
92 const auto *BaseDecl =
93 cast<CXXRecordDecl>(I.getType()->castAs<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).second)
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
145void
146VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
147 uint64_t VTableIndex) {
148 VisitedVirtualBasesSetTy VBases;
149 LayoutSecondaryVirtualPointers(Base, /*BaseIsMorallyVirtual=*/false,
150 VTableIndex, Base.getBase(), VBases);
151}
152
153void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD,
154 VisitedVirtualBasesSetTy &VBases) {
155 for (const auto &I : RD->bases()) {
156 const auto *BaseDecl =
157 cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
158
159 // Check if this is a virtual base.
160 if (I.isVirtual()) {
161 // Check if we've seen this base before.
162 if (!VBases.insert(BaseDecl).second)
163 continue;
164
165 CharUnits BaseOffset =
166 MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
167
168 LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true);
169 }
170
171 // We only need to layout virtual VTTs for this base if it actually has
172 // virtual bases.
173 if (BaseDecl->getNumVBases())
174 LayoutVirtualVTTs(BaseDecl, VBases);
175 }
176}
177
178void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) {
179 const CXXRecordDecl *RD = Base.getBase();
180
181 // Itanium C++ ABI 2.6.2:
182 // An array of virtual table addresses, called the VTT, is declared for
183 // each class type that has indirect or direct virtual base classes.
184 if (RD->getNumVBases() == 0)
185 return;
186
187 bool IsPrimaryVTT = Base.getBase() == MostDerivedClass;
188
189 if (!IsPrimaryVTT) {
190 // Remember the sub-VTT index.
191 SubVTTIndices[Base] = VTTComponents.size();
192 }
193
194 uint64_t VTableIndex = VTTVTables.size();
195 VTTVTables.push_back(VTTVTable(Base, BaseIsVirtual));
196
197 // Add the primary vtable pointer.
198 AddVTablePointer(Base, VTableIndex, RD);
199
200 // Add the secondary VTTs.
201 LayoutSecondaryVTTs(Base);
202
203 // Add the secondary virtual pointers.
204 LayoutSecondaryVirtualPointers(Base, VTableIndex);
205
206 // If this is the primary VTT, we want to lay out virtual VTTs as well.
207 if (IsPrimaryVTT) {
208 VisitedVirtualBasesSetTy VBases;
209 LayoutVirtualVTTs(Base.getBase(), VBases);
210 }
211}
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
Definition: RecordLayout.h:38
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
Definition: RecordLayout.h:249
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
Definition: RecordLayout.h:259
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
Definition: RecordLayout.h:234
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not.
Definition: RecordLayout.h:242
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
base_class_range bases()
Definition: DeclCXX.h:620
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
Definition: DeclCXX.h:635
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:38
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Definition: CharUnits.h:53
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:6072
RecordDecl * getDecl() const
Definition: Type.h:6082
VTTBuilder(ASTContext &Ctx, const CXXRecordDecl *MostDerivedClass, bool GenerateDefinition)
Definition: VTTBuilder.cpp:30
The JSON file list parser is used to communicate input to InstallAPI.
unsigned long uint64_t