1 //===--- VTableBuilder.cpp - C++ vtable layout builder --------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This contains code dealing with generation of the layout of virtual tables.
11 //===----------------------------------------------------------------------===//
13 #include "clang/AST/VTableBuilder.h"
14 #include "clang/AST/ASTContext.h"
15 #include "clang/AST/ASTDiagnostic.h"
16 #include "clang/AST/CXXInheritance.h"
17 #include "clang/AST/RecordLayout.h"
18 #include "clang/Basic/TargetInfo.h"
19 #include "llvm/ADT/SetOperations.h"
20 #include "llvm/ADT/SetVector.h"
21 #include "llvm/ADT/SmallPtrSet.h"
22 #include "llvm/Support/Format.h"
23 #include "llvm/Support/raw_ostream.h"
27 using namespace clang
;
29 #define DUMP_OVERRIDERS 0
33 /// BaseOffset - Represents an offset from a derived class to a direct or
34 /// indirect base class.
36 /// DerivedClass - The derived class.
37 const CXXRecordDecl
*DerivedClass
;
39 /// VirtualBase - If the path from the derived class to the base class
40 /// involves virtual base classes, this holds the declaration of the last
41 /// virtual base in this path (i.e. closest to the base class).
42 const CXXRecordDecl
*VirtualBase
;
44 /// NonVirtualOffset - The offset from the derived class to the base class.
45 /// (Or the offset from the virtual base class to the base class, if the
46 /// path from the derived class to the base class involves a virtual base
48 CharUnits NonVirtualOffset
;
50 BaseOffset() : DerivedClass(nullptr), VirtualBase(nullptr),
51 NonVirtualOffset(CharUnits::Zero()) { }
52 BaseOffset(const CXXRecordDecl
*DerivedClass
,
53 const CXXRecordDecl
*VirtualBase
, CharUnits NonVirtualOffset
)
54 : DerivedClass(DerivedClass
), VirtualBase(VirtualBase
),
55 NonVirtualOffset(NonVirtualOffset
) { }
57 bool isEmpty() const { return NonVirtualOffset
.isZero() && !VirtualBase
; }
60 /// FinalOverriders - Contains the final overrider member functions for all
61 /// member functions in the base subobjects of a class.
62 class FinalOverriders
{
64 /// OverriderInfo - Information about a final overrider.
65 struct OverriderInfo
{
66 /// Method - The method decl of the overrider.
67 const CXXMethodDecl
*Method
;
69 /// VirtualBase - The virtual base class subobject of this overrider.
70 /// Note that this records the closest derived virtual base class subobject.
71 const CXXRecordDecl
*VirtualBase
;
73 /// Offset - the base offset of the overrider's parent in the layout class.
76 OverriderInfo() : Method(nullptr), VirtualBase(nullptr),
77 Offset(CharUnits::Zero()) { }
81 /// MostDerivedClass - The most derived class for which the final overriders
83 const CXXRecordDecl
*MostDerivedClass
;
85 /// MostDerivedClassOffset - If we're building final overriders for a
86 /// construction vtable, this holds the offset from the layout class to the
87 /// most derived class.
88 const CharUnits MostDerivedClassOffset
;
90 /// LayoutClass - The class we're using for layout information. Will be
91 /// different than the most derived class if the final overriders are for a
92 /// construction vtable.
93 const CXXRecordDecl
*LayoutClass
;
97 /// MostDerivedClassLayout - the AST record layout of the most derived class.
98 const ASTRecordLayout
&MostDerivedClassLayout
;
100 /// MethodBaseOffsetPairTy - Uniquely identifies a member function
101 /// in a base subobject.
102 typedef std::pair
<const CXXMethodDecl
*, CharUnits
> MethodBaseOffsetPairTy
;
104 typedef llvm::DenseMap
<MethodBaseOffsetPairTy
,
105 OverriderInfo
> OverridersMapTy
;
107 /// OverridersMap - The final overriders for all virtual member functions of
108 /// all the base subobjects of the most derived class.
109 OverridersMapTy OverridersMap
;
111 /// SubobjectsToOffsetsMapTy - A mapping from a base subobject (represented
112 /// as a record decl and a subobject number) and its offsets in the most
113 /// derived class as well as the layout class.
114 typedef llvm::DenseMap
<std::pair
<const CXXRecordDecl
*, unsigned>,
115 CharUnits
> SubobjectOffsetMapTy
;
117 typedef llvm::DenseMap
<const CXXRecordDecl
*, unsigned> SubobjectCountMapTy
;
119 /// ComputeBaseOffsets - Compute the offsets for all base subobjects of the
121 void ComputeBaseOffsets(BaseSubobject Base
, bool IsVirtual
,
122 CharUnits OffsetInLayoutClass
,
123 SubobjectOffsetMapTy
&SubobjectOffsets
,
124 SubobjectOffsetMapTy
&SubobjectLayoutClassOffsets
,
125 SubobjectCountMapTy
&SubobjectCounts
);
127 typedef llvm::SmallPtrSet
<const CXXRecordDecl
*, 4> VisitedVirtualBasesSetTy
;
129 /// dump - dump the final overriders for a base subobject, and all its direct
130 /// and indirect base subobjects.
131 void dump(raw_ostream
&Out
, BaseSubobject Base
,
132 VisitedVirtualBasesSetTy
& VisitedVirtualBases
);
135 FinalOverriders(const CXXRecordDecl
*MostDerivedClass
,
136 CharUnits MostDerivedClassOffset
,
137 const CXXRecordDecl
*LayoutClass
);
139 /// getOverrider - Get the final overrider for the given method declaration in
140 /// the subobject with the given base offset.
141 OverriderInfo
getOverrider(const CXXMethodDecl
*MD
,
142 CharUnits BaseOffset
) const {
143 assert(OverridersMap
.count(std::make_pair(MD
, BaseOffset
)) &&
144 "Did not find overrider!");
146 return OverridersMap
.lookup(std::make_pair(MD
, BaseOffset
));
149 /// dump - dump the final overriders.
151 VisitedVirtualBasesSetTy VisitedVirtualBases
;
152 dump(llvm::errs(), BaseSubobject(MostDerivedClass
, CharUnits::Zero()),
153 VisitedVirtualBases
);
158 FinalOverriders::FinalOverriders(const CXXRecordDecl
*MostDerivedClass
,
159 CharUnits MostDerivedClassOffset
,
160 const CXXRecordDecl
*LayoutClass
)
161 : MostDerivedClass(MostDerivedClass
),
162 MostDerivedClassOffset(MostDerivedClassOffset
), LayoutClass(LayoutClass
),
163 Context(MostDerivedClass
->getASTContext()),
164 MostDerivedClassLayout(Context
.getASTRecordLayout(MostDerivedClass
)) {
166 // Compute base offsets.
167 SubobjectOffsetMapTy SubobjectOffsets
;
168 SubobjectOffsetMapTy SubobjectLayoutClassOffsets
;
169 SubobjectCountMapTy SubobjectCounts
;
170 ComputeBaseOffsets(BaseSubobject(MostDerivedClass
, CharUnits::Zero()),
172 MostDerivedClassOffset
,
173 SubobjectOffsets
, SubobjectLayoutClassOffsets
,
176 // Get the final overriders.
177 CXXFinalOverriderMap FinalOverriders
;
178 MostDerivedClass
->getFinalOverriders(FinalOverriders
);
180 for (const auto &Overrider
: FinalOverriders
) {
181 const CXXMethodDecl
*MD
= Overrider
.first
;
182 const OverridingMethods
&Methods
= Overrider
.second
;
184 for (const auto &M
: Methods
) {
185 unsigned SubobjectNumber
= M
.first
;
186 assert(SubobjectOffsets
.count(std::make_pair(MD
->getParent(),
188 "Did not find subobject offset!");
190 CharUnits BaseOffset
= SubobjectOffsets
[std::make_pair(MD
->getParent(),
193 assert(M
.second
.size() == 1 && "Final overrider is not unique!");
194 const UniqueVirtualMethod
&Method
= M
.second
.front();
196 const CXXRecordDecl
*OverriderRD
= Method
.Method
->getParent();
197 assert(SubobjectLayoutClassOffsets
.count(
198 std::make_pair(OverriderRD
, Method
.Subobject
))
199 && "Did not find subobject offset!");
200 CharUnits OverriderOffset
=
201 SubobjectLayoutClassOffsets
[std::make_pair(OverriderRD
,
204 OverriderInfo
& Overrider
= OverridersMap
[std::make_pair(MD
, BaseOffset
)];
205 assert(!Overrider
.Method
&& "Overrider should not exist yet!");
207 Overrider
.Offset
= OverriderOffset
;
208 Overrider
.Method
= Method
.Method
;
209 Overrider
.VirtualBase
= Method
.InVirtualSubobject
;
214 // And dump them (for now).
219 static BaseOffset
ComputeBaseOffset(const ASTContext
&Context
,
220 const CXXRecordDecl
*DerivedRD
,
221 const CXXBasePath
&Path
) {
222 CharUnits NonVirtualOffset
= CharUnits::Zero();
224 unsigned NonVirtualStart
= 0;
225 const CXXRecordDecl
*VirtualBase
= nullptr;
227 // First, look for the virtual base class.
228 for (int I
= Path
.size(), E
= 0; I
!= E
; --I
) {
229 const CXXBasePathElement
&Element
= Path
[I
- 1];
231 if (Element
.Base
->isVirtual()) {
233 QualType VBaseType
= Element
.Base
->getType();
234 VirtualBase
= VBaseType
->getAsCXXRecordDecl();
239 // Now compute the non-virtual offset.
240 for (unsigned I
= NonVirtualStart
, E
= Path
.size(); I
!= E
; ++I
) {
241 const CXXBasePathElement
&Element
= Path
[I
];
243 // Check the base class offset.
244 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(Element
.Class
);
246 const CXXRecordDecl
*Base
= Element
.Base
->getType()->getAsCXXRecordDecl();
248 NonVirtualOffset
+= Layout
.getBaseClassOffset(Base
);
251 // FIXME: This should probably use CharUnits or something. Maybe we should
252 // even change the base offsets in ASTRecordLayout to be specified in
254 return BaseOffset(DerivedRD
, VirtualBase
, NonVirtualOffset
);
258 static BaseOffset
ComputeBaseOffset(const ASTContext
&Context
,
259 const CXXRecordDecl
*BaseRD
,
260 const CXXRecordDecl
*DerivedRD
) {
261 CXXBasePaths
Paths(/*FindAmbiguities=*/false,
262 /*RecordPaths=*/true, /*DetectVirtual=*/false);
264 if (!DerivedRD
->isDerivedFrom(BaseRD
, Paths
))
265 llvm_unreachable("Class must be derived from the passed in base class!");
267 return ComputeBaseOffset(Context
, DerivedRD
, Paths
.front());
271 ComputeReturnAdjustmentBaseOffset(ASTContext
&Context
,
272 const CXXMethodDecl
*DerivedMD
,
273 const CXXMethodDecl
*BaseMD
) {
274 const auto *BaseFT
= BaseMD
->getType()->castAs
<FunctionType
>();
275 const auto *DerivedFT
= DerivedMD
->getType()->castAs
<FunctionType
>();
277 // Canonicalize the return types.
278 CanQualType CanDerivedReturnType
=
279 Context
.getCanonicalType(DerivedFT
->getReturnType());
280 CanQualType CanBaseReturnType
=
281 Context
.getCanonicalType(BaseFT
->getReturnType());
283 assert(CanDerivedReturnType
->getTypeClass() ==
284 CanBaseReturnType
->getTypeClass() &&
285 "Types must have same type class!");
287 if (CanDerivedReturnType
== CanBaseReturnType
) {
288 // No adjustment needed.
292 if (isa
<ReferenceType
>(CanDerivedReturnType
)) {
293 CanDerivedReturnType
=
294 CanDerivedReturnType
->getAs
<ReferenceType
>()->getPointeeType();
296 CanBaseReturnType
->getAs
<ReferenceType
>()->getPointeeType();
297 } else if (isa
<PointerType
>(CanDerivedReturnType
)) {
298 CanDerivedReturnType
=
299 CanDerivedReturnType
->getAs
<PointerType
>()->getPointeeType();
301 CanBaseReturnType
->getAs
<PointerType
>()->getPointeeType();
303 llvm_unreachable("Unexpected return type!");
306 // We need to compare unqualified types here; consider
307 // const T *Base::foo();
308 // T *Derived::foo();
309 if (CanDerivedReturnType
.getUnqualifiedType() ==
310 CanBaseReturnType
.getUnqualifiedType()) {
311 // No adjustment needed.
315 const CXXRecordDecl
*DerivedRD
=
316 cast
<CXXRecordDecl
>(cast
<RecordType
>(CanDerivedReturnType
)->getDecl());
318 const CXXRecordDecl
*BaseRD
=
319 cast
<CXXRecordDecl
>(cast
<RecordType
>(CanBaseReturnType
)->getDecl());
321 return ComputeBaseOffset(Context
, BaseRD
, DerivedRD
);
325 FinalOverriders::ComputeBaseOffsets(BaseSubobject Base
, bool IsVirtual
,
326 CharUnits OffsetInLayoutClass
,
327 SubobjectOffsetMapTy
&SubobjectOffsets
,
328 SubobjectOffsetMapTy
&SubobjectLayoutClassOffsets
,
329 SubobjectCountMapTy
&SubobjectCounts
) {
330 const CXXRecordDecl
*RD
= Base
.getBase();
332 unsigned SubobjectNumber
= 0;
334 SubobjectNumber
= ++SubobjectCounts
[RD
];
336 // Set up the subobject to offset mapping.
337 assert(!SubobjectOffsets
.count(std::make_pair(RD
, SubobjectNumber
))
338 && "Subobject offset already exists!");
339 assert(!SubobjectLayoutClassOffsets
.count(std::make_pair(RD
, SubobjectNumber
))
340 && "Subobject offset already exists!");
342 SubobjectOffsets
[std::make_pair(RD
, SubobjectNumber
)] = Base
.getBaseOffset();
343 SubobjectLayoutClassOffsets
[std::make_pair(RD
, SubobjectNumber
)] =
346 // Traverse our bases.
347 for (const auto &B
: RD
->bases()) {
348 const CXXRecordDecl
*BaseDecl
= B
.getType()->getAsCXXRecordDecl();
350 CharUnits BaseOffset
;
351 CharUnits BaseOffsetInLayoutClass
;
353 // Check if we've visited this virtual base before.
354 if (SubobjectOffsets
.count(std::make_pair(BaseDecl
, 0)))
357 const ASTRecordLayout
&LayoutClassLayout
=
358 Context
.getASTRecordLayout(LayoutClass
);
360 BaseOffset
= MostDerivedClassLayout
.getVBaseClassOffset(BaseDecl
);
361 BaseOffsetInLayoutClass
=
362 LayoutClassLayout
.getVBaseClassOffset(BaseDecl
);
364 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(RD
);
365 CharUnits Offset
= Layout
.getBaseClassOffset(BaseDecl
);
367 BaseOffset
= Base
.getBaseOffset() + Offset
;
368 BaseOffsetInLayoutClass
= OffsetInLayoutClass
+ Offset
;
371 ComputeBaseOffsets(BaseSubobject(BaseDecl
, BaseOffset
),
372 B
.isVirtual(), BaseOffsetInLayoutClass
,
373 SubobjectOffsets
, SubobjectLayoutClassOffsets
,
378 void FinalOverriders::dump(raw_ostream
&Out
, BaseSubobject Base
,
379 VisitedVirtualBasesSetTy
&VisitedVirtualBases
) {
380 const CXXRecordDecl
*RD
= Base
.getBase();
381 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(RD
);
383 for (const auto &B
: RD
->bases()) {
384 const CXXRecordDecl
*BaseDecl
= B
.getType()->getAsCXXRecordDecl();
386 // Ignore bases that don't have any virtual member functions.
387 if (!BaseDecl
->isPolymorphic())
390 CharUnits BaseOffset
;
392 if (!VisitedVirtualBases
.insert(BaseDecl
).second
) {
393 // We've visited this base before.
397 BaseOffset
= MostDerivedClassLayout
.getVBaseClassOffset(BaseDecl
);
399 BaseOffset
= Layout
.getBaseClassOffset(BaseDecl
) + Base
.getBaseOffset();
402 dump(Out
, BaseSubobject(BaseDecl
, BaseOffset
), VisitedVirtualBases
);
405 Out
<< "Final overriders for (";
406 RD
->printQualifiedName(Out
);
408 Out
<< Base
.getBaseOffset().getQuantity() << ")\n";
410 // Now dump the overriders for this base subobject.
411 for (const auto *MD
: RD
->methods()) {
412 if (!VTableContextBase::hasVtableSlot(MD
))
414 MD
= MD
->getCanonicalDecl();
416 OverriderInfo Overrider
= getOverrider(MD
, Base
.getBaseOffset());
419 MD
->printQualifiedName(Out
);
421 Overrider
.Method
->printQualifiedName(Out
);
422 Out
<< ", " << Overrider
.Offset
.getQuantity() << ')';
425 if (!Overrider
.Method
->isPure())
426 Offset
= ComputeReturnAdjustmentBaseOffset(Context
, Overrider
.Method
, MD
);
428 if (!Offset
.isEmpty()) {
429 Out
<< " [ret-adj: ";
430 if (Offset
.VirtualBase
) {
431 Offset
.VirtualBase
->printQualifiedName(Out
);
435 Out
<< Offset
.NonVirtualOffset
.getQuantity() << " nv]";
442 /// VCallOffsetMap - Keeps track of vcall offsets when building a vtable.
443 struct VCallOffsetMap
{
445 typedef std::pair
<const CXXMethodDecl
*, CharUnits
> MethodAndOffsetPairTy
;
447 /// Offsets - Keeps track of methods and their offsets.
448 // FIXME: This should be a real map and not a vector.
449 SmallVector
<MethodAndOffsetPairTy
, 16> Offsets
;
451 /// MethodsCanShareVCallOffset - Returns whether two virtual member functions
452 /// can share the same vcall offset.
453 static bool MethodsCanShareVCallOffset(const CXXMethodDecl
*LHS
,
454 const CXXMethodDecl
*RHS
);
457 /// AddVCallOffset - Adds a vcall offset to the map. Returns true if the
458 /// add was successful, or false if there was already a member function with
459 /// the same signature in the map.
460 bool AddVCallOffset(const CXXMethodDecl
*MD
, CharUnits OffsetOffset
);
462 /// getVCallOffsetOffset - Returns the vcall offset offset (relative to the
463 /// vtable address point) for the given virtual member function.
464 CharUnits
getVCallOffsetOffset(const CXXMethodDecl
*MD
);
466 // empty - Return whether the offset map is empty or not.
467 bool empty() const { return Offsets
.empty(); }
470 static bool HasSameVirtualSignature(const CXXMethodDecl
*LHS
,
471 const CXXMethodDecl
*RHS
) {
472 const FunctionProtoType
*LT
=
473 cast
<FunctionProtoType
>(LHS
->getType().getCanonicalType());
474 const FunctionProtoType
*RT
=
475 cast
<FunctionProtoType
>(RHS
->getType().getCanonicalType());
477 // Fast-path matches in the canonical types.
478 if (LT
== RT
) return true;
480 // Force the signatures to match. We can't rely on the overrides
481 // list here because there isn't necessarily an inheritance
482 // relationship between the two methods.
483 if (LT
->getMethodQuals() != RT
->getMethodQuals())
485 return LT
->getParamTypes() == RT
->getParamTypes();
488 bool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl
*LHS
,
489 const CXXMethodDecl
*RHS
) {
490 assert(VTableContextBase::hasVtableSlot(LHS
) && "LHS must be virtual!");
491 assert(VTableContextBase::hasVtableSlot(RHS
) && "RHS must be virtual!");
493 // A destructor can share a vcall offset with another destructor.
494 if (isa
<CXXDestructorDecl
>(LHS
))
495 return isa
<CXXDestructorDecl
>(RHS
);
497 // FIXME: We need to check more things here.
499 // The methods must have the same name.
500 DeclarationName LHSName
= LHS
->getDeclName();
501 DeclarationName RHSName
= RHS
->getDeclName();
502 if (LHSName
!= RHSName
)
505 // And the same signatures.
506 return HasSameVirtualSignature(LHS
, RHS
);
509 bool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl
*MD
,
510 CharUnits OffsetOffset
) {
511 // Check if we can reuse an offset.
512 for (const auto &OffsetPair
: Offsets
) {
513 if (MethodsCanShareVCallOffset(OffsetPair
.first
, MD
))
518 Offsets
.push_back(MethodAndOffsetPairTy(MD
, OffsetOffset
));
522 CharUnits
VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl
*MD
) {
523 // Look for an offset.
524 for (const auto &OffsetPair
: Offsets
) {
525 if (MethodsCanShareVCallOffset(OffsetPair
.first
, MD
))
526 return OffsetPair
.second
;
529 llvm_unreachable("Should always find a vcall offset offset!");
532 /// VCallAndVBaseOffsetBuilder - Class for building vcall and vbase offsets.
533 class VCallAndVBaseOffsetBuilder
{
535 typedef llvm::DenseMap
<const CXXRecordDecl
*, CharUnits
>
536 VBaseOffsetOffsetsMapTy
;
539 const ItaniumVTableContext
&VTables
;
541 /// MostDerivedClass - The most derived class for which we're building vcall
542 /// and vbase offsets.
543 const CXXRecordDecl
*MostDerivedClass
;
545 /// LayoutClass - The class we're using for layout information. Will be
546 /// different than the most derived class if we're building a construction
548 const CXXRecordDecl
*LayoutClass
;
550 /// Context - The ASTContext which we will use for layout information.
553 /// Components - vcall and vbase offset components
554 typedef SmallVector
<VTableComponent
, 64> VTableComponentVectorTy
;
555 VTableComponentVectorTy Components
;
557 /// VisitedVirtualBases - Visited virtual bases.
558 llvm::SmallPtrSet
<const CXXRecordDecl
*, 4> VisitedVirtualBases
;
560 /// VCallOffsets - Keeps track of vcall offsets.
561 VCallOffsetMap VCallOffsets
;
564 /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets,
565 /// relative to the address point.
566 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets
;
568 /// FinalOverriders - The final overriders of the most derived class.
569 /// (Can be null when we're not building a vtable of the most derived class).
570 const FinalOverriders
*Overriders
;
572 /// AddVCallAndVBaseOffsets - Add vcall offsets and vbase offsets for the
573 /// given base subobject.
574 void AddVCallAndVBaseOffsets(BaseSubobject Base
, bool BaseIsVirtual
,
575 CharUnits RealBaseOffset
);
577 /// AddVCallOffsets - Add vcall offsets for the given base subobject.
578 void AddVCallOffsets(BaseSubobject Base
, CharUnits VBaseOffset
);
580 /// AddVBaseOffsets - Add vbase offsets for the given class.
581 void AddVBaseOffsets(const CXXRecordDecl
*Base
,
582 CharUnits OffsetInLayoutClass
);
584 /// getCurrentOffsetOffset - Get the current vcall or vbase offset offset in
585 /// chars, relative to the vtable address point.
586 CharUnits
getCurrentOffsetOffset() const;
589 VCallAndVBaseOffsetBuilder(const ItaniumVTableContext
&VTables
,
590 const CXXRecordDecl
*MostDerivedClass
,
591 const CXXRecordDecl
*LayoutClass
,
592 const FinalOverriders
*Overriders
,
593 BaseSubobject Base
, bool BaseIsVirtual
,
594 CharUnits OffsetInLayoutClass
)
595 : VTables(VTables
), MostDerivedClass(MostDerivedClass
),
596 LayoutClass(LayoutClass
), Context(MostDerivedClass
->getASTContext()),
597 Overriders(Overriders
) {
599 // Add vcall and vbase offsets.
600 AddVCallAndVBaseOffsets(Base
, BaseIsVirtual
, OffsetInLayoutClass
);
603 /// Methods for iterating over the components.
604 typedef VTableComponentVectorTy::const_reverse_iterator const_iterator
;
605 const_iterator
components_begin() const { return Components
.rbegin(); }
606 const_iterator
components_end() const { return Components
.rend(); }
608 const VCallOffsetMap
&getVCallOffsets() const { return VCallOffsets
; }
609 const VBaseOffsetOffsetsMapTy
&getVBaseOffsetOffsets() const {
610 return VBaseOffsetOffsets
;
615 VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base
,
617 CharUnits RealBaseOffset
) {
618 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(Base
.getBase());
620 // Itanium C++ ABI 2.5.2:
621 // ..in classes sharing a virtual table with a primary base class, the vcall
622 // and vbase offsets added by the derived class all come before the vcall
623 // and vbase offsets required by the base class, so that the latter may be
624 // laid out as required by the base class without regard to additions from
625 // the derived class(es).
627 // (Since we're emitting the vcall and vbase offsets in reverse order, we'll
628 // emit them for the primary base first).
629 if (const CXXRecordDecl
*PrimaryBase
= Layout
.getPrimaryBase()) {
630 bool PrimaryBaseIsVirtual
= Layout
.isPrimaryBaseVirtual();
632 CharUnits PrimaryBaseOffset
;
634 // Get the base offset of the primary base.
635 if (PrimaryBaseIsVirtual
) {
636 assert(Layout
.getVBaseClassOffset(PrimaryBase
).isZero() &&
637 "Primary vbase should have a zero offset!");
639 const ASTRecordLayout
&MostDerivedClassLayout
=
640 Context
.getASTRecordLayout(MostDerivedClass
);
643 MostDerivedClassLayout
.getVBaseClassOffset(PrimaryBase
);
645 assert(Layout
.getBaseClassOffset(PrimaryBase
).isZero() &&
646 "Primary base should have a zero offset!");
648 PrimaryBaseOffset
= Base
.getBaseOffset();
651 AddVCallAndVBaseOffsets(
652 BaseSubobject(PrimaryBase
,PrimaryBaseOffset
),
653 PrimaryBaseIsVirtual
, RealBaseOffset
);
656 AddVBaseOffsets(Base
.getBase(), RealBaseOffset
);
658 // We only want to add vcall offsets for virtual bases.
660 AddVCallOffsets(Base
, RealBaseOffset
);
663 CharUnits
VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset() const {
664 // OffsetIndex is the index of this vcall or vbase offset, relative to the
665 // vtable address point. (We subtract 3 to account for the information just
666 // above the address point, the RTTI info, the offset to top, and the
667 // vcall offset itself).
668 size_t NumComponentsAboveAddrPoint
= 3;
669 if (Context
.getLangOpts().OmitVTableRTTI
)
670 NumComponentsAboveAddrPoint
--;
671 int64_t OffsetIndex
=
672 -(int64_t)(NumComponentsAboveAddrPoint
+ Components
.size());
674 // Under the relative ABI, the offset widths are 32-bit ints instead of
676 CharUnits OffsetWidth
= Context
.toCharUnitsFromBits(
677 VTables
.isRelativeLayout()
679 : Context
.getTargetInfo().getPointerWidth(LangAS::Default
));
680 CharUnits OffsetOffset
= OffsetWidth
* OffsetIndex
;
685 void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base
,
686 CharUnits VBaseOffset
) {
687 const CXXRecordDecl
*RD
= Base
.getBase();
688 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(RD
);
690 const CXXRecordDecl
*PrimaryBase
= Layout
.getPrimaryBase();
692 // Handle the primary base first.
693 // We only want to add vcall offsets if the base is non-virtual; a virtual
694 // primary base will have its vcall and vbase offsets emitted already.
695 if (PrimaryBase
&& !Layout
.isPrimaryBaseVirtual()) {
696 // Get the base offset of the primary base.
697 assert(Layout
.getBaseClassOffset(PrimaryBase
).isZero() &&
698 "Primary base should have a zero offset!");
700 AddVCallOffsets(BaseSubobject(PrimaryBase
, Base
.getBaseOffset()),
704 // Add the vcall offsets.
705 for (const auto *MD
: RD
->methods()) {
706 if (!VTableContextBase::hasVtableSlot(MD
))
708 MD
= MD
->getCanonicalDecl();
710 CharUnits OffsetOffset
= getCurrentOffsetOffset();
712 // Don't add a vcall offset if we already have one for this member function
714 if (!VCallOffsets
.AddVCallOffset(MD
, OffsetOffset
))
717 CharUnits Offset
= CharUnits::Zero();
720 // Get the final overrider.
721 FinalOverriders::OverriderInfo Overrider
=
722 Overriders
->getOverrider(MD
, Base
.getBaseOffset());
724 /// The vcall offset is the offset from the virtual base to the object
725 /// where the function was overridden.
726 Offset
= Overrider
.Offset
- VBaseOffset
;
729 Components
.push_back(
730 VTableComponent::MakeVCallOffset(Offset
));
733 // And iterate over all non-virtual bases (ignoring the primary base).
734 for (const auto &B
: RD
->bases()) {
738 const CXXRecordDecl
*BaseDecl
= B
.getType()->getAsCXXRecordDecl();
739 if (BaseDecl
== PrimaryBase
)
742 // Get the base offset of this base.
743 CharUnits BaseOffset
= Base
.getBaseOffset() +
744 Layout
.getBaseClassOffset(BaseDecl
);
746 AddVCallOffsets(BaseSubobject(BaseDecl
, BaseOffset
),
752 VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl
*RD
,
753 CharUnits OffsetInLayoutClass
) {
754 const ASTRecordLayout
&LayoutClassLayout
=
755 Context
.getASTRecordLayout(LayoutClass
);
757 // Add vbase offsets.
758 for (const auto &B
: RD
->bases()) {
759 const CXXRecordDecl
*BaseDecl
= B
.getType()->getAsCXXRecordDecl();
761 // Check if this is a virtual base that we haven't visited before.
762 if (B
.isVirtual() && VisitedVirtualBases
.insert(BaseDecl
).second
) {
764 LayoutClassLayout
.getVBaseClassOffset(BaseDecl
) - OffsetInLayoutClass
;
766 // Add the vbase offset offset.
767 assert(!VBaseOffsetOffsets
.count(BaseDecl
) &&
768 "vbase offset offset already exists!");
770 CharUnits VBaseOffsetOffset
= getCurrentOffsetOffset();
771 VBaseOffsetOffsets
.insert(
772 std::make_pair(BaseDecl
, VBaseOffsetOffset
));
774 Components
.push_back(
775 VTableComponent::MakeVBaseOffset(Offset
));
778 // Check the base class looking for more vbase offsets.
779 AddVBaseOffsets(BaseDecl
, OffsetInLayoutClass
);
783 /// ItaniumVTableBuilder - Class for building vtable layout information.
784 class ItaniumVTableBuilder
{
786 /// PrimaryBasesSetVectorTy - A set vector of direct and indirect
788 typedef llvm::SmallSetVector
<const CXXRecordDecl
*, 8>
789 PrimaryBasesSetVectorTy
;
791 typedef llvm::DenseMap
<const CXXRecordDecl
*, CharUnits
>
792 VBaseOffsetOffsetsMapTy
;
794 typedef VTableLayout::AddressPointsMapTy AddressPointsMapTy
;
796 typedef llvm::DenseMap
<GlobalDecl
, int64_t> MethodVTableIndicesTy
;
799 /// VTables - Global vtable information.
800 ItaniumVTableContext
&VTables
;
802 /// MostDerivedClass - The most derived class for which we're building this
804 const CXXRecordDecl
*MostDerivedClass
;
806 /// MostDerivedClassOffset - If we're building a construction vtable, this
807 /// holds the offset from the layout class to the most derived class.
808 const CharUnits MostDerivedClassOffset
;
810 /// MostDerivedClassIsVirtual - Whether the most derived class is a virtual
811 /// base. (This only makes sense when building a construction vtable).
812 bool MostDerivedClassIsVirtual
;
814 /// LayoutClass - The class we're using for layout information. Will be
815 /// different than the most derived class if we're building a construction
817 const CXXRecordDecl
*LayoutClass
;
819 /// Context - The ASTContext which we will use for layout information.
822 /// FinalOverriders - The final overriders of the most derived class.
823 const FinalOverriders Overriders
;
825 /// VCallOffsetsForVBases - Keeps track of vcall offsets for the virtual
826 /// bases in this vtable.
827 llvm::DenseMap
<const CXXRecordDecl
*, VCallOffsetMap
> VCallOffsetsForVBases
;
829 /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for
830 /// the most derived class.
831 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets
;
833 /// Components - The components of the vtable being built.
834 SmallVector
<VTableComponent
, 64> Components
;
836 /// AddressPoints - Address points for the vtable being built.
837 AddressPointsMapTy AddressPoints
;
839 /// MethodInfo - Contains information about a method in a vtable.
840 /// (Used for computing 'this' pointer adjustment thunks.
842 /// BaseOffset - The base offset of this method.
843 const CharUnits BaseOffset
;
845 /// BaseOffsetInLayoutClass - The base offset in the layout class of this
847 const CharUnits BaseOffsetInLayoutClass
;
849 /// VTableIndex - The index in the vtable that this method has.
850 /// (For destructors, this is the index of the complete destructor).
851 const uint64_t VTableIndex
;
853 MethodInfo(CharUnits BaseOffset
, CharUnits BaseOffsetInLayoutClass
,
854 uint64_t VTableIndex
)
855 : BaseOffset(BaseOffset
),
856 BaseOffsetInLayoutClass(BaseOffsetInLayoutClass
),
857 VTableIndex(VTableIndex
) { }
860 : BaseOffset(CharUnits::Zero()),
861 BaseOffsetInLayoutClass(CharUnits::Zero()),
864 MethodInfo(MethodInfo
const&) = default;
867 typedef llvm::DenseMap
<const CXXMethodDecl
*, MethodInfo
> MethodInfoMapTy
;
869 /// MethodInfoMap - The information for all methods in the vtable we're
870 /// currently building.
871 MethodInfoMapTy MethodInfoMap
;
873 /// MethodVTableIndices - Contains the index (relative to the vtable address
874 /// point) where the function pointer for a virtual function is stored.
875 MethodVTableIndicesTy MethodVTableIndices
;
877 typedef llvm::DenseMap
<uint64_t, ThunkInfo
> VTableThunksMapTy
;
879 /// VTableThunks - The thunks by vtable index in the vtable currently being
881 VTableThunksMapTy VTableThunks
;
883 typedef SmallVector
<ThunkInfo
, 1> ThunkInfoVectorTy
;
884 typedef llvm::DenseMap
<const CXXMethodDecl
*, ThunkInfoVectorTy
> ThunksMapTy
;
886 /// Thunks - A map that contains all the thunks needed for all methods in the
887 /// most derived class for which the vtable is currently being built.
890 /// AddThunk - Add a thunk for the given method.
891 void AddThunk(const CXXMethodDecl
*MD
, const ThunkInfo
&Thunk
);
893 /// ComputeThisAdjustments - Compute the 'this' pointer adjustments for the
894 /// part of the vtable we're currently building.
895 void ComputeThisAdjustments();
897 typedef llvm::SmallPtrSet
<const CXXRecordDecl
*, 4> VisitedVirtualBasesSetTy
;
899 /// PrimaryVirtualBases - All known virtual bases who are a primary base of
901 VisitedVirtualBasesSetTy PrimaryVirtualBases
;
903 /// ComputeReturnAdjustment - Compute the return adjustment given a return
904 /// adjustment base offset.
905 ReturnAdjustment
ComputeReturnAdjustment(BaseOffset Offset
);
907 /// ComputeThisAdjustmentBaseOffset - Compute the base offset for adjusting
908 /// the 'this' pointer from the base subobject to the derived subobject.
909 BaseOffset
ComputeThisAdjustmentBaseOffset(BaseSubobject Base
,
910 BaseSubobject Derived
) const;
912 /// ComputeThisAdjustment - Compute the 'this' pointer adjustment for the
913 /// given virtual member function, its offset in the layout class and its
916 ComputeThisAdjustment(const CXXMethodDecl
*MD
,
917 CharUnits BaseOffsetInLayoutClass
,
918 FinalOverriders::OverriderInfo Overrider
);
920 /// AddMethod - Add a single virtual member function to the vtable
921 /// components vector.
922 void AddMethod(const CXXMethodDecl
*MD
, ReturnAdjustment ReturnAdjustment
);
924 /// IsOverriderUsed - Returns whether the overrider will ever be used in this
925 /// part of the vtable.
927 /// Itanium C++ ABI 2.5.2:
929 /// struct A { virtual void f(); };
930 /// struct B : virtual public A { int i; };
931 /// struct C : virtual public A { int j; };
932 /// struct D : public B, public C {};
934 /// When B and C are declared, A is a primary base in each case, so although
935 /// vcall offsets are allocated in the A-in-B and A-in-C vtables, no this
936 /// adjustment is required and no thunk is generated. However, inside D
937 /// objects, A is no longer a primary base of C, so if we allowed calls to
938 /// C::f() to use the copy of A's vtable in the C subobject, we would need
939 /// to adjust this from C* to B::A*, which would require a third-party
940 /// thunk. Since we require that a call to C::f() first convert to A*,
941 /// C-in-D's copy of A's vtable is never referenced, so this is not
943 bool IsOverriderUsed(const CXXMethodDecl
*Overrider
,
944 CharUnits BaseOffsetInLayoutClass
,
945 const CXXRecordDecl
*FirstBaseInPrimaryBaseChain
,
946 CharUnits FirstBaseOffsetInLayoutClass
) const;
949 /// AddMethods - Add the methods of this base subobject and all its
950 /// primary bases to the vtable components vector.
951 void AddMethods(BaseSubobject Base
, CharUnits BaseOffsetInLayoutClass
,
952 const CXXRecordDecl
*FirstBaseInPrimaryBaseChain
,
953 CharUnits FirstBaseOffsetInLayoutClass
,
954 PrimaryBasesSetVectorTy
&PrimaryBases
);
956 // LayoutVTable - Layout the vtable for the given base class, including its
957 // secondary vtables and any vtables for virtual bases.
960 /// LayoutPrimaryAndSecondaryVTables - Layout the primary vtable for the
961 /// given base subobject, as well as all its secondary vtables.
963 /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
964 /// or a direct or indirect base of a virtual base.
966 /// \param BaseIsVirtualInLayoutClass - Whether the base subobject is virtual
967 /// in the layout class.
968 void LayoutPrimaryAndSecondaryVTables(BaseSubobject Base
,
969 bool BaseIsMorallyVirtual
,
970 bool BaseIsVirtualInLayoutClass
,
971 CharUnits OffsetInLayoutClass
);
973 /// LayoutSecondaryVTables - Layout the secondary vtables for the given base
976 /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
977 /// or a direct or indirect base of a virtual base.
978 void LayoutSecondaryVTables(BaseSubobject Base
, bool BaseIsMorallyVirtual
,
979 CharUnits OffsetInLayoutClass
);
981 /// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this
983 void DeterminePrimaryVirtualBases(const CXXRecordDecl
*RD
,
984 CharUnits OffsetInLayoutClass
,
985 VisitedVirtualBasesSetTy
&VBases
);
987 /// LayoutVTablesForVirtualBases - Layout vtables for all virtual bases of the
988 /// given base (excluding any primary bases).
989 void LayoutVTablesForVirtualBases(const CXXRecordDecl
*RD
,
990 VisitedVirtualBasesSetTy
&VBases
);
992 /// isBuildingConstructionVTable - Return whether this vtable builder is
993 /// building a construction vtable.
994 bool isBuildingConstructorVTable() const {
995 return MostDerivedClass
!= LayoutClass
;
999 /// Component indices of the first component of each of the vtables in the
1001 SmallVector
<size_t, 4> VTableIndices
;
1003 ItaniumVTableBuilder(ItaniumVTableContext
&VTables
,
1004 const CXXRecordDecl
*MostDerivedClass
,
1005 CharUnits MostDerivedClassOffset
,
1006 bool MostDerivedClassIsVirtual
,
1007 const CXXRecordDecl
*LayoutClass
)
1008 : VTables(VTables
), MostDerivedClass(MostDerivedClass
),
1009 MostDerivedClassOffset(MostDerivedClassOffset
),
1010 MostDerivedClassIsVirtual(MostDerivedClassIsVirtual
),
1011 LayoutClass(LayoutClass
), Context(MostDerivedClass
->getASTContext()),
1012 Overriders(MostDerivedClass
, MostDerivedClassOffset
, LayoutClass
) {
1013 assert(!Context
.getTargetInfo().getCXXABI().isMicrosoft());
1017 if (Context
.getLangOpts().DumpVTableLayouts
)
1018 dumpLayout(llvm::outs());
1021 uint64_t getNumThunks() const {
1022 return Thunks
.size();
1025 ThunksMapTy::const_iterator
thunks_begin() const {
1026 return Thunks
.begin();
1029 ThunksMapTy::const_iterator
thunks_end() const {
1030 return Thunks
.end();
1033 const VBaseOffsetOffsetsMapTy
&getVBaseOffsetOffsets() const {
1034 return VBaseOffsetOffsets
;
1037 const AddressPointsMapTy
&getAddressPoints() const {
1038 return AddressPoints
;
1041 MethodVTableIndicesTy::const_iterator
vtable_indices_begin() const {
1042 return MethodVTableIndices
.begin();
1045 MethodVTableIndicesTy::const_iterator
vtable_indices_end() const {
1046 return MethodVTableIndices
.end();
1049 ArrayRef
<VTableComponent
> vtable_components() const { return Components
; }
1051 AddressPointsMapTy::const_iterator
address_points_begin() const {
1052 return AddressPoints
.begin();
1055 AddressPointsMapTy::const_iterator
address_points_end() const {
1056 return AddressPoints
.end();
1059 VTableThunksMapTy::const_iterator
vtable_thunks_begin() const {
1060 return VTableThunks
.begin();
1063 VTableThunksMapTy::const_iterator
vtable_thunks_end() const {
1064 return VTableThunks
.end();
1067 /// dumpLayout - Dump the vtable layout.
1068 void dumpLayout(raw_ostream
&);
1071 void ItaniumVTableBuilder::AddThunk(const CXXMethodDecl
*MD
,
1072 const ThunkInfo
&Thunk
) {
1073 assert(!isBuildingConstructorVTable() &&
1074 "Can't add thunks for construction vtable");
1076 SmallVectorImpl
<ThunkInfo
> &ThunksVector
= Thunks
[MD
];
1078 // Check if we have this thunk already.
1079 if (llvm::is_contained(ThunksVector
, Thunk
))
1082 ThunksVector
.push_back(Thunk
);
1085 typedef llvm::SmallPtrSet
<const CXXMethodDecl
*, 8> OverriddenMethodsSetTy
;
1087 /// Visit all the methods overridden by the given method recursively,
1088 /// in a depth-first pre-order. The Visitor's visitor method returns a bool
1089 /// indicating whether to continue the recursion for the given overridden
1090 /// method (i.e. returning false stops the iteration).
1091 template <class VisitorTy
>
1093 visitAllOverriddenMethods(const CXXMethodDecl
*MD
, VisitorTy
&Visitor
) {
1094 assert(VTableContextBase::hasVtableSlot(MD
) && "Method is not virtual!");
1096 for (const CXXMethodDecl
*OverriddenMD
: MD
->overridden_methods()) {
1097 if (!Visitor(OverriddenMD
))
1099 visitAllOverriddenMethods(OverriddenMD
, Visitor
);
1103 /// ComputeAllOverriddenMethods - Given a method decl, will return a set of all
1104 /// the overridden methods that the function decl overrides.
1106 ComputeAllOverriddenMethods(const CXXMethodDecl
*MD
,
1107 OverriddenMethodsSetTy
& OverriddenMethods
) {
1108 auto OverriddenMethodsCollector
= [&](const CXXMethodDecl
*MD
) {
1109 // Don't recurse on this method if we've already collected it.
1110 return OverriddenMethods
.insert(MD
).second
;
1112 visitAllOverriddenMethods(MD
, OverriddenMethodsCollector
);
1115 void ItaniumVTableBuilder::ComputeThisAdjustments() {
1116 // Now go through the method info map and see if any of the methods need
1117 // 'this' pointer adjustments.
1118 for (const auto &MI
: MethodInfoMap
) {
1119 const CXXMethodDecl
*MD
= MI
.first
;
1120 const MethodInfo
&MethodInfo
= MI
.second
;
1122 // Ignore adjustments for unused function pointers.
1123 uint64_t VTableIndex
= MethodInfo
.VTableIndex
;
1124 if (Components
[VTableIndex
].getKind() ==
1125 VTableComponent::CK_UnusedFunctionPointer
)
1128 // Get the final overrider for this method.
1129 FinalOverriders::OverriderInfo Overrider
=
1130 Overriders
.getOverrider(MD
, MethodInfo
.BaseOffset
);
1132 // Check if we need an adjustment at all.
1133 if (MethodInfo
.BaseOffsetInLayoutClass
== Overrider
.Offset
) {
1134 // When a return thunk is needed by a derived class that overrides a
1135 // virtual base, gcc uses a virtual 'this' adjustment as well.
1136 // While the thunk itself might be needed by vtables in subclasses or
1137 // in construction vtables, there doesn't seem to be a reason for using
1138 // the thunk in this vtable. Still, we do so to match gcc.
1139 if (VTableThunks
.lookup(VTableIndex
).Return
.isEmpty())
1143 ThisAdjustment ThisAdjustment
=
1144 ComputeThisAdjustment(MD
, MethodInfo
.BaseOffsetInLayoutClass
, Overrider
);
1146 if (ThisAdjustment
.isEmpty())
1150 VTableThunks
[VTableIndex
].This
= ThisAdjustment
;
1152 if (isa
<CXXDestructorDecl
>(MD
)) {
1153 // Add an adjustment for the deleting destructor as well.
1154 VTableThunks
[VTableIndex
+ 1].This
= ThisAdjustment
;
1158 /// Clear the method info map.
1159 MethodInfoMap
.clear();
1161 if (isBuildingConstructorVTable()) {
1162 // We don't need to store thunk information for construction vtables.
1166 for (const auto &TI
: VTableThunks
) {
1167 const VTableComponent
&Component
= Components
[TI
.first
];
1168 const ThunkInfo
&Thunk
= TI
.second
;
1169 const CXXMethodDecl
*MD
;
1171 switch (Component
.getKind()) {
1173 llvm_unreachable("Unexpected vtable component kind!");
1174 case VTableComponent::CK_FunctionPointer
:
1175 MD
= Component
.getFunctionDecl();
1177 case VTableComponent::CK_CompleteDtorPointer
:
1178 MD
= Component
.getDestructorDecl();
1180 case VTableComponent::CK_DeletingDtorPointer
:
1181 // We've already added the thunk when we saw the complete dtor pointer.
1185 if (MD
->getParent() == MostDerivedClass
)
1186 AddThunk(MD
, Thunk
);
1191 ItaniumVTableBuilder::ComputeReturnAdjustment(BaseOffset Offset
) {
1192 ReturnAdjustment Adjustment
;
1194 if (!Offset
.isEmpty()) {
1195 if (Offset
.VirtualBase
) {
1196 // Get the virtual base offset offset.
1197 if (Offset
.DerivedClass
== MostDerivedClass
) {
1198 // We can get the offset offset directly from our map.
1199 Adjustment
.Virtual
.Itanium
.VBaseOffsetOffset
=
1200 VBaseOffsetOffsets
.lookup(Offset
.VirtualBase
).getQuantity();
1202 Adjustment
.Virtual
.Itanium
.VBaseOffsetOffset
=
1203 VTables
.getVirtualBaseOffsetOffset(Offset
.DerivedClass
,
1204 Offset
.VirtualBase
).getQuantity();
1208 Adjustment
.NonVirtual
= Offset
.NonVirtualOffset
.getQuantity();
1214 BaseOffset
ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
1215 BaseSubobject Base
, BaseSubobject Derived
) const {
1216 const CXXRecordDecl
*BaseRD
= Base
.getBase();
1217 const CXXRecordDecl
*DerivedRD
= Derived
.getBase();
1219 CXXBasePaths
Paths(/*FindAmbiguities=*/true,
1220 /*RecordPaths=*/true, /*DetectVirtual=*/true);
1222 if (!DerivedRD
->isDerivedFrom(BaseRD
, Paths
))
1223 llvm_unreachable("Class must be derived from the passed in base class!");
1225 // We have to go through all the paths, and see which one leads us to the
1226 // right base subobject.
1227 for (const CXXBasePath
&Path
: Paths
) {
1228 BaseOffset Offset
= ComputeBaseOffset(Context
, DerivedRD
, Path
);
1230 CharUnits OffsetToBaseSubobject
= Offset
.NonVirtualOffset
;
1232 if (Offset
.VirtualBase
) {
1233 // If we have a virtual base class, the non-virtual offset is relative
1234 // to the virtual base class offset.
1235 const ASTRecordLayout
&LayoutClassLayout
=
1236 Context
.getASTRecordLayout(LayoutClass
);
1238 /// Get the virtual base offset, relative to the most derived class
1240 OffsetToBaseSubobject
+=
1241 LayoutClassLayout
.getVBaseClassOffset(Offset
.VirtualBase
);
1243 // Otherwise, the non-virtual offset is relative to the derived class
1245 OffsetToBaseSubobject
+= Derived
.getBaseOffset();
1248 // Check if this path gives us the right base subobject.
1249 if (OffsetToBaseSubobject
== Base
.getBaseOffset()) {
1250 // Since we're going from the base class _to_ the derived class, we'll
1251 // invert the non-virtual offset here.
1252 Offset
.NonVirtualOffset
= -Offset
.NonVirtualOffset
;
1257 return BaseOffset();
1260 ThisAdjustment
ItaniumVTableBuilder::ComputeThisAdjustment(
1261 const CXXMethodDecl
*MD
, CharUnits BaseOffsetInLayoutClass
,
1262 FinalOverriders::OverriderInfo Overrider
) {
1263 // Ignore adjustments for pure virtual member functions.
1264 if (Overrider
.Method
->isPure())
1265 return ThisAdjustment();
1267 BaseSubobject
OverriddenBaseSubobject(MD
->getParent(),
1268 BaseOffsetInLayoutClass
);
1270 BaseSubobject
OverriderBaseSubobject(Overrider
.Method
->getParent(),
1273 // Compute the adjustment offset.
1274 BaseOffset Offset
= ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject
,
1275 OverriderBaseSubobject
);
1276 if (Offset
.isEmpty())
1277 return ThisAdjustment();
1279 ThisAdjustment Adjustment
;
1281 if (Offset
.VirtualBase
) {
1282 // Get the vcall offset map for this virtual base.
1283 VCallOffsetMap
&VCallOffsets
= VCallOffsetsForVBases
[Offset
.VirtualBase
];
1285 if (VCallOffsets
.empty()) {
1286 // We don't have vcall offsets for this virtual base, go ahead and
1288 VCallAndVBaseOffsetBuilder
Builder(
1289 VTables
, MostDerivedClass
, MostDerivedClass
,
1290 /*Overriders=*/nullptr,
1291 BaseSubobject(Offset
.VirtualBase
, CharUnits::Zero()),
1292 /*BaseIsVirtual=*/true,
1293 /*OffsetInLayoutClass=*/
1296 VCallOffsets
= Builder
.getVCallOffsets();
1299 Adjustment
.Virtual
.Itanium
.VCallOffsetOffset
=
1300 VCallOffsets
.getVCallOffsetOffset(MD
).getQuantity();
1303 // Set the non-virtual part of the adjustment.
1304 Adjustment
.NonVirtual
= Offset
.NonVirtualOffset
.getQuantity();
1309 void ItaniumVTableBuilder::AddMethod(const CXXMethodDecl
*MD
,
1310 ReturnAdjustment ReturnAdjustment
) {
1311 if (const CXXDestructorDecl
*DD
= dyn_cast
<CXXDestructorDecl
>(MD
)) {
1312 assert(ReturnAdjustment
.isEmpty() &&
1313 "Destructor can't have return adjustment!");
1315 // Add both the complete destructor and the deleting destructor.
1316 Components
.push_back(VTableComponent::MakeCompleteDtor(DD
));
1317 Components
.push_back(VTableComponent::MakeDeletingDtor(DD
));
1319 // Add the return adjustment if necessary.
1320 if (!ReturnAdjustment
.isEmpty())
1321 VTableThunks
[Components
.size()].Return
= ReturnAdjustment
;
1323 // Add the function.
1324 Components
.push_back(VTableComponent::MakeFunction(MD
));
1328 /// OverridesIndirectMethodInBase - Return whether the given member function
1329 /// overrides any methods in the set of given bases.
1330 /// Unlike OverridesMethodInBase, this checks "overriders of overriders".
1331 /// For example, if we have:
1333 /// struct A { virtual void f(); }
1334 /// struct B : A { virtual void f(); }
1335 /// struct C : B { virtual void f(); }
1337 /// OverridesIndirectMethodInBase will return true if given C::f as the method
1338 /// and { A } as the set of bases.
1339 static bool OverridesIndirectMethodInBases(
1340 const CXXMethodDecl
*MD
,
1341 ItaniumVTableBuilder::PrimaryBasesSetVectorTy
&Bases
) {
1342 if (Bases
.count(MD
->getParent()))
1345 for (const CXXMethodDecl
*OverriddenMD
: MD
->overridden_methods()) {
1346 // Check "indirect overriders".
1347 if (OverridesIndirectMethodInBases(OverriddenMD
, Bases
))
1354 bool ItaniumVTableBuilder::IsOverriderUsed(
1355 const CXXMethodDecl
*Overrider
, CharUnits BaseOffsetInLayoutClass
,
1356 const CXXRecordDecl
*FirstBaseInPrimaryBaseChain
,
1357 CharUnits FirstBaseOffsetInLayoutClass
) const {
1358 // If the base and the first base in the primary base chain have the same
1359 // offsets, then this overrider will be used.
1360 if (BaseOffsetInLayoutClass
== FirstBaseOffsetInLayoutClass
)
1363 // We know now that Base (or a direct or indirect base of it) is a primary
1364 // base in part of the class hierarchy, but not a primary base in the most
1367 // If the overrider is the first base in the primary base chain, we know
1368 // that the overrider will be used.
1369 if (Overrider
->getParent() == FirstBaseInPrimaryBaseChain
)
1372 ItaniumVTableBuilder::PrimaryBasesSetVectorTy PrimaryBases
;
1374 const CXXRecordDecl
*RD
= FirstBaseInPrimaryBaseChain
;
1375 PrimaryBases
.insert(RD
);
1377 // Now traverse the base chain, starting with the first base, until we find
1378 // the base that is no longer a primary base.
1380 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(RD
);
1381 const CXXRecordDecl
*PrimaryBase
= Layout
.getPrimaryBase();
1386 if (Layout
.isPrimaryBaseVirtual()) {
1387 assert(Layout
.getVBaseClassOffset(PrimaryBase
).isZero() &&
1388 "Primary base should always be at offset 0!");
1390 const ASTRecordLayout
&LayoutClassLayout
=
1391 Context
.getASTRecordLayout(LayoutClass
);
1393 // Now check if this is the primary base that is not a primary base in the
1394 // most derived class.
1395 if (LayoutClassLayout
.getVBaseClassOffset(PrimaryBase
) !=
1396 FirstBaseOffsetInLayoutClass
) {
1397 // We found it, stop walking the chain.
1401 assert(Layout
.getBaseClassOffset(PrimaryBase
).isZero() &&
1402 "Primary base should always be at offset 0!");
1405 if (!PrimaryBases
.insert(PrimaryBase
))
1406 llvm_unreachable("Found a duplicate primary base!");
1411 // If the final overrider is an override of one of the primary bases,
1412 // then we know that it will be used.
1413 return OverridesIndirectMethodInBases(Overrider
, PrimaryBases
);
1416 typedef llvm::SmallSetVector
<const CXXRecordDecl
*, 8> BasesSetVectorTy
;
1418 /// FindNearestOverriddenMethod - Given a method, returns the overridden method
1419 /// from the nearest base. Returns null if no method was found.
1420 /// The Bases are expected to be sorted in a base-to-derived order.
1421 static const CXXMethodDecl
*
1422 FindNearestOverriddenMethod(const CXXMethodDecl
*MD
,
1423 BasesSetVectorTy
&Bases
) {
1424 OverriddenMethodsSetTy OverriddenMethods
;
1425 ComputeAllOverriddenMethods(MD
, OverriddenMethods
);
1427 for (const CXXRecordDecl
*PrimaryBase
: llvm::reverse(Bases
)) {
1428 // Now check the overridden methods.
1429 for (const CXXMethodDecl
*OverriddenMD
: OverriddenMethods
) {
1430 // We found our overridden method.
1431 if (OverriddenMD
->getParent() == PrimaryBase
)
1432 return OverriddenMD
;
1439 void ItaniumVTableBuilder::AddMethods(
1440 BaseSubobject Base
, CharUnits BaseOffsetInLayoutClass
,
1441 const CXXRecordDecl
*FirstBaseInPrimaryBaseChain
,
1442 CharUnits FirstBaseOffsetInLayoutClass
,
1443 PrimaryBasesSetVectorTy
&PrimaryBases
) {
1444 // Itanium C++ ABI 2.5.2:
1445 // The order of the virtual function pointers in a virtual table is the
1446 // order of declaration of the corresponding member functions in the class.
1448 // There is an entry for any virtual function declared in a class,
1449 // whether it is a new function or overrides a base class function,
1450 // unless it overrides a function from the primary base, and conversion
1451 // between their return types does not require an adjustment.
1453 const CXXRecordDecl
*RD
= Base
.getBase();
1454 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(RD
);
1456 if (const CXXRecordDecl
*PrimaryBase
= Layout
.getPrimaryBase()) {
1457 CharUnits PrimaryBaseOffset
;
1458 CharUnits PrimaryBaseOffsetInLayoutClass
;
1459 if (Layout
.isPrimaryBaseVirtual()) {
1460 assert(Layout
.getVBaseClassOffset(PrimaryBase
).isZero() &&
1461 "Primary vbase should have a zero offset!");
1463 const ASTRecordLayout
&MostDerivedClassLayout
=
1464 Context
.getASTRecordLayout(MostDerivedClass
);
1467 MostDerivedClassLayout
.getVBaseClassOffset(PrimaryBase
);
1469 const ASTRecordLayout
&LayoutClassLayout
=
1470 Context
.getASTRecordLayout(LayoutClass
);
1472 PrimaryBaseOffsetInLayoutClass
=
1473 LayoutClassLayout
.getVBaseClassOffset(PrimaryBase
);
1475 assert(Layout
.getBaseClassOffset(PrimaryBase
).isZero() &&
1476 "Primary base should have a zero offset!");
1478 PrimaryBaseOffset
= Base
.getBaseOffset();
1479 PrimaryBaseOffsetInLayoutClass
= BaseOffsetInLayoutClass
;
1482 AddMethods(BaseSubobject(PrimaryBase
, PrimaryBaseOffset
),
1483 PrimaryBaseOffsetInLayoutClass
, FirstBaseInPrimaryBaseChain
,
1484 FirstBaseOffsetInLayoutClass
, PrimaryBases
);
1486 if (!PrimaryBases
.insert(PrimaryBase
))
1487 llvm_unreachable("Found a duplicate primary base!");
1490 typedef llvm::SmallVector
<const CXXMethodDecl
*, 8> NewVirtualFunctionsTy
;
1491 NewVirtualFunctionsTy NewVirtualFunctions
;
1493 llvm::SmallVector
<const CXXMethodDecl
*, 4> NewImplicitVirtualFunctions
;
1495 // Now go through all virtual member functions and add them.
1496 for (const auto *MD
: RD
->methods()) {
1497 if (!ItaniumVTableContext::hasVtableSlot(MD
))
1499 MD
= MD
->getCanonicalDecl();
1501 // Get the final overrider.
1502 FinalOverriders::OverriderInfo Overrider
=
1503 Overriders
.getOverrider(MD
, Base
.getBaseOffset());
1505 // Check if this virtual member function overrides a method in a primary
1506 // base. If this is the case, and the return type doesn't require adjustment
1507 // then we can just use the member function from the primary base.
1508 if (const CXXMethodDecl
*OverriddenMD
=
1509 FindNearestOverriddenMethod(MD
, PrimaryBases
)) {
1510 if (ComputeReturnAdjustmentBaseOffset(Context
, MD
,
1511 OverriddenMD
).isEmpty()) {
1512 // Replace the method info of the overridden method with our own
1514 assert(MethodInfoMap
.count(OverriddenMD
) &&
1515 "Did not find the overridden method!");
1516 MethodInfo
&OverriddenMethodInfo
= MethodInfoMap
[OverriddenMD
];
1518 MethodInfo
MethodInfo(Base
.getBaseOffset(), BaseOffsetInLayoutClass
,
1519 OverriddenMethodInfo
.VTableIndex
);
1521 assert(!MethodInfoMap
.count(MD
) &&
1522 "Should not have method info for this method yet!");
1524 MethodInfoMap
.insert(std::make_pair(MD
, MethodInfo
));
1525 MethodInfoMap
.erase(OverriddenMD
);
1527 // If the overridden method exists in a virtual base class or a direct
1528 // or indirect base class of a virtual base class, we need to emit a
1529 // thunk if we ever have a class hierarchy where the base class is not
1530 // a primary base in the complete object.
1531 if (!isBuildingConstructorVTable() && OverriddenMD
!= MD
) {
1532 // Compute the this adjustment.
1533 ThisAdjustment ThisAdjustment
=
1534 ComputeThisAdjustment(OverriddenMD
, BaseOffsetInLayoutClass
,
1537 if (ThisAdjustment
.Virtual
.Itanium
.VCallOffsetOffset
&&
1538 Overrider
.Method
->getParent() == MostDerivedClass
) {
1540 // There's no return adjustment from OverriddenMD and MD,
1541 // but that doesn't mean there isn't one between MD and
1542 // the final overrider.
1543 BaseOffset ReturnAdjustmentOffset
=
1544 ComputeReturnAdjustmentBaseOffset(Context
, Overrider
.Method
, MD
);
1545 ReturnAdjustment ReturnAdjustment
=
1546 ComputeReturnAdjustment(ReturnAdjustmentOffset
);
1548 // This is a virtual thunk for the most derived class, add it.
1549 AddThunk(Overrider
.Method
,
1550 ThunkInfo(ThisAdjustment
, ReturnAdjustment
));
1558 if (MD
->isImplicit())
1559 NewImplicitVirtualFunctions
.push_back(MD
);
1561 NewVirtualFunctions
.push_back(MD
);
1565 NewImplicitVirtualFunctions
.begin(), NewImplicitVirtualFunctions
.end(),
1566 [](const CXXMethodDecl
*A
, const CXXMethodDecl
*B
) {
1569 if (A
->isCopyAssignmentOperator() != B
->isCopyAssignmentOperator())
1570 return A
->isCopyAssignmentOperator();
1571 if (A
->isMoveAssignmentOperator() != B
->isMoveAssignmentOperator())
1572 return A
->isMoveAssignmentOperator();
1573 if (isa
<CXXDestructorDecl
>(A
) != isa
<CXXDestructorDecl
>(B
))
1574 return isa
<CXXDestructorDecl
>(A
);
1575 assert(A
->getOverloadedOperator() == OO_EqualEqual
&&
1576 B
->getOverloadedOperator() == OO_EqualEqual
&&
1577 "unexpected or duplicate implicit virtual function");
1578 // We rely on Sema to have declared the operator== members in the
1579 // same order as the corresponding operator<=> members.
1582 NewVirtualFunctions
.append(NewImplicitVirtualFunctions
.begin(),
1583 NewImplicitVirtualFunctions
.end());
1585 for (const CXXMethodDecl
*MD
: NewVirtualFunctions
) {
1586 // Get the final overrider.
1587 FinalOverriders::OverriderInfo Overrider
=
1588 Overriders
.getOverrider(MD
, Base
.getBaseOffset());
1590 // Insert the method info for this method.
1591 MethodInfo
MethodInfo(Base
.getBaseOffset(), BaseOffsetInLayoutClass
,
1594 assert(!MethodInfoMap
.count(MD
) &&
1595 "Should not have method info for this method yet!");
1596 MethodInfoMap
.insert(std::make_pair(MD
, MethodInfo
));
1598 // Check if this overrider is going to be used.
1599 const CXXMethodDecl
*OverriderMD
= Overrider
.Method
;
1600 if (!IsOverriderUsed(OverriderMD
, BaseOffsetInLayoutClass
,
1601 FirstBaseInPrimaryBaseChain
,
1602 FirstBaseOffsetInLayoutClass
)) {
1603 Components
.push_back(VTableComponent::MakeUnusedFunction(OverriderMD
));
1607 // Check if this overrider needs a return adjustment.
1608 // We don't want to do this for pure virtual member functions.
1609 BaseOffset ReturnAdjustmentOffset
;
1610 if (!OverriderMD
->isPure()) {
1611 ReturnAdjustmentOffset
=
1612 ComputeReturnAdjustmentBaseOffset(Context
, OverriderMD
, MD
);
1615 ReturnAdjustment ReturnAdjustment
=
1616 ComputeReturnAdjustment(ReturnAdjustmentOffset
);
1618 AddMethod(Overrider
.Method
, ReturnAdjustment
);
1622 void ItaniumVTableBuilder::LayoutVTable() {
1623 LayoutPrimaryAndSecondaryVTables(BaseSubobject(MostDerivedClass
,
1625 /*BaseIsMorallyVirtual=*/false,
1626 MostDerivedClassIsVirtual
,
1627 MostDerivedClassOffset
);
1629 VisitedVirtualBasesSetTy VBases
;
1631 // Determine the primary virtual bases.
1632 DeterminePrimaryVirtualBases(MostDerivedClass
, MostDerivedClassOffset
,
1636 LayoutVTablesForVirtualBases(MostDerivedClass
, VBases
);
1638 // -fapple-kext adds an extra entry at end of vtbl.
1639 bool IsAppleKext
= Context
.getLangOpts().AppleKext
;
1641 Components
.push_back(VTableComponent::MakeVCallOffset(CharUnits::Zero()));
1644 void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
1645 BaseSubobject Base
, bool BaseIsMorallyVirtual
,
1646 bool BaseIsVirtualInLayoutClass
, CharUnits OffsetInLayoutClass
) {
1647 assert(Base
.getBase()->isDynamicClass() && "class does not have a vtable!");
1649 unsigned VTableIndex
= Components
.size();
1650 VTableIndices
.push_back(VTableIndex
);
1652 // Add vcall and vbase offsets for this vtable.
1653 VCallAndVBaseOffsetBuilder
Builder(
1654 VTables
, MostDerivedClass
, LayoutClass
, &Overriders
, Base
,
1655 BaseIsVirtualInLayoutClass
, OffsetInLayoutClass
);
1656 Components
.append(Builder
.components_begin(), Builder
.components_end());
1658 // Check if we need to add these vcall offsets.
1659 if (BaseIsVirtualInLayoutClass
&& !Builder
.getVCallOffsets().empty()) {
1660 VCallOffsetMap
&VCallOffsets
= VCallOffsetsForVBases
[Base
.getBase()];
1662 if (VCallOffsets
.empty())
1663 VCallOffsets
= Builder
.getVCallOffsets();
1666 // If we're laying out the most derived class we want to keep track of the
1667 // virtual base class offset offsets.
1668 if (Base
.getBase() == MostDerivedClass
)
1669 VBaseOffsetOffsets
= Builder
.getVBaseOffsetOffsets();
1671 // Add the offset to top.
1672 CharUnits OffsetToTop
= MostDerivedClassOffset
- OffsetInLayoutClass
;
1673 Components
.push_back(VTableComponent::MakeOffsetToTop(OffsetToTop
));
1675 // Next, add the RTTI.
1676 if (!Context
.getLangOpts().OmitVTableRTTI
)
1677 Components
.push_back(VTableComponent::MakeRTTI(MostDerivedClass
));
1679 uint64_t AddressPoint
= Components
.size();
1681 // Now go through all virtual member functions and add them.
1682 PrimaryBasesSetVectorTy PrimaryBases
;
1683 AddMethods(Base
, OffsetInLayoutClass
,
1684 Base
.getBase(), OffsetInLayoutClass
,
1687 const CXXRecordDecl
*RD
= Base
.getBase();
1688 if (RD
== MostDerivedClass
) {
1689 assert(MethodVTableIndices
.empty());
1690 for (const auto &I
: MethodInfoMap
) {
1691 const CXXMethodDecl
*MD
= I
.first
;
1692 const MethodInfo
&MI
= I
.second
;
1693 if (const CXXDestructorDecl
*DD
= dyn_cast
<CXXDestructorDecl
>(MD
)) {
1694 MethodVTableIndices
[GlobalDecl(DD
, Dtor_Complete
)]
1695 = MI
.VTableIndex
- AddressPoint
;
1696 MethodVTableIndices
[GlobalDecl(DD
, Dtor_Deleting
)]
1697 = MI
.VTableIndex
+ 1 - AddressPoint
;
1699 MethodVTableIndices
[MD
] = MI
.VTableIndex
- AddressPoint
;
1704 // Compute 'this' pointer adjustments.
1705 ComputeThisAdjustments();
1707 // Add all address points.
1709 AddressPoints
.insert(
1710 std::make_pair(BaseSubobject(RD
, OffsetInLayoutClass
),
1711 VTableLayout::AddressPointLocation
{
1712 unsigned(VTableIndices
.size() - 1),
1713 unsigned(AddressPoint
- VTableIndex
)}));
1715 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(RD
);
1716 const CXXRecordDecl
*PrimaryBase
= Layout
.getPrimaryBase();
1721 if (Layout
.isPrimaryBaseVirtual()) {
1722 // Check if this virtual primary base is a primary base in the layout
1723 // class. If it's not, we don't want to add it.
1724 const ASTRecordLayout
&LayoutClassLayout
=
1725 Context
.getASTRecordLayout(LayoutClass
);
1727 if (LayoutClassLayout
.getVBaseClassOffset(PrimaryBase
) !=
1728 OffsetInLayoutClass
) {
1729 // We don't want to add this class (or any of its primary bases).
1737 // Layout secondary vtables.
1738 LayoutSecondaryVTables(Base
, BaseIsMorallyVirtual
, OffsetInLayoutClass
);
1742 ItaniumVTableBuilder::LayoutSecondaryVTables(BaseSubobject Base
,
1743 bool BaseIsMorallyVirtual
,
1744 CharUnits OffsetInLayoutClass
) {
1745 // Itanium C++ ABI 2.5.2:
1746 // Following the primary virtual table of a derived class are secondary
1747 // virtual tables for each of its proper base classes, except any primary
1748 // base(s) with which it shares its primary virtual table.
1750 const CXXRecordDecl
*RD
= Base
.getBase();
1751 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(RD
);
1752 const CXXRecordDecl
*PrimaryBase
= Layout
.getPrimaryBase();
1754 for (const auto &B
: RD
->bases()) {
1755 // Ignore virtual bases, we'll emit them later.
1759 const CXXRecordDecl
*BaseDecl
= B
.getType()->getAsCXXRecordDecl();
1761 // Ignore bases that don't have a vtable.
1762 if (!BaseDecl
->isDynamicClass())
1765 if (isBuildingConstructorVTable()) {
1766 // Itanium C++ ABI 2.6.4:
1767 // Some of the base class subobjects may not need construction virtual
1768 // tables, which will therefore not be present in the construction
1769 // virtual table group, even though the subobject virtual tables are
1770 // present in the main virtual table group for the complete object.
1771 if (!BaseIsMorallyVirtual
&& !BaseDecl
->getNumVBases())
1775 // Get the base offset of this base.
1776 CharUnits RelativeBaseOffset
= Layout
.getBaseClassOffset(BaseDecl
);
1777 CharUnits BaseOffset
= Base
.getBaseOffset() + RelativeBaseOffset
;
1779 CharUnits BaseOffsetInLayoutClass
=
1780 OffsetInLayoutClass
+ RelativeBaseOffset
;
1782 // Don't emit a secondary vtable for a primary base. We might however want
1783 // to emit secondary vtables for other bases of this base.
1784 if (BaseDecl
== PrimaryBase
) {
1785 LayoutSecondaryVTables(BaseSubobject(BaseDecl
, BaseOffset
),
1786 BaseIsMorallyVirtual
, BaseOffsetInLayoutClass
);
1790 // Layout the primary vtable (and any secondary vtables) for this base.
1791 LayoutPrimaryAndSecondaryVTables(
1792 BaseSubobject(BaseDecl
, BaseOffset
),
1793 BaseIsMorallyVirtual
,
1794 /*BaseIsVirtualInLayoutClass=*/false,
1795 BaseOffsetInLayoutClass
);
1799 void ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
1800 const CXXRecordDecl
*RD
, CharUnits OffsetInLayoutClass
,
1801 VisitedVirtualBasesSetTy
&VBases
) {
1802 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(RD
);
1804 // Check if this base has a primary base.
1805 if (const CXXRecordDecl
*PrimaryBase
= Layout
.getPrimaryBase()) {
1807 // Check if it's virtual.
1808 if (Layout
.isPrimaryBaseVirtual()) {
1809 bool IsPrimaryVirtualBase
= true;
1811 if (isBuildingConstructorVTable()) {
1812 // Check if the base is actually a primary base in the class we use for
1814 const ASTRecordLayout
&LayoutClassLayout
=
1815 Context
.getASTRecordLayout(LayoutClass
);
1817 CharUnits PrimaryBaseOffsetInLayoutClass
=
1818 LayoutClassLayout
.getVBaseClassOffset(PrimaryBase
);
1820 // We know that the base is not a primary base in the layout class if
1821 // the base offsets are different.
1822 if (PrimaryBaseOffsetInLayoutClass
!= OffsetInLayoutClass
)
1823 IsPrimaryVirtualBase
= false;
1826 if (IsPrimaryVirtualBase
)
1827 PrimaryVirtualBases
.insert(PrimaryBase
);
1831 // Traverse bases, looking for more primary virtual bases.
1832 for (const auto &B
: RD
->bases()) {
1833 const CXXRecordDecl
*BaseDecl
= B
.getType()->getAsCXXRecordDecl();
1835 CharUnits BaseOffsetInLayoutClass
;
1837 if (B
.isVirtual()) {
1838 if (!VBases
.insert(BaseDecl
).second
)
1841 const ASTRecordLayout
&LayoutClassLayout
=
1842 Context
.getASTRecordLayout(LayoutClass
);
1844 BaseOffsetInLayoutClass
=
1845 LayoutClassLayout
.getVBaseClassOffset(BaseDecl
);
1847 BaseOffsetInLayoutClass
=
1848 OffsetInLayoutClass
+ Layout
.getBaseClassOffset(BaseDecl
);
1851 DeterminePrimaryVirtualBases(BaseDecl
, BaseOffsetInLayoutClass
, VBases
);
1855 void ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
1856 const CXXRecordDecl
*RD
, VisitedVirtualBasesSetTy
&VBases
) {
1857 // Itanium C++ ABI 2.5.2:
1858 // Then come the virtual base virtual tables, also in inheritance graph
1859 // order, and again excluding primary bases (which share virtual tables with
1860 // the classes for which they are primary).
1861 for (const auto &B
: RD
->bases()) {
1862 const CXXRecordDecl
*BaseDecl
= B
.getType()->getAsCXXRecordDecl();
1864 // Check if this base needs a vtable. (If it's virtual, not a primary base
1865 // of some other class, and we haven't visited it before).
1866 if (B
.isVirtual() && BaseDecl
->isDynamicClass() &&
1867 !PrimaryVirtualBases
.count(BaseDecl
) &&
1868 VBases
.insert(BaseDecl
).second
) {
1869 const ASTRecordLayout
&MostDerivedClassLayout
=
1870 Context
.getASTRecordLayout(MostDerivedClass
);
1871 CharUnits BaseOffset
=
1872 MostDerivedClassLayout
.getVBaseClassOffset(BaseDecl
);
1874 const ASTRecordLayout
&LayoutClassLayout
=
1875 Context
.getASTRecordLayout(LayoutClass
);
1876 CharUnits BaseOffsetInLayoutClass
=
1877 LayoutClassLayout
.getVBaseClassOffset(BaseDecl
);
1879 LayoutPrimaryAndSecondaryVTables(
1880 BaseSubobject(BaseDecl
, BaseOffset
),
1881 /*BaseIsMorallyVirtual=*/true,
1882 /*BaseIsVirtualInLayoutClass=*/true,
1883 BaseOffsetInLayoutClass
);
1886 // We only need to check the base for virtual base vtables if it actually
1887 // has virtual bases.
1888 if (BaseDecl
->getNumVBases())
1889 LayoutVTablesForVirtualBases(BaseDecl
, VBases
);
1893 /// dumpLayout - Dump the vtable layout.
1894 void ItaniumVTableBuilder::dumpLayout(raw_ostream
&Out
) {
1895 // FIXME: write more tests that actually use the dumpLayout output to prevent
1896 // ItaniumVTableBuilder regressions.
1898 if (isBuildingConstructorVTable()) {
1899 Out
<< "Construction vtable for ('";
1900 MostDerivedClass
->printQualifiedName(Out
);
1902 Out
<< MostDerivedClassOffset
.getQuantity() << ") in '";
1903 LayoutClass
->printQualifiedName(Out
);
1905 Out
<< "Vtable for '";
1906 MostDerivedClass
->printQualifiedName(Out
);
1908 Out
<< "' (" << Components
.size() << " entries).\n";
1910 // Iterate through the address points and insert them into a new map where
1911 // they are keyed by the index and not the base object.
1912 // Since an address point can be shared by multiple subobjects, we use an
1914 std::multimap
<uint64_t, BaseSubobject
> AddressPointsByIndex
;
1915 for (const auto &AP
: AddressPoints
) {
1916 const BaseSubobject
&Base
= AP
.first
;
1918 VTableIndices
[AP
.second
.VTableIndex
] + AP
.second
.AddressPointIndex
;
1920 AddressPointsByIndex
.insert(std::make_pair(Index
, Base
));
1923 for (unsigned I
= 0, E
= Components
.size(); I
!= E
; ++I
) {
1926 Out
<< llvm::format("%4d | ", I
);
1928 const VTableComponent
&Component
= Components
[I
];
1930 // Dump the component.
1931 switch (Component
.getKind()) {
1933 case VTableComponent::CK_VCallOffset
:
1934 Out
<< "vcall_offset ("
1935 << Component
.getVCallOffset().getQuantity()
1939 case VTableComponent::CK_VBaseOffset
:
1940 Out
<< "vbase_offset ("
1941 << Component
.getVBaseOffset().getQuantity()
1945 case VTableComponent::CK_OffsetToTop
:
1946 Out
<< "offset_to_top ("
1947 << Component
.getOffsetToTop().getQuantity()
1951 case VTableComponent::CK_RTTI
:
1952 Component
.getRTTIDecl()->printQualifiedName(Out
);
1956 case VTableComponent::CK_FunctionPointer
: {
1957 const CXXMethodDecl
*MD
= Component
.getFunctionDecl();
1960 PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual
,
1966 if (MD
->isDeleted())
1967 Out
<< " [deleted]";
1969 ThunkInfo Thunk
= VTableThunks
.lookup(I
);
1970 if (!Thunk
.isEmpty()) {
1971 // If this function pointer has a return adjustment, dump it.
1972 if (!Thunk
.Return
.isEmpty()) {
1973 Out
<< "\n [return adjustment: ";
1974 Out
<< Thunk
.Return
.NonVirtual
<< " non-virtual";
1976 if (Thunk
.Return
.Virtual
.Itanium
.VBaseOffsetOffset
) {
1977 Out
<< ", " << Thunk
.Return
.Virtual
.Itanium
.VBaseOffsetOffset
;
1978 Out
<< " vbase offset offset";
1984 // If this function pointer has a 'this' pointer adjustment, dump it.
1985 if (!Thunk
.This
.isEmpty()) {
1986 Out
<< "\n [this adjustment: ";
1987 Out
<< Thunk
.This
.NonVirtual
<< " non-virtual";
1989 if (Thunk
.This
.Virtual
.Itanium
.VCallOffsetOffset
) {
1990 Out
<< ", " << Thunk
.This
.Virtual
.Itanium
.VCallOffsetOffset
;
1991 Out
<< " vcall offset offset";
2001 case VTableComponent::CK_CompleteDtorPointer
:
2002 case VTableComponent::CK_DeletingDtorPointer
: {
2004 Component
.getKind() == VTableComponent::CK_CompleteDtorPointer
;
2006 const CXXDestructorDecl
*DD
= Component
.getDestructorDecl();
2008 DD
->printQualifiedName(Out
);
2010 Out
<< "() [complete]";
2012 Out
<< "() [deleting]";
2017 ThunkInfo Thunk
= VTableThunks
.lookup(I
);
2018 if (!Thunk
.isEmpty()) {
2019 // If this destructor has a 'this' pointer adjustment, dump it.
2020 if (!Thunk
.This
.isEmpty()) {
2021 Out
<< "\n [this adjustment: ";
2022 Out
<< Thunk
.This
.NonVirtual
<< " non-virtual";
2024 if (Thunk
.This
.Virtual
.Itanium
.VCallOffsetOffset
) {
2025 Out
<< ", " << Thunk
.This
.Virtual
.Itanium
.VCallOffsetOffset
;
2026 Out
<< " vcall offset offset";
2036 case VTableComponent::CK_UnusedFunctionPointer
: {
2037 const CXXMethodDecl
*MD
= Component
.getUnusedFunctionDecl();
2040 PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual
,
2042 Out
<< "[unused] " << Str
;
2051 // Dump the next address point.
2052 uint64_t NextIndex
= Index
+ 1;
2053 if (AddressPointsByIndex
.count(NextIndex
)) {
2054 if (AddressPointsByIndex
.count(NextIndex
) == 1) {
2055 const BaseSubobject
&Base
=
2056 AddressPointsByIndex
.find(NextIndex
)->second
;
2059 Base
.getBase()->printQualifiedName(Out
);
2060 Out
<< ", " << Base
.getBaseOffset().getQuantity();
2061 Out
<< ") vtable address --\n";
2063 CharUnits BaseOffset
=
2064 AddressPointsByIndex
.lower_bound(NextIndex
)->second
.getBaseOffset();
2066 // We store the class names in a set to get a stable order.
2067 std::set
<std::string
> ClassNames
;
2068 for (const auto &I
:
2069 llvm::make_range(AddressPointsByIndex
.equal_range(NextIndex
))) {
2070 assert(I
.second
.getBaseOffset() == BaseOffset
&&
2071 "Invalid base offset!");
2072 const CXXRecordDecl
*RD
= I
.second
.getBase();
2073 ClassNames
.insert(RD
->getQualifiedNameAsString());
2076 for (const std::string
&Name
: ClassNames
) {
2077 Out
<< " -- (" << Name
;
2078 Out
<< ", " << BaseOffset
.getQuantity() << ") vtable address --\n";
2086 if (isBuildingConstructorVTable())
2089 if (MostDerivedClass
->getNumVBases()) {
2090 // We store the virtual base class names and their offsets in a map to get
2093 std::map
<std::string
, CharUnits
> ClassNamesAndOffsets
;
2094 for (const auto &I
: VBaseOffsetOffsets
) {
2095 std::string ClassName
= I
.first
->getQualifiedNameAsString();
2096 CharUnits OffsetOffset
= I
.second
;
2097 ClassNamesAndOffsets
.insert(std::make_pair(ClassName
, OffsetOffset
));
2100 Out
<< "Virtual base offset offsets for '";
2101 MostDerivedClass
->printQualifiedName(Out
);
2103 Out
<< ClassNamesAndOffsets
.size();
2104 Out
<< (ClassNamesAndOffsets
.size() == 1 ? " entry" : " entries") << ").\n";
2106 for (const auto &I
: ClassNamesAndOffsets
)
2107 Out
<< " " << I
.first
<< " | " << I
.second
.getQuantity() << '\n';
2112 if (!Thunks
.empty()) {
2113 // We store the method names in a map to get a stable order.
2114 std::map
<std::string
, const CXXMethodDecl
*> MethodNamesAndDecls
;
2116 for (const auto &I
: Thunks
) {
2117 const CXXMethodDecl
*MD
= I
.first
;
2118 std::string MethodName
=
2119 PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual
,
2122 MethodNamesAndDecls
.insert(std::make_pair(MethodName
, MD
));
2125 for (const auto &I
: MethodNamesAndDecls
) {
2126 const std::string
&MethodName
= I
.first
;
2127 const CXXMethodDecl
*MD
= I
.second
;
2129 ThunkInfoVectorTy ThunksVector
= Thunks
[MD
];
2130 llvm::sort(ThunksVector
, [](const ThunkInfo
&LHS
, const ThunkInfo
&RHS
) {
2131 assert(LHS
.Method
== nullptr && RHS
.Method
== nullptr);
2132 return std::tie(LHS
.This
, LHS
.Return
) < std::tie(RHS
.This
, RHS
.Return
);
2135 Out
<< "Thunks for '" << MethodName
<< "' (" << ThunksVector
.size();
2136 Out
<< (ThunksVector
.size() == 1 ? " entry" : " entries") << ").\n";
2138 for (unsigned I
= 0, E
= ThunksVector
.size(); I
!= E
; ++I
) {
2139 const ThunkInfo
&Thunk
= ThunksVector
[I
];
2141 Out
<< llvm::format("%4d | ", I
);
2143 // If this function pointer has a return pointer adjustment, dump it.
2144 if (!Thunk
.Return
.isEmpty()) {
2145 Out
<< "return adjustment: " << Thunk
.Return
.NonVirtual
;
2146 Out
<< " non-virtual";
2147 if (Thunk
.Return
.Virtual
.Itanium
.VBaseOffsetOffset
) {
2148 Out
<< ", " << Thunk
.Return
.Virtual
.Itanium
.VBaseOffsetOffset
;
2149 Out
<< " vbase offset offset";
2152 if (!Thunk
.This
.isEmpty())
2156 // If this function pointer has a 'this' pointer adjustment, dump it.
2157 if (!Thunk
.This
.isEmpty()) {
2158 Out
<< "this adjustment: ";
2159 Out
<< Thunk
.This
.NonVirtual
<< " non-virtual";
2161 if (Thunk
.This
.Virtual
.Itanium
.VCallOffsetOffset
) {
2162 Out
<< ", " << Thunk
.This
.Virtual
.Itanium
.VCallOffsetOffset
;
2163 Out
<< " vcall offset offset";
2174 // Compute the vtable indices for all the member functions.
2175 // Store them in a map keyed by the index so we'll get a sorted table.
2176 std::map
<uint64_t, std::string
> IndicesMap
;
2178 for (const auto *MD
: MostDerivedClass
->methods()) {
2179 // We only want virtual member functions.
2180 if (!ItaniumVTableContext::hasVtableSlot(MD
))
2182 MD
= MD
->getCanonicalDecl();
2184 std::string MethodName
=
2185 PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual
,
2188 if (const CXXDestructorDecl
*DD
= dyn_cast
<CXXDestructorDecl
>(MD
)) {
2189 GlobalDecl
GD(DD
, Dtor_Complete
);
2190 assert(MethodVTableIndices
.count(GD
));
2191 uint64_t VTableIndex
= MethodVTableIndices
[GD
];
2192 IndicesMap
[VTableIndex
] = MethodName
+ " [complete]";
2193 IndicesMap
[VTableIndex
+ 1] = MethodName
+ " [deleting]";
2195 assert(MethodVTableIndices
.count(MD
));
2196 IndicesMap
[MethodVTableIndices
[MD
]] = MethodName
;
2200 // Print the vtable indices for all the member functions.
2201 if (!IndicesMap
.empty()) {
2202 Out
<< "VTable indices for '";
2203 MostDerivedClass
->printQualifiedName(Out
);
2204 Out
<< "' (" << IndicesMap
.size() << " entries).\n";
2206 for (const auto &I
: IndicesMap
) {
2207 uint64_t VTableIndex
= I
.first
;
2208 const std::string
&MethodName
= I
.second
;
2210 Out
<< llvm::format("%4" PRIu64
" | ", VTableIndex
) << MethodName
2219 static VTableLayout::AddressPointsIndexMapTy
2220 MakeAddressPointIndices(const VTableLayout::AddressPointsMapTy
&addressPoints
,
2221 unsigned numVTables
) {
2222 VTableLayout::AddressPointsIndexMapTy
indexMap(numVTables
);
2224 for (auto it
= addressPoints
.begin(); it
!= addressPoints
.end(); ++it
) {
2225 const auto &addressPointLoc
= it
->second
;
2226 unsigned vtableIndex
= addressPointLoc
.VTableIndex
;
2227 unsigned addressPoint
= addressPointLoc
.AddressPointIndex
;
2228 if (indexMap
[vtableIndex
]) {
2229 // Multiple BaseSubobjects can map to the same AddressPointLocation, but
2230 // every vtable index should have a unique address point.
2231 assert(indexMap
[vtableIndex
] == addressPoint
&&
2232 "Every vtable index should have a unique address point. Found a "
2233 "vtable that has two different address points.");
2235 indexMap
[vtableIndex
] = addressPoint
;
2239 // Note that by this point, not all the address may be initialized if the
2240 // AddressPoints map is empty. This is ok if the map isn't needed. See
2241 // MicrosoftVTableContext::computeVTableRelatedInformation() which uses an
2246 VTableLayout::VTableLayout(ArrayRef
<size_t> VTableIndices
,
2247 ArrayRef
<VTableComponent
> VTableComponents
,
2248 ArrayRef
<VTableThunkTy
> VTableThunks
,
2249 const AddressPointsMapTy
&AddressPoints
)
2250 : VTableComponents(VTableComponents
), VTableThunks(VTableThunks
),
2251 AddressPoints(AddressPoints
), AddressPointIndices(MakeAddressPointIndices(
2252 AddressPoints
, VTableIndices
.size())) {
2253 if (VTableIndices
.size() <= 1)
2254 assert(VTableIndices
.size() == 1 && VTableIndices
[0] == 0);
2256 this->VTableIndices
= OwningArrayRef
<size_t>(VTableIndices
);
2258 llvm::sort(this->VTableThunks
, [](const VTableLayout::VTableThunkTy
&LHS
,
2259 const VTableLayout::VTableThunkTy
&RHS
) {
2260 assert((LHS
.first
!= RHS
.first
|| LHS
.second
== RHS
.second
) &&
2261 "Different thunks should have unique indices!");
2262 return LHS
.first
< RHS
.first
;
2266 VTableLayout::~VTableLayout() { }
2268 bool VTableContextBase::hasVtableSlot(const CXXMethodDecl
*MD
) {
2269 return MD
->isVirtual() && !MD
->isImmediateFunction();
2272 ItaniumVTableContext::ItaniumVTableContext(
2273 ASTContext
&Context
, VTableComponentLayout ComponentLayout
)
2274 : VTableContextBase(/*MS=*/false), ComponentLayout(ComponentLayout
) {}
2276 ItaniumVTableContext::~ItaniumVTableContext() {}
2278 uint64_t ItaniumVTableContext::getMethodVTableIndex(GlobalDecl GD
) {
2279 GD
= GD
.getCanonicalDecl();
2280 MethodVTableIndicesTy::iterator I
= MethodVTableIndices
.find(GD
);
2281 if (I
!= MethodVTableIndices
.end())
2284 const CXXRecordDecl
*RD
= cast
<CXXMethodDecl
>(GD
.getDecl())->getParent();
2286 computeVTableRelatedInformation(RD
);
2288 I
= MethodVTableIndices
.find(GD
);
2289 assert(I
!= MethodVTableIndices
.end() && "Did not find index!");
2294 ItaniumVTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl
*RD
,
2295 const CXXRecordDecl
*VBase
) {
2296 ClassPairTy
ClassPair(RD
, VBase
);
2298 VirtualBaseClassOffsetOffsetsMapTy::iterator I
=
2299 VirtualBaseClassOffsetOffsets
.find(ClassPair
);
2300 if (I
!= VirtualBaseClassOffsetOffsets
.end())
2303 VCallAndVBaseOffsetBuilder
Builder(*this, RD
, RD
, /*Overriders=*/nullptr,
2304 BaseSubobject(RD
, CharUnits::Zero()),
2305 /*BaseIsVirtual=*/false,
2306 /*OffsetInLayoutClass=*/CharUnits::Zero());
2308 for (const auto &I
: Builder
.getVBaseOffsetOffsets()) {
2309 // Insert all types.
2310 ClassPairTy
ClassPair(RD
, I
.first
);
2312 VirtualBaseClassOffsetOffsets
.insert(std::make_pair(ClassPair
, I
.second
));
2315 I
= VirtualBaseClassOffsetOffsets
.find(ClassPair
);
2316 assert(I
!= VirtualBaseClassOffsetOffsets
.end() && "Did not find index!");
2321 static std::unique_ptr
<VTableLayout
>
2322 CreateVTableLayout(const ItaniumVTableBuilder
&Builder
) {
2323 SmallVector
<VTableLayout::VTableThunkTy
, 1>
2324 VTableThunks(Builder
.vtable_thunks_begin(), Builder
.vtable_thunks_end());
2326 return std::make_unique
<VTableLayout
>(
2327 Builder
.VTableIndices
, Builder
.vtable_components(), VTableThunks
,
2328 Builder
.getAddressPoints());
2332 ItaniumVTableContext::computeVTableRelatedInformation(const CXXRecordDecl
*RD
) {
2333 std::unique_ptr
<const VTableLayout
> &Entry
= VTableLayouts
[RD
];
2335 // Check if we've computed this information before.
2339 ItaniumVTableBuilder
Builder(*this, RD
, CharUnits::Zero(),
2340 /*MostDerivedClassIsVirtual=*/false, RD
);
2341 Entry
= CreateVTableLayout(Builder
);
2343 MethodVTableIndices
.insert(Builder
.vtable_indices_begin(),
2344 Builder
.vtable_indices_end());
2346 // Add the known thunks.
2347 Thunks
.insert(Builder
.thunks_begin(), Builder
.thunks_end());
2349 // If we don't have the vbase information for this class, insert it.
2350 // getVirtualBaseOffsetOffset will compute it separately without computing
2351 // the rest of the vtable related information.
2352 if (!RD
->getNumVBases())
2355 const CXXRecordDecl
*VBase
=
2356 RD
->vbases_begin()->getType()->getAsCXXRecordDecl();
2358 if (VirtualBaseClassOffsetOffsets
.count(std::make_pair(RD
, VBase
)))
2361 for (const auto &I
: Builder
.getVBaseOffsetOffsets()) {
2362 // Insert all types.
2363 ClassPairTy
ClassPair(RD
, I
.first
);
2365 VirtualBaseClassOffsetOffsets
.insert(std::make_pair(ClassPair
, I
.second
));
2369 std::unique_ptr
<VTableLayout
>
2370 ItaniumVTableContext::createConstructionVTableLayout(
2371 const CXXRecordDecl
*MostDerivedClass
, CharUnits MostDerivedClassOffset
,
2372 bool MostDerivedClassIsVirtual
, const CXXRecordDecl
*LayoutClass
) {
2373 ItaniumVTableBuilder
Builder(*this, MostDerivedClass
, MostDerivedClassOffset
,
2374 MostDerivedClassIsVirtual
, LayoutClass
);
2375 return CreateVTableLayout(Builder
);
2380 // Vtables in the Microsoft ABI are different from the Itanium ABI.
2382 // The main differences are:
2383 // 1. Separate vftable and vbtable.
2385 // 2. Each subobject with a vfptr gets its own vftable rather than an address
2386 // point in a single vtable shared between all the subobjects.
2387 // Each vftable is represented by a separate section and virtual calls
2388 // must be done using the vftable which has a slot for the function to be
2391 // 3. Virtual method definitions expect their 'this' parameter to point to the
2392 // first vfptr whose table provides a compatible overridden method. In many
2393 // cases, this permits the original vf-table entry to directly call
2394 // the method instead of passing through a thunk.
2395 // See example before VFTableBuilder::ComputeThisOffset below.
2397 // A compatible overridden method is one which does not have a non-trivial
2398 // covariant-return adjustment.
2400 // The first vfptr is the one with the lowest offset in the complete-object
2401 // layout of the defining class, and the method definition will subtract
2402 // that constant offset from the parameter value to get the real 'this'
2403 // value. Therefore, if the offset isn't really constant (e.g. if a virtual
2404 // function defined in a virtual base is overridden in a more derived
2405 // virtual base and these bases have a reverse order in the complete
2406 // object), the vf-table may require a this-adjustment thunk.
2408 // 4. vftables do not contain new entries for overrides that merely require
2409 // this-adjustment. Together with #3, this keeps vf-tables smaller and
2410 // eliminates the need for this-adjustment thunks in many cases, at the cost
2411 // of often requiring redundant work to adjust the "this" pointer.
2413 // 5. Instead of VTT and constructor vtables, vbtables and vtordisps are used.
2414 // Vtordisps are emitted into the class layout if a class has
2415 // a) a user-defined ctor/dtor
2417 // b) a method overriding a method in a virtual base.
2419 // To get a better understanding of this code,
2420 // you might want to see examples in test/CodeGenCXX/microsoft-abi-vtables-*.cpp
2422 class VFTableBuilder
{
2424 typedef llvm::DenseMap
<GlobalDecl
, MethodVFTableLocation
>
2425 MethodVFTableLocationsTy
;
2427 typedef llvm::iterator_range
<MethodVFTableLocationsTy::const_iterator
>
2428 method_locations_range
;
2431 /// VTables - Global vtable information.
2432 MicrosoftVTableContext
&VTables
;
2434 /// Context - The ASTContext which we will use for layout information.
2435 ASTContext
&Context
;
2437 /// MostDerivedClass - The most derived class for which we're building this
2439 const CXXRecordDecl
*MostDerivedClass
;
2441 const ASTRecordLayout
&MostDerivedClassLayout
;
2443 const VPtrInfo
&WhichVFPtr
;
2445 /// FinalOverriders - The final overriders of the most derived class.
2446 const FinalOverriders Overriders
;
2448 /// Components - The components of the vftable being built.
2449 SmallVector
<VTableComponent
, 64> Components
;
2451 MethodVFTableLocationsTy MethodVFTableLocations
;
2453 /// Does this class have an RTTI component?
2454 bool HasRTTIComponent
= false;
2456 /// MethodInfo - Contains information about a method in a vtable.
2457 /// (Used for computing 'this' pointer adjustment thunks.
2459 /// VBTableIndex - The nonzero index in the vbtable that
2460 /// this method's base has, or zero.
2461 const uint64_t VBTableIndex
;
2463 /// VFTableIndex - The index in the vftable that this method has.
2464 const uint64_t VFTableIndex
;
2466 /// Shadowed - Indicates if this vftable slot is shadowed by
2467 /// a slot for a covariant-return override. If so, it shouldn't be printed
2468 /// or used for vcalls in the most derived class.
2471 /// UsesExtraSlot - Indicates if this vftable slot was created because
2472 /// any of the overridden slots required a return adjusting thunk.
2475 MethodInfo(uint64_t VBTableIndex
, uint64_t VFTableIndex
,
2476 bool UsesExtraSlot
= false)
2477 : VBTableIndex(VBTableIndex
), VFTableIndex(VFTableIndex
),
2478 Shadowed(false), UsesExtraSlot(UsesExtraSlot
) {}
2481 : VBTableIndex(0), VFTableIndex(0), Shadowed(false),
2482 UsesExtraSlot(false) {}
2485 typedef llvm::DenseMap
<const CXXMethodDecl
*, MethodInfo
> MethodInfoMapTy
;
2487 /// MethodInfoMap - The information for all methods in the vftable we're
2488 /// currently building.
2489 MethodInfoMapTy MethodInfoMap
;
2491 typedef llvm::DenseMap
<uint64_t, ThunkInfo
> VTableThunksMapTy
;
2493 /// VTableThunks - The thunks by vftable index in the vftable currently being
2495 VTableThunksMapTy VTableThunks
;
2497 typedef SmallVector
<ThunkInfo
, 1> ThunkInfoVectorTy
;
2498 typedef llvm::DenseMap
<const CXXMethodDecl
*, ThunkInfoVectorTy
> ThunksMapTy
;
2500 /// Thunks - A map that contains all the thunks needed for all methods in the
2501 /// most derived class for which the vftable is currently being built.
2504 /// AddThunk - Add a thunk for the given method.
2505 void AddThunk(const CXXMethodDecl
*MD
, const ThunkInfo
&Thunk
) {
2506 SmallVector
<ThunkInfo
, 1> &ThunksVector
= Thunks
[MD
];
2508 // Check if we have this thunk already.
2509 if (llvm::is_contained(ThunksVector
, Thunk
))
2512 ThunksVector
.push_back(Thunk
);
2515 /// ComputeThisOffset - Returns the 'this' argument offset for the given
2516 /// method, relative to the beginning of the MostDerivedClass.
2517 CharUnits
ComputeThisOffset(FinalOverriders::OverriderInfo Overrider
);
2519 void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider
,
2520 CharUnits ThisOffset
, ThisAdjustment
&TA
);
2522 /// AddMethod - Add a single virtual member function to the vftable
2523 /// components vector.
2524 void AddMethod(const CXXMethodDecl
*MD
, ThunkInfo TI
) {
2525 if (!TI
.isEmpty()) {
2526 VTableThunks
[Components
.size()] = TI
;
2529 if (const CXXDestructorDecl
*DD
= dyn_cast
<CXXDestructorDecl
>(MD
)) {
2530 assert(TI
.Return
.isEmpty() &&
2531 "Destructor can't have return adjustment!");
2532 Components
.push_back(VTableComponent::MakeDeletingDtor(DD
));
2534 Components
.push_back(VTableComponent::MakeFunction(MD
));
2538 /// AddMethods - Add the methods of this base subobject and the relevant
2539 /// subbases to the vftable we're currently laying out.
2540 void AddMethods(BaseSubobject Base
, unsigned BaseDepth
,
2541 const CXXRecordDecl
*LastVBase
,
2542 BasesSetVectorTy
&VisitedBases
);
2544 void LayoutVFTable() {
2545 // RTTI data goes before all other entries.
2546 if (HasRTTIComponent
)
2547 Components
.push_back(VTableComponent::MakeRTTI(MostDerivedClass
));
2549 BasesSetVectorTy VisitedBases
;
2550 AddMethods(BaseSubobject(MostDerivedClass
, CharUnits::Zero()), 0, nullptr,
2552 // Note that it is possible for the vftable to contain only an RTTI
2553 // pointer, if all virtual functions are constewval.
2554 assert(!Components
.empty() && "vftable can't be empty");
2556 assert(MethodVFTableLocations
.empty());
2557 for (const auto &I
: MethodInfoMap
) {
2558 const CXXMethodDecl
*MD
= I
.first
;
2559 const MethodInfo
&MI
= I
.second
;
2560 assert(MD
== MD
->getCanonicalDecl());
2562 // Skip the methods that the MostDerivedClass didn't override
2563 // and the entries shadowed by return adjusting thunks.
2564 if (MD
->getParent() != MostDerivedClass
|| MI
.Shadowed
)
2566 MethodVFTableLocation
Loc(MI
.VBTableIndex
, WhichVFPtr
.getVBaseWithVPtr(),
2567 WhichVFPtr
.NonVirtualOffset
, MI
.VFTableIndex
);
2568 if (const CXXDestructorDecl
*DD
= dyn_cast
<CXXDestructorDecl
>(MD
)) {
2569 MethodVFTableLocations
[GlobalDecl(DD
, Dtor_Deleting
)] = Loc
;
2571 MethodVFTableLocations
[MD
] = Loc
;
2577 VFTableBuilder(MicrosoftVTableContext
&VTables
,
2578 const CXXRecordDecl
*MostDerivedClass
, const VPtrInfo
&Which
)
2580 Context(MostDerivedClass
->getASTContext()),
2581 MostDerivedClass(MostDerivedClass
),
2582 MostDerivedClassLayout(Context
.getASTRecordLayout(MostDerivedClass
)),
2584 Overriders(MostDerivedClass
, CharUnits(), MostDerivedClass
) {
2585 // Provide the RTTI component if RTTIData is enabled. If the vftable would
2586 // be available externally, we should not provide the RTTI componenent. It
2587 // is currently impossible to get available externally vftables with either
2588 // dllimport or extern template instantiations, but eventually we may add a
2589 // flag to support additional devirtualization that needs this.
2590 if (Context
.getLangOpts().RTTIData
)
2591 HasRTTIComponent
= true;
2595 if (Context
.getLangOpts().DumpVTableLayouts
)
2596 dumpLayout(llvm::outs());
2599 uint64_t getNumThunks() const { return Thunks
.size(); }
2601 ThunksMapTy::const_iterator
thunks_begin() const { return Thunks
.begin(); }
2603 ThunksMapTy::const_iterator
thunks_end() const { return Thunks
.end(); }
2605 method_locations_range
vtable_locations() const {
2606 return method_locations_range(MethodVFTableLocations
.begin(),
2607 MethodVFTableLocations
.end());
2610 ArrayRef
<VTableComponent
> vtable_components() const { return Components
; }
2612 VTableThunksMapTy::const_iterator
vtable_thunks_begin() const {
2613 return VTableThunks
.begin();
2616 VTableThunksMapTy::const_iterator
vtable_thunks_end() const {
2617 return VTableThunks
.end();
2620 void dumpLayout(raw_ostream
&);
2625 // Let's study one class hierarchy as an example:
2627 // virtual void f();
2631 // struct B : virtual A {
2632 // virtual void f();
2637 // 0 | (A vftable pointer)
2641 // 0 | (B vbtable pointer)
2642 // 4 | struct A (virtual base)
2643 // 4 | (A vftable pointer)
2646 // Let's assume we have a pointer to the A part of an object of dynamic type B:
2651 // In this hierarchy, f() belongs to the vftable of A, so B::f() expects
2652 // "this" parameter to point at the A subobject, which is B+4.
2653 // In the B::f() prologue, it adjusts "this" back to B by subtracting 4,
2654 // performed as a *static* adjustment.
2656 // Interesting thing happens when we alter the relative placement of A and B
2657 // subobjects in a class:
2658 // struct C : virtual B { };
2664 // Respective record layout is:
2665 // 0 | (C vbtable pointer)
2666 // 4 | struct A (virtual base)
2667 // 4 | (A vftable pointer)
2669 // 12 | struct B (virtual base)
2670 // 12 | (B vbtable pointer)
2672 // The final overrider of f() in class C is still B::f(), so B+4 should be
2673 // passed as "this" to that code. However, "a" points at B-8, so the respective
2674 // vftable entry should hold a thunk that adds 12 to the "this" argument before
2675 // performing a tail call to B::f().
2677 // With this example in mind, we can now calculate the 'this' argument offset
2678 // for the given method, relative to the beginning of the MostDerivedClass.
2680 VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider
) {
2681 BasesSetVectorTy Bases
;
2684 // Find the set of least derived bases that define the given method.
2685 OverriddenMethodsSetTy VisitedOverriddenMethods
;
2686 auto InitialOverriddenDefinitionCollector
= [&](
2687 const CXXMethodDecl
*OverriddenMD
) {
2688 if (OverriddenMD
->size_overridden_methods() == 0)
2689 Bases
.insert(OverriddenMD
->getParent());
2690 // Don't recurse on this method if we've already collected it.
2691 return VisitedOverriddenMethods
.insert(OverriddenMD
).second
;
2693 visitAllOverriddenMethods(Overrider
.Method
,
2694 InitialOverriddenDefinitionCollector
);
2697 // If there are no overrides then 'this' is located
2698 // in the base that defines the method.
2699 if (Bases
.size() == 0)
2700 return Overrider
.Offset
;
2703 Overrider
.Method
->getParent()->lookupInBases(
2704 [&Bases
](const CXXBaseSpecifier
*Specifier
, CXXBasePath
&) {
2705 return Bases
.count(Specifier
->getType()->getAsCXXRecordDecl());
2709 // This will hold the smallest this offset among overridees of MD.
2710 // This implies that an offset of a non-virtual base will dominate an offset
2711 // of a virtual base to potentially reduce the number of thunks required
2712 // in the derived classes that inherit this method.
2716 const ASTRecordLayout
&OverriderRDLayout
=
2717 Context
.getASTRecordLayout(Overrider
.Method
->getParent());
2718 for (const CXXBasePath
&Path
: Paths
) {
2719 CharUnits ThisOffset
= Overrider
.Offset
;
2720 CharUnits LastVBaseOffset
;
2722 // For each path from the overrider to the parents of the overridden
2723 // methods, traverse the path, calculating the this offset in the most
2725 for (const CXXBasePathElement
&Element
: Path
) {
2726 QualType CurTy
= Element
.Base
->getType();
2727 const CXXRecordDecl
*PrevRD
= Element
.Class
,
2728 *CurRD
= CurTy
->getAsCXXRecordDecl();
2729 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(PrevRD
);
2731 if (Element
.Base
->isVirtual()) {
2732 // The interesting things begin when you have virtual inheritance.
2733 // The final overrider will use a static adjustment equal to the offset
2734 // of the vbase in the final overrider class.
2735 // For example, if the final overrider is in a vbase B of the most
2736 // derived class and it overrides a method of the B's own vbase A,
2737 // it uses A* as "this". In its prologue, it can cast A* to B* with
2738 // a static offset. This offset is used regardless of the actual
2739 // offset of A from B in the most derived class, requiring an
2740 // this-adjusting thunk in the vftable if A and B are laid out
2741 // differently in the most derived class.
2742 LastVBaseOffset
= ThisOffset
=
2743 Overrider
.Offset
+ OverriderRDLayout
.getVBaseClassOffset(CurRD
);
2745 ThisOffset
+= Layout
.getBaseClassOffset(CurRD
);
2749 if (isa
<CXXDestructorDecl
>(Overrider
.Method
)) {
2750 if (LastVBaseOffset
.isZero()) {
2751 // If a "Base" class has at least one non-virtual base with a virtual
2752 // destructor, the "Base" virtual destructor will take the address
2753 // of the "Base" subobject as the "this" argument.
2754 ThisOffset
= Overrider
.Offset
;
2756 // A virtual destructor of a virtual base takes the address of the
2757 // virtual base subobject as the "this" argument.
2758 ThisOffset
= LastVBaseOffset
;
2762 if (Ret
> ThisOffset
|| First
) {
2768 assert(!First
&& "Method not found in the given subobject?");
2772 // Things are getting even more complex when the "this" adjustment has to
2773 // use a dynamic offset instead of a static one, or even two dynamic offsets.
2774 // This is sometimes required when a virtual call happens in the middle of
2775 // a non-most-derived class construction or destruction.
2777 // Let's take a look at the following example:
2779 // virtual void f();
2782 // void foo(A *a) { a->f(); } // Knows nothing about siblings of A.
2784 // struct B : virtual A {
2785 // virtual void f();
2791 // struct C : virtual B {
2792 // virtual void f();
2795 // Record layouts for these classes are:
2797 // 0 | (A vftable pointer)
2800 // 0 | (B vbtable pointer)
2801 // 4 | (vtordisp for vbase A)
2802 // 8 | struct A (virtual base)
2803 // 8 | (A vftable pointer)
2806 // 0 | (C vbtable pointer)
2807 // 4 | (vtordisp for vbase A)
2808 // 8 | struct A (virtual base) // A precedes B!
2809 // 8 | (A vftable pointer)
2810 // 12 | struct B (virtual base)
2811 // 12 | (B vbtable pointer)
2813 // When one creates an object of type C, the C constructor:
2814 // - initializes all the vbptrs, then
2815 // - calls the A subobject constructor
2816 // (initializes A's vfptr with an address of A vftable), then
2817 // - calls the B subobject constructor
2818 // (initializes A's vfptr with an address of B vftable and vtordisp for A),
2819 // that in turn calls foo(), then
2820 // - initializes A's vfptr with an address of C vftable and zeroes out the
2822 // FIXME: if a structor knows it belongs to MDC, why doesn't it use a vftable
2823 // without vtordisp thunks?
2824 // FIXME: how are vtordisp handled in the presence of nooverride/final?
2826 // When foo() is called, an object with a layout of class C has a vftable
2827 // referencing B::f() that assumes a B layout, so the "this" adjustments are
2828 // incorrect, unless an extra adjustment is done. This adjustment is called
2829 // "vtordisp adjustment". Vtordisp basically holds the difference between the
2830 // actual location of a vbase in the layout class and the location assumed by
2831 // the vftable of the class being constructed/destructed. Vtordisp is only
2832 // needed if "this" escapes a
2833 // structor (or we can't prove otherwise).
2834 // [i.e. vtordisp is a dynamic adjustment for a static adjustment, which is an
2835 // estimation of a dynamic adjustment]
2837 // foo() gets a pointer to the A vbase and doesn't know anything about B or C,
2838 // so it just passes that pointer as "this" in a virtual call.
2839 // If there was no vtordisp, that would just dispatch to B::f().
2840 // However, B::f() assumes B+8 is passed as "this",
2841 // yet the pointer foo() passes along is B-4 (i.e. C+8).
2842 // An extra adjustment is needed, so we emit a thunk into the B vftable.
2843 // This vtordisp thunk subtracts the value of vtordisp
2844 // from the "this" argument (-12) before making a tailcall to B::f().
2846 // Let's consider an even more complex example:
2847 // struct D : virtual B, virtual C {
2854 // 0 | (D vbtable pointer)
2855 // 4 | (vtordisp for vbase A)
2856 // 8 | struct A (virtual base) // A precedes both B and C!
2857 // 8 | (A vftable pointer)
2858 // 12 | struct B (virtual base) // B precedes C!
2859 // 12 | (B vbtable pointer)
2860 // 16 | struct C (virtual base)
2861 // 16 | (C vbtable pointer)
2863 // When D::D() calls foo(), we find ourselves in a thunk that should tailcall
2864 // to C::f(), which assumes C+8 as its "this" parameter. This time, foo()
2865 // passes along A, which is C-8. The A vtordisp holds
2866 // "D.vbptr[index_of_A] - offset_of_A_in_D"
2867 // and we statically know offset_of_A_in_D, so can get a pointer to D.
2868 // When we know it, we can make an extra vbtable lookup to locate the C vbase
2869 // and one extra static adjustment to calculate the expected value of C+8.
2870 void VFTableBuilder::CalculateVtordispAdjustment(
2871 FinalOverriders::OverriderInfo Overrider
, CharUnits ThisOffset
,
2872 ThisAdjustment
&TA
) {
2873 const ASTRecordLayout::VBaseOffsetsMapTy
&VBaseMap
=
2874 MostDerivedClassLayout
.getVBaseOffsetsMap();
2875 const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator
&VBaseMapEntry
=
2876 VBaseMap
.find(WhichVFPtr
.getVBaseWithVPtr());
2877 assert(VBaseMapEntry
!= VBaseMap
.end());
2879 // If there's no vtordisp or the final overrider is defined in the same vbase
2880 // as the initial declaration, we don't need any vtordisp adjustment.
2881 if (!VBaseMapEntry
->second
.hasVtorDisp() ||
2882 Overrider
.VirtualBase
== WhichVFPtr
.getVBaseWithVPtr())
2885 // OK, now we know we need to use a vtordisp thunk.
2886 // The implicit vtordisp field is located right before the vbase.
2887 CharUnits OffsetOfVBaseWithVFPtr
= VBaseMapEntry
->second
.VBaseOffset
;
2888 TA
.Virtual
.Microsoft
.VtordispOffset
=
2889 (OffsetOfVBaseWithVFPtr
- WhichVFPtr
.FullOffsetInMDC
).getQuantity() - 4;
2891 // A simple vtordisp thunk will suffice if the final overrider is defined
2892 // in either the most derived class or its non-virtual base.
2893 if (Overrider
.Method
->getParent() == MostDerivedClass
||
2894 !Overrider
.VirtualBase
)
2897 // Otherwise, we need to do use the dynamic offset of the final overrider
2898 // in order to get "this" adjustment right.
2899 TA
.Virtual
.Microsoft
.VBPtrOffset
=
2900 (OffsetOfVBaseWithVFPtr
+ WhichVFPtr
.NonVirtualOffset
-
2901 MostDerivedClassLayout
.getVBPtrOffset()).getQuantity();
2902 TA
.Virtual
.Microsoft
.VBOffsetOffset
=
2903 Context
.getTypeSizeInChars(Context
.IntTy
).getQuantity() *
2904 VTables
.getVBTableIndex(MostDerivedClass
, Overrider
.VirtualBase
);
2906 TA
.NonVirtual
= (ThisOffset
- Overrider
.Offset
).getQuantity();
2909 static void GroupNewVirtualOverloads(
2910 const CXXRecordDecl
*RD
,
2911 SmallVector
<const CXXMethodDecl
*, 10> &VirtualMethods
) {
2912 // Put the virtual methods into VirtualMethods in the proper order:
2913 // 1) Group overloads by declaration name. New groups are added to the
2914 // vftable in the order of their first declarations in this class
2915 // (including overrides, non-virtual methods and any other named decl that
2916 // might be nested within the class).
2917 // 2) In each group, new overloads appear in the reverse order of declaration.
2918 typedef SmallVector
<const CXXMethodDecl
*, 1> MethodGroup
;
2919 SmallVector
<MethodGroup
, 10> Groups
;
2920 typedef llvm::DenseMap
<DeclarationName
, unsigned> VisitedGroupIndicesTy
;
2921 VisitedGroupIndicesTy VisitedGroupIndices
;
2922 for (const auto *D
: RD
->decls()) {
2923 const auto *ND
= dyn_cast
<NamedDecl
>(D
);
2926 VisitedGroupIndicesTy::iterator J
;
2928 std::tie(J
, Inserted
) = VisitedGroupIndices
.insert(
2929 std::make_pair(ND
->getDeclName(), Groups
.size()));
2931 Groups
.push_back(MethodGroup());
2932 if (const auto *MD
= dyn_cast
<CXXMethodDecl
>(ND
))
2933 if (MicrosoftVTableContext::hasVtableSlot(MD
))
2934 Groups
[J
->second
].push_back(MD
->getCanonicalDecl());
2937 for (const MethodGroup
&Group
: Groups
)
2938 VirtualMethods
.append(Group
.rbegin(), Group
.rend());
2941 static bool isDirectVBase(const CXXRecordDecl
*Base
, const CXXRecordDecl
*RD
) {
2942 for (const auto &B
: RD
->bases()) {
2943 if (B
.isVirtual() && B
.getType()->getAsCXXRecordDecl() == Base
)
2949 void VFTableBuilder::AddMethods(BaseSubobject Base
, unsigned BaseDepth
,
2950 const CXXRecordDecl
*LastVBase
,
2951 BasesSetVectorTy
&VisitedBases
) {
2952 const CXXRecordDecl
*RD
= Base
.getBase();
2953 if (!RD
->isPolymorphic())
2956 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(RD
);
2958 // See if this class expands a vftable of the base we look at, which is either
2959 // the one defined by the vfptr base path or the primary base of the current
2961 const CXXRecordDecl
*NextBase
= nullptr, *NextLastVBase
= LastVBase
;
2962 CharUnits NextBaseOffset
;
2963 if (BaseDepth
< WhichVFPtr
.PathToIntroducingObject
.size()) {
2964 NextBase
= WhichVFPtr
.PathToIntroducingObject
[BaseDepth
];
2965 if (isDirectVBase(NextBase
, RD
)) {
2966 NextLastVBase
= NextBase
;
2967 NextBaseOffset
= MostDerivedClassLayout
.getVBaseClassOffset(NextBase
);
2970 Base
.getBaseOffset() + Layout
.getBaseClassOffset(NextBase
);
2972 } else if (const CXXRecordDecl
*PrimaryBase
= Layout
.getPrimaryBase()) {
2973 assert(!Layout
.isPrimaryBaseVirtual() &&
2974 "No primary virtual bases in this ABI");
2975 NextBase
= PrimaryBase
;
2976 NextBaseOffset
= Base
.getBaseOffset();
2980 AddMethods(BaseSubobject(NextBase
, NextBaseOffset
), BaseDepth
+ 1,
2981 NextLastVBase
, VisitedBases
);
2982 if (!VisitedBases
.insert(NextBase
))
2983 llvm_unreachable("Found a duplicate primary base!");
2986 SmallVector
<const CXXMethodDecl
*, 10> VirtualMethods
;
2987 // Put virtual methods in the proper order.
2988 GroupNewVirtualOverloads(RD
, VirtualMethods
);
2990 // Now go through all virtual member functions and add them to the current
2991 // vftable. This is done by
2992 // - replacing overridden methods in their existing slots, as long as they
2993 // don't require return adjustment; calculating This adjustment if needed.
2994 // - adding new slots for methods of the current base not present in any
2996 // - adding new slots for methods that require Return adjustment.
2997 // We keep track of the methods visited in the sub-bases in MethodInfoMap.
2998 for (const CXXMethodDecl
*MD
: VirtualMethods
) {
2999 FinalOverriders::OverriderInfo FinalOverrider
=
3000 Overriders
.getOverrider(MD
, Base
.getBaseOffset());
3001 const CXXMethodDecl
*FinalOverriderMD
= FinalOverrider
.Method
;
3002 const CXXMethodDecl
*OverriddenMD
=
3003 FindNearestOverriddenMethod(MD
, VisitedBases
);
3005 ThisAdjustment ThisAdjustmentOffset
;
3006 bool ReturnAdjustingThunk
= false, ForceReturnAdjustmentMangling
= false;
3007 CharUnits ThisOffset
= ComputeThisOffset(FinalOverrider
);
3008 ThisAdjustmentOffset
.NonVirtual
=
3009 (ThisOffset
- WhichVFPtr
.FullOffsetInMDC
).getQuantity();
3010 if ((OverriddenMD
|| FinalOverriderMD
!= MD
) &&
3011 WhichVFPtr
.getVBaseWithVPtr())
3012 CalculateVtordispAdjustment(FinalOverrider
, ThisOffset
,
3013 ThisAdjustmentOffset
);
3016 LastVBase
? VTables
.getVBTableIndex(MostDerivedClass
, LastVBase
) : 0;
3019 // If MD overrides anything in this vftable, we need to update the
3021 MethodInfoMapTy::iterator OverriddenMDIterator
=
3022 MethodInfoMap
.find(OverriddenMD
);
3024 // If the overridden method went to a different vftable, skip it.
3025 if (OverriddenMDIterator
== MethodInfoMap
.end())
3028 MethodInfo
&OverriddenMethodInfo
= OverriddenMDIterator
->second
;
3030 VBIndex
= OverriddenMethodInfo
.VBTableIndex
;
3032 // Let's check if the overrider requires any return adjustments.
3033 // We must create a new slot if the MD's return type is not trivially
3034 // convertible to the OverriddenMD's one.
3035 // Once a chain of method overrides adds a return adjusting vftable slot,
3036 // all subsequent overrides will also use an extra method slot.
3037 ReturnAdjustingThunk
= !ComputeReturnAdjustmentBaseOffset(
3038 Context
, MD
, OverriddenMD
).isEmpty() ||
3039 OverriddenMethodInfo
.UsesExtraSlot
;
3041 if (!ReturnAdjustingThunk
) {
3042 // No return adjustment needed - just replace the overridden method info
3043 // with the current info.
3044 MethodInfo
MI(VBIndex
, OverriddenMethodInfo
.VFTableIndex
);
3045 MethodInfoMap
.erase(OverriddenMDIterator
);
3047 assert(!MethodInfoMap
.count(MD
) &&
3048 "Should not have method info for this method yet!");
3049 MethodInfoMap
.insert(std::make_pair(MD
, MI
));
3053 // In case we need a return adjustment, we'll add a new slot for
3054 // the overrider. Mark the overridden method as shadowed by the new slot.
3055 OverriddenMethodInfo
.Shadowed
= true;
3057 // Force a special name mangling for a return-adjusting thunk
3058 // unless the method is the final overrider without this adjustment.
3059 ForceReturnAdjustmentMangling
=
3060 !(MD
== FinalOverriderMD
&& ThisAdjustmentOffset
.isEmpty());
3061 } else if (Base
.getBaseOffset() != WhichVFPtr
.FullOffsetInMDC
||
3062 MD
->size_overridden_methods()) {
3063 // Skip methods that don't belong to the vftable of the current class,
3064 // e.g. each method that wasn't seen in any of the visited sub-bases
3065 // but overrides multiple methods of other sub-bases.
3069 // If we got here, MD is a method not seen in any of the sub-bases or
3070 // it requires return adjustment. Insert the method info for this method.
3071 MethodInfo
MI(VBIndex
,
3072 HasRTTIComponent
? Components
.size() - 1 : Components
.size(),
3073 ReturnAdjustingThunk
);
3075 assert(!MethodInfoMap
.count(MD
) &&
3076 "Should not have method info for this method yet!");
3077 MethodInfoMap
.insert(std::make_pair(MD
, MI
));
3079 // Check if this overrider needs a return adjustment.
3080 // We don't want to do this for pure virtual member functions.
3081 BaseOffset ReturnAdjustmentOffset
;
3082 ReturnAdjustment ReturnAdjustment
;
3083 if (!FinalOverriderMD
->isPure()) {
3084 ReturnAdjustmentOffset
=
3085 ComputeReturnAdjustmentBaseOffset(Context
, FinalOverriderMD
, MD
);
3087 if (!ReturnAdjustmentOffset
.isEmpty()) {
3088 ForceReturnAdjustmentMangling
= true;
3089 ReturnAdjustment
.NonVirtual
=
3090 ReturnAdjustmentOffset
.NonVirtualOffset
.getQuantity();
3091 if (ReturnAdjustmentOffset
.VirtualBase
) {
3092 const ASTRecordLayout
&DerivedLayout
=
3093 Context
.getASTRecordLayout(ReturnAdjustmentOffset
.DerivedClass
);
3094 ReturnAdjustment
.Virtual
.Microsoft
.VBPtrOffset
=
3095 DerivedLayout
.getVBPtrOffset().getQuantity();
3096 ReturnAdjustment
.Virtual
.Microsoft
.VBIndex
=
3097 VTables
.getVBTableIndex(ReturnAdjustmentOffset
.DerivedClass
,
3098 ReturnAdjustmentOffset
.VirtualBase
);
3102 AddMethod(FinalOverriderMD
,
3103 ThunkInfo(ThisAdjustmentOffset
, ReturnAdjustment
,
3104 ForceReturnAdjustmentMangling
? MD
: nullptr));
3108 static void PrintBasePath(const VPtrInfo::BasePath
&Path
, raw_ostream
&Out
) {
3109 for (const CXXRecordDecl
*Elem
: llvm::reverse(Path
)) {
3111 Elem
->printQualifiedName(Out
);
3116 static void dumpMicrosoftThunkAdjustment(const ThunkInfo
&TI
, raw_ostream
&Out
,
3117 bool ContinueFirstLine
) {
3118 const ReturnAdjustment
&R
= TI
.Return
;
3119 bool Multiline
= false;
3120 const char *LinePrefix
= "\n ";
3121 if (!R
.isEmpty() || TI
.Method
) {
3122 if (!ContinueFirstLine
)
3124 Out
<< "[return adjustment (to type '"
3125 << TI
.Method
->getReturnType().getCanonicalType() << "'): ";
3126 if (R
.Virtual
.Microsoft
.VBPtrOffset
)
3127 Out
<< "vbptr at offset " << R
.Virtual
.Microsoft
.VBPtrOffset
<< ", ";
3128 if (R
.Virtual
.Microsoft
.VBIndex
)
3129 Out
<< "vbase #" << R
.Virtual
.Microsoft
.VBIndex
<< ", ";
3130 Out
<< R
.NonVirtual
<< " non-virtual]";
3134 const ThisAdjustment
&T
= TI
.This
;
3136 if (Multiline
|| !ContinueFirstLine
)
3138 Out
<< "[this adjustment: ";
3139 if (!TI
.This
.Virtual
.isEmpty()) {
3140 assert(T
.Virtual
.Microsoft
.VtordispOffset
< 0);
3141 Out
<< "vtordisp at " << T
.Virtual
.Microsoft
.VtordispOffset
<< ", ";
3142 if (T
.Virtual
.Microsoft
.VBPtrOffset
) {
3143 Out
<< "vbptr at " << T
.Virtual
.Microsoft
.VBPtrOffset
3145 assert(T
.Virtual
.Microsoft
.VBOffsetOffset
> 0);
3146 Out
<< LinePrefix
<< " vboffset at "
3147 << T
.Virtual
.Microsoft
.VBOffsetOffset
<< " in the vbtable, ";
3150 Out
<< T
.NonVirtual
<< " non-virtual]";
3154 void VFTableBuilder::dumpLayout(raw_ostream
&Out
) {
3155 Out
<< "VFTable for ";
3156 PrintBasePath(WhichVFPtr
.PathToIntroducingObject
, Out
);
3158 MostDerivedClass
->printQualifiedName(Out
);
3159 Out
<< "' (" << Components
.size()
3160 << (Components
.size() == 1 ? " entry" : " entries") << ").\n";
3162 for (unsigned I
= 0, E
= Components
.size(); I
!= E
; ++I
) {
3163 Out
<< llvm::format("%4d | ", I
);
3165 const VTableComponent
&Component
= Components
[I
];
3167 // Dump the component.
3168 switch (Component
.getKind()) {
3169 case VTableComponent::CK_RTTI
:
3170 Component
.getRTTIDecl()->printQualifiedName(Out
);
3174 case VTableComponent::CK_FunctionPointer
: {
3175 const CXXMethodDecl
*MD
= Component
.getFunctionDecl();
3177 // FIXME: Figure out how to print the real thunk type, since they can
3178 // differ in the return type.
3179 std::string Str
= PredefinedExpr::ComputeName(
3180 PredefinedExpr::PrettyFunctionNoVirtual
, MD
);
3185 if (MD
->isDeleted())
3186 Out
<< " [deleted]";
3188 ThunkInfo Thunk
= VTableThunks
.lookup(I
);
3189 if (!Thunk
.isEmpty())
3190 dumpMicrosoftThunkAdjustment(Thunk
, Out
, /*ContinueFirstLine=*/false);
3195 case VTableComponent::CK_DeletingDtorPointer
: {
3196 const CXXDestructorDecl
*DD
= Component
.getDestructorDecl();
3198 DD
->printQualifiedName(Out
);
3199 Out
<< "() [scalar deleting]";
3204 ThunkInfo Thunk
= VTableThunks
.lookup(I
);
3205 if (!Thunk
.isEmpty()) {
3206 assert(Thunk
.Return
.isEmpty() &&
3207 "No return adjustment needed for destructors!");
3208 dumpMicrosoftThunkAdjustment(Thunk
, Out
, /*ContinueFirstLine=*/false);
3215 DiagnosticsEngine
&Diags
= Context
.getDiagnostics();
3216 unsigned DiagID
= Diags
.getCustomDiagID(
3217 DiagnosticsEngine::Error
,
3218 "Unexpected vftable component type %0 for component number %1");
3219 Diags
.Report(MostDerivedClass
->getLocation(), DiagID
)
3220 << I
<< Component
.getKind();
3228 if (!Thunks
.empty()) {
3229 // We store the method names in a map to get a stable order.
3230 std::map
<std::string
, const CXXMethodDecl
*> MethodNamesAndDecls
;
3232 for (const auto &I
: Thunks
) {
3233 const CXXMethodDecl
*MD
= I
.first
;
3234 std::string MethodName
= PredefinedExpr::ComputeName(
3235 PredefinedExpr::PrettyFunctionNoVirtual
, MD
);
3237 MethodNamesAndDecls
.insert(std::make_pair(MethodName
, MD
));
3240 for (const auto &MethodNameAndDecl
: MethodNamesAndDecls
) {
3241 const std::string
&MethodName
= MethodNameAndDecl
.first
;
3242 const CXXMethodDecl
*MD
= MethodNameAndDecl
.second
;
3244 ThunkInfoVectorTy ThunksVector
= Thunks
[MD
];
3245 llvm::stable_sort(ThunksVector
, [](const ThunkInfo
&LHS
,
3246 const ThunkInfo
&RHS
) {
3247 // Keep different thunks with the same adjustments in the order they
3248 // were put into the vector.
3249 return std::tie(LHS
.This
, LHS
.Return
) < std::tie(RHS
.This
, RHS
.Return
);
3252 Out
<< "Thunks for '" << MethodName
<< "' (" << ThunksVector
.size();
3253 Out
<< (ThunksVector
.size() == 1 ? " entry" : " entries") << ").\n";
3255 for (unsigned I
= 0, E
= ThunksVector
.size(); I
!= E
; ++I
) {
3256 const ThunkInfo
&Thunk
= ThunksVector
[I
];
3258 Out
<< llvm::format("%4d | ", I
);
3259 dumpMicrosoftThunkAdjustment(Thunk
, Out
, /*ContinueFirstLine=*/true);
3270 static bool setsIntersect(const llvm::SmallPtrSet
<const CXXRecordDecl
*, 4> &A
,
3271 ArrayRef
<const CXXRecordDecl
*> B
) {
3272 for (const CXXRecordDecl
*Decl
: B
) {
3279 static bool rebucketPaths(VPtrInfoVector
&Paths
);
3281 /// Produces MSVC-compatible vbtable data. The symbols produced by this
3282 /// algorithm match those produced by MSVC 2012 and newer, which is different
3285 /// MSVC 2012 appears to minimize the vbtable names using the following
3286 /// algorithm. First, walk the class hierarchy in the usual order, depth first,
3287 /// left to right, to find all of the subobjects which contain a vbptr field.
3288 /// Visiting each class node yields a list of inheritance paths to vbptrs. Each
3289 /// record with a vbptr creates an initially empty path.
3291 /// To combine paths from child nodes, the paths are compared to check for
3292 /// ambiguity. Paths are "ambiguous" if multiple paths have the same set of
3293 /// components in the same order. Each group of ambiguous paths is extended by
3294 /// appending the class of the base from which it came. If the current class
3295 /// node produced an ambiguous path, its path is extended with the current class.
3296 /// After extending paths, MSVC again checks for ambiguity, and extends any
3297 /// ambiguous path which wasn't already extended. Because each node yields an
3298 /// unambiguous set of paths, MSVC doesn't need to extend any path more than once
3299 /// to produce an unambiguous set of paths.
3301 /// TODO: Presumably vftables use the same algorithm.
3302 void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables
,
3303 const CXXRecordDecl
*RD
,
3304 VPtrInfoVector
&Paths
) {
3305 assert(Paths
.empty());
3306 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(RD
);
3308 // Base case: this subobject has its own vptr.
3309 if (ForVBTables
? Layout
.hasOwnVBPtr() : Layout
.hasOwnVFPtr())
3310 Paths
.push_back(std::make_unique
<VPtrInfo
>(RD
));
3312 // Recursive case: get all the vbtables from our bases and remove anything
3313 // that shares a virtual base.
3314 llvm::SmallPtrSet
<const CXXRecordDecl
*, 4> VBasesSeen
;
3315 for (const auto &B
: RD
->bases()) {
3316 const CXXRecordDecl
*Base
= B
.getType()->getAsCXXRecordDecl();
3317 if (B
.isVirtual() && VBasesSeen
.count(Base
))
3320 if (!Base
->isDynamicClass())
3323 const VPtrInfoVector
&BasePaths
=
3324 ForVBTables
? enumerateVBTables(Base
) : getVFPtrOffsets(Base
);
3326 for (const std::unique_ptr
<VPtrInfo
> &BaseInfo
: BasePaths
) {
3327 // Don't include the path if it goes through a virtual base that we've
3328 // already included.
3329 if (setsIntersect(VBasesSeen
, BaseInfo
->ContainingVBases
))
3332 // Copy the path and adjust it as necessary.
3333 auto P
= std::make_unique
<VPtrInfo
>(*BaseInfo
);
3335 // We mangle Base into the path if the path would've been ambiguous and it
3336 // wasn't already extended with Base.
3337 if (P
->MangledPath
.empty() || P
->MangledPath
.back() != Base
)
3338 P
->NextBaseToMangle
= Base
;
3340 // Keep track of which vtable the derived class is going to extend with
3341 // new methods or bases. We append to either the vftable of our primary
3342 // base, or the first non-virtual base that has a vbtable.
3343 if (P
->ObjectWithVPtr
== Base
&&
3344 Base
== (ForVBTables
? Layout
.getBaseSharingVBPtr()
3345 : Layout
.getPrimaryBase()))
3346 P
->ObjectWithVPtr
= RD
;
3348 // Keep track of the full adjustment from the MDC to this vtable. The
3349 // adjustment is captured by an optional vbase and a non-virtual offset.
3351 P
->ContainingVBases
.push_back(Base
);
3352 else if (P
->ContainingVBases
.empty())
3353 P
->NonVirtualOffset
+= Layout
.getBaseClassOffset(Base
);
3355 // Update the full offset in the MDC.
3356 P
->FullOffsetInMDC
= P
->NonVirtualOffset
;
3357 if (const CXXRecordDecl
*VB
= P
->getVBaseWithVPtr())
3358 P
->FullOffsetInMDC
+= Layout
.getVBaseClassOffset(VB
);
3360 Paths
.push_back(std::move(P
));
3364 VBasesSeen
.insert(Base
);
3366 // After visiting any direct base, we've transitively visited all of its
3367 // morally virtual bases.
3368 for (const auto &VB
: Base
->vbases())
3369 VBasesSeen
.insert(VB
.getType()->getAsCXXRecordDecl());
3372 // Sort the paths into buckets, and if any of them are ambiguous, extend all
3373 // paths in ambiguous buckets.
3374 bool Changed
= true;
3376 Changed
= rebucketPaths(Paths
);
3379 static bool extendPath(VPtrInfo
&P
) {
3380 if (P
.NextBaseToMangle
) {
3381 P
.MangledPath
.push_back(P
.NextBaseToMangle
);
3382 P
.NextBaseToMangle
= nullptr;// Prevent the path from being extended twice.
3388 static bool rebucketPaths(VPtrInfoVector
&Paths
) {
3389 // What we're essentially doing here is bucketing together ambiguous paths.
3390 // Any bucket with more than one path in it gets extended by NextBase, which
3391 // is usually the direct base of the inherited the vbptr. This code uses a
3392 // sorted vector to implement a multiset to form the buckets. Note that the
3393 // ordering is based on pointers, but it doesn't change our output order. The
3394 // current algorithm is designed to match MSVC 2012's names.
3395 llvm::SmallVector
<std::reference_wrapper
<VPtrInfo
>, 2> PathsSorted(
3396 llvm::make_pointee_range(Paths
));
3397 llvm::sort(PathsSorted
, [](const VPtrInfo
&LHS
, const VPtrInfo
&RHS
) {
3398 return LHS
.MangledPath
< RHS
.MangledPath
;
3400 bool Changed
= false;
3401 for (size_t I
= 0, E
= PathsSorted
.size(); I
!= E
;) {
3402 // Scan forward to find the end of the bucket.
3403 size_t BucketStart
= I
;
3407 PathsSorted
[BucketStart
].get().MangledPath
==
3408 PathsSorted
[I
].get().MangledPath
);
3410 // If this bucket has multiple paths, extend them all.
3411 if (I
- BucketStart
> 1) {
3412 for (size_t II
= BucketStart
; II
!= I
; ++II
)
3413 Changed
|= extendPath(PathsSorted
[II
]);
3414 assert(Changed
&& "no paths were extended to fix ambiguity");
3420 MicrosoftVTableContext::~MicrosoftVTableContext() {}
3423 typedef llvm::SetVector
<BaseSubobject
, std::vector
<BaseSubobject
>,
3424 llvm::DenseSet
<BaseSubobject
>> FullPathTy
;
3427 // This recursive function finds all paths from a subobject centered at
3428 // (RD, Offset) to the subobject located at IntroducingObject.
3429 static void findPathsToSubobject(ASTContext
&Context
,
3430 const ASTRecordLayout
&MostDerivedLayout
,
3431 const CXXRecordDecl
*RD
, CharUnits Offset
,
3432 BaseSubobject IntroducingObject
,
3433 FullPathTy
&FullPath
,
3434 std::list
<FullPathTy
> &Paths
) {
3435 if (BaseSubobject(RD
, Offset
) == IntroducingObject
) {
3436 Paths
.push_back(FullPath
);
3440 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(RD
);
3442 for (const CXXBaseSpecifier
&BS
: RD
->bases()) {
3443 const CXXRecordDecl
*Base
= BS
.getType()->getAsCXXRecordDecl();
3444 CharUnits NewOffset
= BS
.isVirtual()
3445 ? MostDerivedLayout
.getVBaseClassOffset(Base
)
3446 : Offset
+ Layout
.getBaseClassOffset(Base
);
3447 FullPath
.insert(BaseSubobject(Base
, NewOffset
));
3448 findPathsToSubobject(Context
, MostDerivedLayout
, Base
, NewOffset
,
3449 IntroducingObject
, FullPath
, Paths
);
3450 FullPath
.pop_back();
3454 // Return the paths which are not subsets of other paths.
3455 static void removeRedundantPaths(std::list
<FullPathTy
> &FullPaths
) {
3456 FullPaths
.remove_if([&](const FullPathTy
&SpecificPath
) {
3457 for (const FullPathTy
&OtherPath
: FullPaths
) {
3458 if (&SpecificPath
== &OtherPath
)
3460 if (llvm::all_of(SpecificPath
, [&](const BaseSubobject
&BSO
) {
3461 return OtherPath
.contains(BSO
);
3470 static CharUnits
getOffsetOfFullPath(ASTContext
&Context
,
3471 const CXXRecordDecl
*RD
,
3472 const FullPathTy
&FullPath
) {
3473 const ASTRecordLayout
&MostDerivedLayout
=
3474 Context
.getASTRecordLayout(RD
);
3475 CharUnits Offset
= CharUnits::fromQuantity(-1);
3476 for (const BaseSubobject
&BSO
: FullPath
) {
3477 const CXXRecordDecl
*Base
= BSO
.getBase();
3478 // The first entry in the path is always the most derived record, skip it.
3480 assert(Offset
.getQuantity() == -1);
3481 Offset
= CharUnits::Zero();
3484 assert(Offset
.getQuantity() != -1);
3485 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(RD
);
3486 // While we know which base has to be traversed, we don't know if that base
3487 // was a virtual base.
3488 const CXXBaseSpecifier
*BaseBS
= std::find_if(
3489 RD
->bases_begin(), RD
->bases_end(), [&](const CXXBaseSpecifier
&BS
) {
3490 return BS
.getType()->getAsCXXRecordDecl() == Base
;
3492 Offset
= BaseBS
->isVirtual() ? MostDerivedLayout
.getVBaseClassOffset(Base
)
3493 : Offset
+ Layout
.getBaseClassOffset(Base
);
3499 // We want to select the path which introduces the most covariant overrides. If
3500 // two paths introduce overrides which the other path doesn't contain, issue a
3502 static const FullPathTy
*selectBestPath(ASTContext
&Context
,
3503 const CXXRecordDecl
*RD
,
3504 const VPtrInfo
&Info
,
3505 std::list
<FullPathTy
> &FullPaths
) {
3506 // Handle some easy cases first.
3507 if (FullPaths
.empty())
3509 if (FullPaths
.size() == 1)
3510 return &FullPaths
.front();
3512 const FullPathTy
*BestPath
= nullptr;
3513 typedef std::set
<const CXXMethodDecl
*> OverriderSetTy
;
3514 OverriderSetTy LastOverrides
;
3515 for (const FullPathTy
&SpecificPath
: FullPaths
) {
3516 assert(!SpecificPath
.empty());
3517 OverriderSetTy CurrentOverrides
;
3518 const CXXRecordDecl
*TopLevelRD
= SpecificPath
.begin()->getBase();
3519 // Find the distance from the start of the path to the subobject with the
3521 CharUnits BaseOffset
=
3522 getOffsetOfFullPath(Context
, TopLevelRD
, SpecificPath
);
3523 FinalOverriders
Overriders(TopLevelRD
, CharUnits::Zero(), TopLevelRD
);
3524 for (const CXXMethodDecl
*MD
: Info
.IntroducingObject
->methods()) {
3525 if (!MicrosoftVTableContext::hasVtableSlot(MD
))
3527 FinalOverriders::OverriderInfo OI
=
3528 Overriders
.getOverrider(MD
->getCanonicalDecl(), BaseOffset
);
3529 const CXXMethodDecl
*OverridingMethod
= OI
.Method
;
3530 // Only overriders which have a return adjustment introduce problematic
3532 if (ComputeReturnAdjustmentBaseOffset(Context
, OverridingMethod
, MD
)
3535 // It's possible that the overrider isn't in this path. If so, skip it
3536 // because this path didn't introduce it.
3537 const CXXRecordDecl
*OverridingParent
= OverridingMethod
->getParent();
3538 if (llvm::none_of(SpecificPath
, [&](const BaseSubobject
&BSO
) {
3539 return BSO
.getBase() == OverridingParent
;
3542 CurrentOverrides
.insert(OverridingMethod
);
3544 OverriderSetTy NewOverrides
=
3545 llvm::set_difference(CurrentOverrides
, LastOverrides
);
3546 if (NewOverrides
.empty())
3548 OverriderSetTy MissingOverrides
=
3549 llvm::set_difference(LastOverrides
, CurrentOverrides
);
3550 if (MissingOverrides
.empty()) {
3551 // This path is a strict improvement over the last path, let's use it.
3552 BestPath
= &SpecificPath
;
3553 std::swap(CurrentOverrides
, LastOverrides
);
3555 // This path introduces an overrider with a conflicting covariant thunk.
3556 DiagnosticsEngine
&Diags
= Context
.getDiagnostics();
3557 const CXXMethodDecl
*CovariantMD
= *NewOverrides
.begin();
3558 const CXXMethodDecl
*ConflictMD
= *MissingOverrides
.begin();
3559 Diags
.Report(RD
->getLocation(), diag::err_vftable_ambiguous_component
)
3561 Diags
.Report(CovariantMD
->getLocation(), diag::note_covariant_thunk
)
3563 Diags
.Report(ConflictMD
->getLocation(), diag::note_covariant_thunk
)
3567 // Go with the path that introduced the most covariant overrides. If there is
3568 // no such path, pick the first path.
3569 return BestPath
? BestPath
: &FullPaths
.front();
3572 static void computeFullPathsForVFTables(ASTContext
&Context
,
3573 const CXXRecordDecl
*RD
,
3574 VPtrInfoVector
&Paths
) {
3575 const ASTRecordLayout
&MostDerivedLayout
= Context
.getASTRecordLayout(RD
);
3576 FullPathTy FullPath
;
3577 std::list
<FullPathTy
> FullPaths
;
3578 for (const std::unique_ptr
<VPtrInfo
>& Info
: Paths
) {
3579 findPathsToSubobject(
3580 Context
, MostDerivedLayout
, RD
, CharUnits::Zero(),
3581 BaseSubobject(Info
->IntroducingObject
, Info
->FullOffsetInMDC
), FullPath
,
3584 removeRedundantPaths(FullPaths
);
3585 Info
->PathToIntroducingObject
.clear();
3586 if (const FullPathTy
*BestPath
=
3587 selectBestPath(Context
, RD
, *Info
, FullPaths
))
3588 for (const BaseSubobject
&BSO
: *BestPath
)
3589 Info
->PathToIntroducingObject
.push_back(BSO
.getBase());
3594 static bool vfptrIsEarlierInMDC(const ASTRecordLayout
&Layout
,
3595 const MethodVFTableLocation
&LHS
,
3596 const MethodVFTableLocation
&RHS
) {
3597 CharUnits L
= LHS
.VFPtrOffset
;
3598 CharUnits R
= RHS
.VFPtrOffset
;
3600 L
+= Layout
.getVBaseClassOffset(LHS
.VBase
);
3602 R
+= Layout
.getVBaseClassOffset(RHS
.VBase
);
3606 void MicrosoftVTableContext::computeVTableRelatedInformation(
3607 const CXXRecordDecl
*RD
) {
3608 assert(RD
->isDynamicClass());
3610 // Check if we've computed this information before.
3611 if (VFPtrLocations
.count(RD
))
3614 const VTableLayout::AddressPointsMapTy EmptyAddressPointsMap
;
3617 auto VFPtrs
= std::make_unique
<VPtrInfoVector
>();
3618 computeVTablePaths(/*ForVBTables=*/false, RD
, *VFPtrs
);
3619 computeFullPathsForVFTables(Context
, RD
, *VFPtrs
);
3620 VFPtrLocations
[RD
] = std::move(VFPtrs
);
3623 MethodVFTableLocationsTy NewMethodLocations
;
3624 for (const std::unique_ptr
<VPtrInfo
> &VFPtr
: *VFPtrLocations
[RD
]) {
3625 VFTableBuilder
Builder(*this, RD
, *VFPtr
);
3627 VFTableIdTy
id(RD
, VFPtr
->FullOffsetInMDC
);
3628 assert(VFTableLayouts
.count(id
) == 0);
3629 SmallVector
<VTableLayout::VTableThunkTy
, 1> VTableThunks(
3630 Builder
.vtable_thunks_begin(), Builder
.vtable_thunks_end());
3631 VFTableLayouts
[id
] = std::make_unique
<VTableLayout
>(
3632 ArrayRef
<size_t>{0}, Builder
.vtable_components(), VTableThunks
,
3633 EmptyAddressPointsMap
);
3634 Thunks
.insert(Builder
.thunks_begin(), Builder
.thunks_end());
3636 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(RD
);
3637 for (const auto &Loc
: Builder
.vtable_locations()) {
3638 auto Insert
= NewMethodLocations
.insert(Loc
);
3639 if (!Insert
.second
) {
3640 const MethodVFTableLocation
&NewLoc
= Loc
.second
;
3641 MethodVFTableLocation
&OldLoc
= Insert
.first
->second
;
3642 if (vfptrIsEarlierInMDC(Layout
, NewLoc
, OldLoc
))
3648 MethodVFTableLocations
.insert(NewMethodLocations
.begin(),
3649 NewMethodLocations
.end());
3650 if (Context
.getLangOpts().DumpVTableLayouts
)
3651 dumpMethodLocations(RD
, NewMethodLocations
, llvm::outs());
3654 void MicrosoftVTableContext::dumpMethodLocations(
3655 const CXXRecordDecl
*RD
, const MethodVFTableLocationsTy
&NewMethods
,
3657 // Compute the vtable indices for all the member functions.
3658 // Store them in a map keyed by the location so we'll get a sorted table.
3659 std::map
<MethodVFTableLocation
, std::string
> IndicesMap
;
3660 bool HasNonzeroOffset
= false;
3662 for (const auto &I
: NewMethods
) {
3663 const CXXMethodDecl
*MD
= cast
<const CXXMethodDecl
>(I
.first
.getDecl());
3664 assert(hasVtableSlot(MD
));
3666 std::string MethodName
= PredefinedExpr::ComputeName(
3667 PredefinedExpr::PrettyFunctionNoVirtual
, MD
);
3669 if (isa
<CXXDestructorDecl
>(MD
)) {
3670 IndicesMap
[I
.second
] = MethodName
+ " [scalar deleting]";
3672 IndicesMap
[I
.second
] = MethodName
;
3675 if (!I
.second
.VFPtrOffset
.isZero() || I
.second
.VBTableIndex
!= 0)
3676 HasNonzeroOffset
= true;
3679 // Print the vtable indices for all the member functions.
3680 if (!IndicesMap
.empty()) {
3681 Out
<< "VFTable indices for ";
3683 RD
->printQualifiedName(Out
);
3684 Out
<< "' (" << IndicesMap
.size()
3685 << (IndicesMap
.size() == 1 ? " entry" : " entries") << ").\n";
3687 CharUnits LastVFPtrOffset
= CharUnits::fromQuantity(-1);
3688 uint64_t LastVBIndex
= 0;
3689 for (const auto &I
: IndicesMap
) {
3690 CharUnits VFPtrOffset
= I
.first
.VFPtrOffset
;
3691 uint64_t VBIndex
= I
.first
.VBTableIndex
;
3692 if (HasNonzeroOffset
&&
3693 (VFPtrOffset
!= LastVFPtrOffset
|| VBIndex
!= LastVBIndex
)) {
3694 assert(VBIndex
> LastVBIndex
|| VFPtrOffset
> LastVFPtrOffset
);
3695 Out
<< " -- accessible via ";
3697 Out
<< "vbtable index " << VBIndex
<< ", ";
3698 Out
<< "vfptr at offset " << VFPtrOffset
.getQuantity() << " --\n";
3699 LastVFPtrOffset
= VFPtrOffset
;
3700 LastVBIndex
= VBIndex
;
3703 uint64_t VTableIndex
= I
.first
.Index
;
3704 const std::string
&MethodName
= I
.second
;
3705 Out
<< llvm::format("%4" PRIu64
" | ", VTableIndex
) << MethodName
<< '\n';
3713 const VirtualBaseInfo
&MicrosoftVTableContext::computeVBTableRelatedInformation(
3714 const CXXRecordDecl
*RD
) {
3715 VirtualBaseInfo
*VBI
;
3718 // Get or create a VBI for RD. Don't hold a reference to the DenseMap cell,
3719 // as it may be modified and rehashed under us.
3720 std::unique_ptr
<VirtualBaseInfo
> &Entry
= VBaseInfo
[RD
];
3723 Entry
= std::make_unique
<VirtualBaseInfo
>();
3727 computeVTablePaths(/*ForVBTables=*/true, RD
, VBI
->VBPtrPaths
);
3729 // First, see if the Derived class shared the vbptr with a non-virtual base.
3730 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(RD
);
3731 if (const CXXRecordDecl
*VBPtrBase
= Layout
.getBaseSharingVBPtr()) {
3732 // If the Derived class shares the vbptr with a non-virtual base, the shared
3733 // virtual bases come first so that the layout is the same.
3734 const VirtualBaseInfo
&BaseInfo
=
3735 computeVBTableRelatedInformation(VBPtrBase
);
3736 VBI
->VBTableIndices
.insert(BaseInfo
.VBTableIndices
.begin(),
3737 BaseInfo
.VBTableIndices
.end());
3740 // New vbases are added to the end of the vbtable.
3741 // Skip the self entry and vbases visited in the non-virtual base, if any.
3742 unsigned VBTableIndex
= 1 + VBI
->VBTableIndices
.size();
3743 for (const auto &VB
: RD
->vbases()) {
3744 const CXXRecordDecl
*CurVBase
= VB
.getType()->getAsCXXRecordDecl();
3745 if (!VBI
->VBTableIndices
.count(CurVBase
))
3746 VBI
->VBTableIndices
[CurVBase
] = VBTableIndex
++;
3752 unsigned MicrosoftVTableContext::getVBTableIndex(const CXXRecordDecl
*Derived
,
3753 const CXXRecordDecl
*VBase
) {
3754 const VirtualBaseInfo
&VBInfo
= computeVBTableRelatedInformation(Derived
);
3755 assert(VBInfo
.VBTableIndices
.count(VBase
));
3756 return VBInfo
.VBTableIndices
.find(VBase
)->second
;
3759 const VPtrInfoVector
&
3760 MicrosoftVTableContext::enumerateVBTables(const CXXRecordDecl
*RD
) {
3761 return computeVBTableRelatedInformation(RD
).VBPtrPaths
;
3764 const VPtrInfoVector
&
3765 MicrosoftVTableContext::getVFPtrOffsets(const CXXRecordDecl
*RD
) {
3766 computeVTableRelatedInformation(RD
);
3768 assert(VFPtrLocations
.count(RD
) && "Couldn't find vfptr locations");
3769 return *VFPtrLocations
[RD
];
3772 const VTableLayout
&
3773 MicrosoftVTableContext::getVFTableLayout(const CXXRecordDecl
*RD
,
3774 CharUnits VFPtrOffset
) {
3775 computeVTableRelatedInformation(RD
);
3777 VFTableIdTy
id(RD
, VFPtrOffset
);
3778 assert(VFTableLayouts
.count(id
) && "Couldn't find a VFTable at this offset");
3779 return *VFTableLayouts
[id
];
3782 MethodVFTableLocation
3783 MicrosoftVTableContext::getMethodVFTableLocation(GlobalDecl GD
) {
3784 assert(hasVtableSlot(cast
<CXXMethodDecl
>(GD
.getDecl())) &&
3785 "Only use this method for virtual methods or dtors");
3786 if (isa
<CXXDestructorDecl
>(GD
.getDecl()))
3787 assert(GD
.getDtorType() == Dtor_Deleting
);
3789 GD
= GD
.getCanonicalDecl();
3791 MethodVFTableLocationsTy::iterator I
= MethodVFTableLocations
.find(GD
);
3792 if (I
!= MethodVFTableLocations
.end())
3795 const CXXRecordDecl
*RD
= cast
<CXXMethodDecl
>(GD
.getDecl())->getParent();
3797 computeVTableRelatedInformation(RD
);
3799 I
= MethodVFTableLocations
.find(GD
);
3800 assert(I
!= MethodVFTableLocations
.end() && "Did not find index!");