xref: /aosp_15_r20/external/clang/lib/AST/VTableBuilder.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===--- VTableBuilder.cpp - C++ vtable layout builder --------------------===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // This contains code dealing with generation of the layout of virtual tables.
11*67e74705SXin Li //
12*67e74705SXin Li //===----------------------------------------------------------------------===//
13*67e74705SXin Li 
14*67e74705SXin Li #include "clang/AST/VTableBuilder.h"
15*67e74705SXin Li #include "clang/AST/ASTContext.h"
16*67e74705SXin Li #include "clang/AST/ASTDiagnostic.h"
17*67e74705SXin Li #include "clang/AST/CXXInheritance.h"
18*67e74705SXin Li #include "clang/AST/RecordLayout.h"
19*67e74705SXin Li #include "clang/Basic/TargetInfo.h"
20*67e74705SXin Li #include "llvm/ADT/SetOperations.h"
21*67e74705SXin Li #include "llvm/ADT/SmallPtrSet.h"
22*67e74705SXin Li #include "llvm/Support/Format.h"
23*67e74705SXin Li #include "llvm/Support/raw_ostream.h"
24*67e74705SXin Li #include <algorithm>
25*67e74705SXin Li #include <cstdio>
26*67e74705SXin Li 
27*67e74705SXin Li using namespace clang;
28*67e74705SXin Li 
29*67e74705SXin Li #define DUMP_OVERRIDERS 0
30*67e74705SXin Li 
31*67e74705SXin Li namespace {
32*67e74705SXin Li 
33*67e74705SXin Li /// BaseOffset - Represents an offset from a derived class to a direct or
34*67e74705SXin Li /// indirect base class.
35*67e74705SXin Li struct BaseOffset {
36*67e74705SXin Li   /// DerivedClass - The derived class.
37*67e74705SXin Li   const CXXRecordDecl *DerivedClass;
38*67e74705SXin Li 
39*67e74705SXin Li   /// VirtualBase - If the path from the derived class to the base class
40*67e74705SXin Li   /// involves virtual base classes, this holds the declaration of the last
41*67e74705SXin Li   /// virtual base in this path (i.e. closest to the base class).
42*67e74705SXin Li   const CXXRecordDecl *VirtualBase;
43*67e74705SXin Li 
44*67e74705SXin Li   /// NonVirtualOffset - The offset from the derived class to the base class.
45*67e74705SXin Li   /// (Or the offset from the virtual base class to the base class, if the
46*67e74705SXin Li   /// path from the derived class to the base class involves a virtual base
47*67e74705SXin Li   /// class.
48*67e74705SXin Li   CharUnits NonVirtualOffset;
49*67e74705SXin Li 
BaseOffset__anon965a958e0111::BaseOffset50*67e74705SXin Li   BaseOffset() : DerivedClass(nullptr), VirtualBase(nullptr),
51*67e74705SXin Li                  NonVirtualOffset(CharUnits::Zero()) { }
BaseOffset__anon965a958e0111::BaseOffset52*67e74705SXin Li   BaseOffset(const CXXRecordDecl *DerivedClass,
53*67e74705SXin Li              const CXXRecordDecl *VirtualBase, CharUnits NonVirtualOffset)
54*67e74705SXin Li     : DerivedClass(DerivedClass), VirtualBase(VirtualBase),
55*67e74705SXin Li     NonVirtualOffset(NonVirtualOffset) { }
56*67e74705SXin Li 
isEmpty__anon965a958e0111::BaseOffset57*67e74705SXin Li   bool isEmpty() const { return NonVirtualOffset.isZero() && !VirtualBase; }
58*67e74705SXin Li };
59*67e74705SXin Li 
60*67e74705SXin Li /// FinalOverriders - Contains the final overrider member functions for all
61*67e74705SXin Li /// member functions in the base subobjects of a class.
62*67e74705SXin Li class FinalOverriders {
63*67e74705SXin Li public:
64*67e74705SXin Li   /// OverriderInfo - Information about a final overrider.
65*67e74705SXin Li   struct OverriderInfo {
66*67e74705SXin Li     /// Method - The method decl of the overrider.
67*67e74705SXin Li     const CXXMethodDecl *Method;
68*67e74705SXin Li 
69*67e74705SXin Li     /// VirtualBase - The virtual base class subobject of this overrider.
70*67e74705SXin Li     /// Note that this records the closest derived virtual base class subobject.
71*67e74705SXin Li     const CXXRecordDecl *VirtualBase;
72*67e74705SXin Li 
73*67e74705SXin Li     /// Offset - the base offset of the overrider's parent in the layout class.
74*67e74705SXin Li     CharUnits Offset;
75*67e74705SXin Li 
OverriderInfo__anon965a958e0111::FinalOverriders::OverriderInfo76*67e74705SXin Li     OverriderInfo() : Method(nullptr), VirtualBase(nullptr),
77*67e74705SXin Li                       Offset(CharUnits::Zero()) { }
78*67e74705SXin Li   };
79*67e74705SXin Li 
80*67e74705SXin Li private:
81*67e74705SXin Li   /// MostDerivedClass - The most derived class for which the final overriders
82*67e74705SXin Li   /// are stored.
83*67e74705SXin Li   const CXXRecordDecl *MostDerivedClass;
84*67e74705SXin Li 
85*67e74705SXin Li   /// MostDerivedClassOffset - If we're building final overriders for a
86*67e74705SXin Li   /// construction vtable, this holds the offset from the layout class to the
87*67e74705SXin Li   /// most derived class.
88*67e74705SXin Li   const CharUnits MostDerivedClassOffset;
89*67e74705SXin Li 
90*67e74705SXin Li   /// LayoutClass - The class we're using for layout information. Will be
91*67e74705SXin Li   /// different than the most derived class if the final overriders are for a
92*67e74705SXin Li   /// construction vtable.
93*67e74705SXin Li   const CXXRecordDecl *LayoutClass;
94*67e74705SXin Li 
95*67e74705SXin Li   ASTContext &Context;
96*67e74705SXin Li 
97*67e74705SXin Li   /// MostDerivedClassLayout - the AST record layout of the most derived class.
98*67e74705SXin Li   const ASTRecordLayout &MostDerivedClassLayout;
99*67e74705SXin Li 
100*67e74705SXin Li   /// MethodBaseOffsetPairTy - Uniquely identifies a member function
101*67e74705SXin Li   /// in a base subobject.
102*67e74705SXin Li   typedef std::pair<const CXXMethodDecl *, CharUnits> MethodBaseOffsetPairTy;
103*67e74705SXin Li 
104*67e74705SXin Li   typedef llvm::DenseMap<MethodBaseOffsetPairTy,
105*67e74705SXin Li                          OverriderInfo> OverridersMapTy;
106*67e74705SXin Li 
107*67e74705SXin Li   /// OverridersMap - The final overriders for all virtual member functions of
108*67e74705SXin Li   /// all the base subobjects of the most derived class.
109*67e74705SXin Li   OverridersMapTy OverridersMap;
110*67e74705SXin Li 
111*67e74705SXin Li   /// SubobjectsToOffsetsMapTy - A mapping from a base subobject (represented
112*67e74705SXin Li   /// as a record decl and a subobject number) and its offsets in the most
113*67e74705SXin Li   /// derived class as well as the layout class.
114*67e74705SXin Li   typedef llvm::DenseMap<std::pair<const CXXRecordDecl *, unsigned>,
115*67e74705SXin Li                          CharUnits> SubobjectOffsetMapTy;
116*67e74705SXin Li 
117*67e74705SXin Li   typedef llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCountMapTy;
118*67e74705SXin Li 
119*67e74705SXin Li   /// ComputeBaseOffsets - Compute the offsets for all base subobjects of the
120*67e74705SXin Li   /// given base.
121*67e74705SXin Li   void ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
122*67e74705SXin Li                           CharUnits OffsetInLayoutClass,
123*67e74705SXin Li                           SubobjectOffsetMapTy &SubobjectOffsets,
124*67e74705SXin Li                           SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
125*67e74705SXin Li                           SubobjectCountMapTy &SubobjectCounts);
126*67e74705SXin Li 
127*67e74705SXin Li   typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
128*67e74705SXin Li 
129*67e74705SXin Li   /// dump - dump the final overriders for a base subobject, and all its direct
130*67e74705SXin Li   /// and indirect base subobjects.
131*67e74705SXin Li   void dump(raw_ostream &Out, BaseSubobject Base,
132*67e74705SXin Li             VisitedVirtualBasesSetTy& VisitedVirtualBases);
133*67e74705SXin Li 
134*67e74705SXin Li public:
135*67e74705SXin Li   FinalOverriders(const CXXRecordDecl *MostDerivedClass,
136*67e74705SXin Li                   CharUnits MostDerivedClassOffset,
137*67e74705SXin Li                   const CXXRecordDecl *LayoutClass);
138*67e74705SXin Li 
139*67e74705SXin Li   /// getOverrider - Get the final overrider for the given method declaration in
140*67e74705SXin Li   /// the subobject with the given base offset.
getOverrider(const CXXMethodDecl * MD,CharUnits BaseOffset) const141*67e74705SXin Li   OverriderInfo getOverrider(const CXXMethodDecl *MD,
142*67e74705SXin Li                              CharUnits BaseOffset) const {
143*67e74705SXin Li     assert(OverridersMap.count(std::make_pair(MD, BaseOffset)) &&
144*67e74705SXin Li            "Did not find overrider!");
145*67e74705SXin Li 
146*67e74705SXin Li     return OverridersMap.lookup(std::make_pair(MD, BaseOffset));
147*67e74705SXin Li   }
148*67e74705SXin Li 
149*67e74705SXin Li   /// dump - dump the final overriders.
dump()150*67e74705SXin Li   void dump() {
151*67e74705SXin Li     VisitedVirtualBasesSetTy VisitedVirtualBases;
152*67e74705SXin Li     dump(llvm::errs(), BaseSubobject(MostDerivedClass, CharUnits::Zero()),
153*67e74705SXin Li          VisitedVirtualBases);
154*67e74705SXin Li   }
155*67e74705SXin Li 
156*67e74705SXin Li };
157*67e74705SXin Li 
FinalOverriders(const CXXRecordDecl * MostDerivedClass,CharUnits MostDerivedClassOffset,const CXXRecordDecl * LayoutClass)158*67e74705SXin Li FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass,
159*67e74705SXin Li                                  CharUnits MostDerivedClassOffset,
160*67e74705SXin Li                                  const CXXRecordDecl *LayoutClass)
161*67e74705SXin Li   : MostDerivedClass(MostDerivedClass),
162*67e74705SXin Li   MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass),
163*67e74705SXin Li   Context(MostDerivedClass->getASTContext()),
164*67e74705SXin Li   MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)) {
165*67e74705SXin Li 
166*67e74705SXin Li   // Compute base offsets.
167*67e74705SXin Li   SubobjectOffsetMapTy SubobjectOffsets;
168*67e74705SXin Li   SubobjectOffsetMapTy SubobjectLayoutClassOffsets;
169*67e74705SXin Li   SubobjectCountMapTy SubobjectCounts;
170*67e74705SXin Li   ComputeBaseOffsets(BaseSubobject(MostDerivedClass, CharUnits::Zero()),
171*67e74705SXin Li                      /*IsVirtual=*/false,
172*67e74705SXin Li                      MostDerivedClassOffset,
173*67e74705SXin Li                      SubobjectOffsets, SubobjectLayoutClassOffsets,
174*67e74705SXin Li                      SubobjectCounts);
175*67e74705SXin Li 
176*67e74705SXin Li   // Get the final overriders.
177*67e74705SXin Li   CXXFinalOverriderMap FinalOverriders;
178*67e74705SXin Li   MostDerivedClass->getFinalOverriders(FinalOverriders);
179*67e74705SXin Li 
180*67e74705SXin Li   for (const auto &Overrider : FinalOverriders) {
181*67e74705SXin Li     const CXXMethodDecl *MD = Overrider.first;
182*67e74705SXin Li     const OverridingMethods &Methods = Overrider.second;
183*67e74705SXin Li 
184*67e74705SXin Li     for (const auto &M : Methods) {
185*67e74705SXin Li       unsigned SubobjectNumber = M.first;
186*67e74705SXin Li       assert(SubobjectOffsets.count(std::make_pair(MD->getParent(),
187*67e74705SXin Li                                                    SubobjectNumber)) &&
188*67e74705SXin Li              "Did not find subobject offset!");
189*67e74705SXin Li 
190*67e74705SXin Li       CharUnits BaseOffset = SubobjectOffsets[std::make_pair(MD->getParent(),
191*67e74705SXin Li                                                             SubobjectNumber)];
192*67e74705SXin Li 
193*67e74705SXin Li       assert(M.second.size() == 1 && "Final overrider is not unique!");
194*67e74705SXin Li       const UniqueVirtualMethod &Method = M.second.front();
195*67e74705SXin Li 
196*67e74705SXin Li       const CXXRecordDecl *OverriderRD = Method.Method->getParent();
197*67e74705SXin Li       assert(SubobjectLayoutClassOffsets.count(
198*67e74705SXin Li              std::make_pair(OverriderRD, Method.Subobject))
199*67e74705SXin Li              && "Did not find subobject offset!");
200*67e74705SXin Li       CharUnits OverriderOffset =
201*67e74705SXin Li         SubobjectLayoutClassOffsets[std::make_pair(OverriderRD,
202*67e74705SXin Li                                                    Method.Subobject)];
203*67e74705SXin Li 
204*67e74705SXin Li       OverriderInfo& Overrider = OverridersMap[std::make_pair(MD, BaseOffset)];
205*67e74705SXin Li       assert(!Overrider.Method && "Overrider should not exist yet!");
206*67e74705SXin Li 
207*67e74705SXin Li       Overrider.Offset = OverriderOffset;
208*67e74705SXin Li       Overrider.Method = Method.Method;
209*67e74705SXin Li       Overrider.VirtualBase = Method.InVirtualSubobject;
210*67e74705SXin Li     }
211*67e74705SXin Li   }
212*67e74705SXin Li 
213*67e74705SXin Li #if DUMP_OVERRIDERS
214*67e74705SXin Li   // And dump them (for now).
215*67e74705SXin Li   dump();
216*67e74705SXin Li #endif
217*67e74705SXin Li }
218*67e74705SXin Li 
ComputeBaseOffset(const ASTContext & Context,const CXXRecordDecl * DerivedRD,const CXXBasePath & Path)219*67e74705SXin Li static BaseOffset ComputeBaseOffset(const ASTContext &Context,
220*67e74705SXin Li                                     const CXXRecordDecl *DerivedRD,
221*67e74705SXin Li                                     const CXXBasePath &Path) {
222*67e74705SXin Li   CharUnits NonVirtualOffset = CharUnits::Zero();
223*67e74705SXin Li 
224*67e74705SXin Li   unsigned NonVirtualStart = 0;
225*67e74705SXin Li   const CXXRecordDecl *VirtualBase = nullptr;
226*67e74705SXin Li 
227*67e74705SXin Li   // First, look for the virtual base class.
228*67e74705SXin Li   for (int I = Path.size(), E = 0; I != E; --I) {
229*67e74705SXin Li     const CXXBasePathElement &Element = Path[I - 1];
230*67e74705SXin Li 
231*67e74705SXin Li     if (Element.Base->isVirtual()) {
232*67e74705SXin Li       NonVirtualStart = I;
233*67e74705SXin Li       QualType VBaseType = Element.Base->getType();
234*67e74705SXin Li       VirtualBase = VBaseType->getAsCXXRecordDecl();
235*67e74705SXin Li       break;
236*67e74705SXin Li     }
237*67e74705SXin Li   }
238*67e74705SXin Li 
239*67e74705SXin Li   // Now compute the non-virtual offset.
240*67e74705SXin Li   for (unsigned I = NonVirtualStart, E = Path.size(); I != E; ++I) {
241*67e74705SXin Li     const CXXBasePathElement &Element = Path[I];
242*67e74705SXin Li 
243*67e74705SXin Li     // Check the base class offset.
244*67e74705SXin Li     const ASTRecordLayout &Layout = Context.getASTRecordLayout(Element.Class);
245*67e74705SXin Li 
246*67e74705SXin Li     const CXXRecordDecl *Base = Element.Base->getType()->getAsCXXRecordDecl();
247*67e74705SXin Li 
248*67e74705SXin Li     NonVirtualOffset += Layout.getBaseClassOffset(Base);
249*67e74705SXin Li   }
250*67e74705SXin Li 
251*67e74705SXin Li   // FIXME: This should probably use CharUnits or something. Maybe we should
252*67e74705SXin Li   // even change the base offsets in ASTRecordLayout to be specified in
253*67e74705SXin Li   // CharUnits.
254*67e74705SXin Li   return BaseOffset(DerivedRD, VirtualBase, NonVirtualOffset);
255*67e74705SXin Li 
256*67e74705SXin Li }
257*67e74705SXin Li 
ComputeBaseOffset(const ASTContext & Context,const CXXRecordDecl * BaseRD,const CXXRecordDecl * DerivedRD)258*67e74705SXin Li static BaseOffset ComputeBaseOffset(const ASTContext &Context,
259*67e74705SXin Li                                     const CXXRecordDecl *BaseRD,
260*67e74705SXin Li                                     const CXXRecordDecl *DerivedRD) {
261*67e74705SXin Li   CXXBasePaths Paths(/*FindAmbiguities=*/false,
262*67e74705SXin Li                      /*RecordPaths=*/true, /*DetectVirtual=*/false);
263*67e74705SXin Li 
264*67e74705SXin Li   if (!DerivedRD->isDerivedFrom(BaseRD, Paths))
265*67e74705SXin Li     llvm_unreachable("Class must be derived from the passed in base class!");
266*67e74705SXin Li 
267*67e74705SXin Li   return ComputeBaseOffset(Context, DerivedRD, Paths.front());
268*67e74705SXin Li }
269*67e74705SXin Li 
270*67e74705SXin Li static BaseOffset
ComputeReturnAdjustmentBaseOffset(ASTContext & Context,const CXXMethodDecl * DerivedMD,const CXXMethodDecl * BaseMD)271*67e74705SXin Li ComputeReturnAdjustmentBaseOffset(ASTContext &Context,
272*67e74705SXin Li                                   const CXXMethodDecl *DerivedMD,
273*67e74705SXin Li                                   const CXXMethodDecl *BaseMD) {
274*67e74705SXin Li   const FunctionType *BaseFT = BaseMD->getType()->getAs<FunctionType>();
275*67e74705SXin Li   const FunctionType *DerivedFT = DerivedMD->getType()->getAs<FunctionType>();
276*67e74705SXin Li 
277*67e74705SXin Li   // Canonicalize the return types.
278*67e74705SXin Li   CanQualType CanDerivedReturnType =
279*67e74705SXin Li       Context.getCanonicalType(DerivedFT->getReturnType());
280*67e74705SXin Li   CanQualType CanBaseReturnType =
281*67e74705SXin Li       Context.getCanonicalType(BaseFT->getReturnType());
282*67e74705SXin Li 
283*67e74705SXin Li   assert(CanDerivedReturnType->getTypeClass() ==
284*67e74705SXin Li          CanBaseReturnType->getTypeClass() &&
285*67e74705SXin Li          "Types must have same type class!");
286*67e74705SXin Li 
287*67e74705SXin Li   if (CanDerivedReturnType == CanBaseReturnType) {
288*67e74705SXin Li     // No adjustment needed.
289*67e74705SXin Li     return BaseOffset();
290*67e74705SXin Li   }
291*67e74705SXin Li 
292*67e74705SXin Li   if (isa<ReferenceType>(CanDerivedReturnType)) {
293*67e74705SXin Li     CanDerivedReturnType =
294*67e74705SXin Li       CanDerivedReturnType->getAs<ReferenceType>()->getPointeeType();
295*67e74705SXin Li     CanBaseReturnType =
296*67e74705SXin Li       CanBaseReturnType->getAs<ReferenceType>()->getPointeeType();
297*67e74705SXin Li   } else if (isa<PointerType>(CanDerivedReturnType)) {
298*67e74705SXin Li     CanDerivedReturnType =
299*67e74705SXin Li       CanDerivedReturnType->getAs<PointerType>()->getPointeeType();
300*67e74705SXin Li     CanBaseReturnType =
301*67e74705SXin Li       CanBaseReturnType->getAs<PointerType>()->getPointeeType();
302*67e74705SXin Li   } else {
303*67e74705SXin Li     llvm_unreachable("Unexpected return type!");
304*67e74705SXin Li   }
305*67e74705SXin Li 
306*67e74705SXin Li   // We need to compare unqualified types here; consider
307*67e74705SXin Li   //   const T *Base::foo();
308*67e74705SXin Li   //   T *Derived::foo();
309*67e74705SXin Li   if (CanDerivedReturnType.getUnqualifiedType() ==
310*67e74705SXin Li       CanBaseReturnType.getUnqualifiedType()) {
311*67e74705SXin Li     // No adjustment needed.
312*67e74705SXin Li     return BaseOffset();
313*67e74705SXin Li   }
314*67e74705SXin Li 
315*67e74705SXin Li   const CXXRecordDecl *DerivedRD =
316*67e74705SXin Li     cast<CXXRecordDecl>(cast<RecordType>(CanDerivedReturnType)->getDecl());
317*67e74705SXin Li 
318*67e74705SXin Li   const CXXRecordDecl *BaseRD =
319*67e74705SXin Li     cast<CXXRecordDecl>(cast<RecordType>(CanBaseReturnType)->getDecl());
320*67e74705SXin Li 
321*67e74705SXin Li   return ComputeBaseOffset(Context, BaseRD, DerivedRD);
322*67e74705SXin Li }
323*67e74705SXin Li 
324*67e74705SXin Li void
ComputeBaseOffsets(BaseSubobject Base,bool IsVirtual,CharUnits OffsetInLayoutClass,SubobjectOffsetMapTy & SubobjectOffsets,SubobjectOffsetMapTy & SubobjectLayoutClassOffsets,SubobjectCountMapTy & SubobjectCounts)325*67e74705SXin Li FinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
326*67e74705SXin Li                               CharUnits OffsetInLayoutClass,
327*67e74705SXin Li                               SubobjectOffsetMapTy &SubobjectOffsets,
328*67e74705SXin Li                               SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
329*67e74705SXin Li                               SubobjectCountMapTy &SubobjectCounts) {
330*67e74705SXin Li   const CXXRecordDecl *RD = Base.getBase();
331*67e74705SXin Li 
332*67e74705SXin Li   unsigned SubobjectNumber = 0;
333*67e74705SXin Li   if (!IsVirtual)
334*67e74705SXin Li     SubobjectNumber = ++SubobjectCounts[RD];
335*67e74705SXin Li 
336*67e74705SXin Li   // Set up the subobject to offset mapping.
337*67e74705SXin Li   assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber))
338*67e74705SXin Li          && "Subobject offset already exists!");
339*67e74705SXin Li   assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber))
340*67e74705SXin Li          && "Subobject offset already exists!");
341*67e74705SXin Li 
342*67e74705SXin Li   SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] = Base.getBaseOffset();
343*67e74705SXin Li   SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] =
344*67e74705SXin Li     OffsetInLayoutClass;
345*67e74705SXin Li 
346*67e74705SXin Li   // Traverse our bases.
347*67e74705SXin Li   for (const auto &B : RD->bases()) {
348*67e74705SXin Li     const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
349*67e74705SXin Li 
350*67e74705SXin Li     CharUnits BaseOffset;
351*67e74705SXin Li     CharUnits BaseOffsetInLayoutClass;
352*67e74705SXin Li     if (B.isVirtual()) {
353*67e74705SXin Li       // Check if we've visited this virtual base before.
354*67e74705SXin Li       if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0)))
355*67e74705SXin Li         continue;
356*67e74705SXin Li 
357*67e74705SXin Li       const ASTRecordLayout &LayoutClassLayout =
358*67e74705SXin Li         Context.getASTRecordLayout(LayoutClass);
359*67e74705SXin Li 
360*67e74705SXin Li       BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
361*67e74705SXin Li       BaseOffsetInLayoutClass =
362*67e74705SXin Li         LayoutClassLayout.getVBaseClassOffset(BaseDecl);
363*67e74705SXin Li     } else {
364*67e74705SXin Li       const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
365*67e74705SXin Li       CharUnits Offset = Layout.getBaseClassOffset(BaseDecl);
366*67e74705SXin Li 
367*67e74705SXin Li       BaseOffset = Base.getBaseOffset() + Offset;
368*67e74705SXin Li       BaseOffsetInLayoutClass = OffsetInLayoutClass + Offset;
369*67e74705SXin Li     }
370*67e74705SXin Li 
371*67e74705SXin Li     ComputeBaseOffsets(BaseSubobject(BaseDecl, BaseOffset),
372*67e74705SXin Li                        B.isVirtual(), BaseOffsetInLayoutClass,
373*67e74705SXin Li                        SubobjectOffsets, SubobjectLayoutClassOffsets,
374*67e74705SXin Li                        SubobjectCounts);
375*67e74705SXin Li   }
376*67e74705SXin Li }
377*67e74705SXin Li 
dump(raw_ostream & Out,BaseSubobject Base,VisitedVirtualBasesSetTy & VisitedVirtualBases)378*67e74705SXin Li void FinalOverriders::dump(raw_ostream &Out, BaseSubobject Base,
379*67e74705SXin Li                            VisitedVirtualBasesSetTy &VisitedVirtualBases) {
380*67e74705SXin Li   const CXXRecordDecl *RD = Base.getBase();
381*67e74705SXin Li   const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
382*67e74705SXin Li 
383*67e74705SXin Li   for (const auto &B : RD->bases()) {
384*67e74705SXin Li     const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
385*67e74705SXin Li 
386*67e74705SXin Li     // Ignore bases that don't have any virtual member functions.
387*67e74705SXin Li     if (!BaseDecl->isPolymorphic())
388*67e74705SXin Li       continue;
389*67e74705SXin Li 
390*67e74705SXin Li     CharUnits BaseOffset;
391*67e74705SXin Li     if (B.isVirtual()) {
392*67e74705SXin Li       if (!VisitedVirtualBases.insert(BaseDecl).second) {
393*67e74705SXin Li         // We've visited this base before.
394*67e74705SXin Li         continue;
395*67e74705SXin Li       }
396*67e74705SXin Li 
397*67e74705SXin Li       BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
398*67e74705SXin Li     } else {
399*67e74705SXin Li       BaseOffset = Layout.getBaseClassOffset(BaseDecl) + Base.getBaseOffset();
400*67e74705SXin Li     }
401*67e74705SXin Li 
402*67e74705SXin Li     dump(Out, BaseSubobject(BaseDecl, BaseOffset), VisitedVirtualBases);
403*67e74705SXin Li   }
404*67e74705SXin Li 
405*67e74705SXin Li   Out << "Final overriders for (";
406*67e74705SXin Li   RD->printQualifiedName(Out);
407*67e74705SXin Li   Out << ", ";
408*67e74705SXin Li   Out << Base.getBaseOffset().getQuantity() << ")\n";
409*67e74705SXin Li 
410*67e74705SXin Li   // Now dump the overriders for this base subobject.
411*67e74705SXin Li   for (const auto *MD : RD->methods()) {
412*67e74705SXin Li     if (!MD->isVirtual())
413*67e74705SXin Li       continue;
414*67e74705SXin Li     MD = MD->getCanonicalDecl();
415*67e74705SXin Li 
416*67e74705SXin Li     OverriderInfo Overrider = getOverrider(MD, Base.getBaseOffset());
417*67e74705SXin Li 
418*67e74705SXin Li     Out << "  ";
419*67e74705SXin Li     MD->printQualifiedName(Out);
420*67e74705SXin Li     Out << " - (";
421*67e74705SXin Li     Overrider.Method->printQualifiedName(Out);
422*67e74705SXin Li     Out << ", " << Overrider.Offset.getQuantity() << ')';
423*67e74705SXin Li 
424*67e74705SXin Li     BaseOffset Offset;
425*67e74705SXin Li     if (!Overrider.Method->isPure())
426*67e74705SXin Li       Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
427*67e74705SXin Li 
428*67e74705SXin Li     if (!Offset.isEmpty()) {
429*67e74705SXin Li       Out << " [ret-adj: ";
430*67e74705SXin Li       if (Offset.VirtualBase) {
431*67e74705SXin Li         Offset.VirtualBase->printQualifiedName(Out);
432*67e74705SXin Li         Out << " vbase, ";
433*67e74705SXin Li       }
434*67e74705SXin Li 
435*67e74705SXin Li       Out << Offset.NonVirtualOffset.getQuantity() << " nv]";
436*67e74705SXin Li     }
437*67e74705SXin Li 
438*67e74705SXin Li     Out << "\n";
439*67e74705SXin Li   }
440*67e74705SXin Li }
441*67e74705SXin Li 
442*67e74705SXin Li /// VCallOffsetMap - Keeps track of vcall offsets when building a vtable.
443*67e74705SXin Li struct VCallOffsetMap {
444*67e74705SXin Li 
445*67e74705SXin Li   typedef std::pair<const CXXMethodDecl *, CharUnits> MethodAndOffsetPairTy;
446*67e74705SXin Li 
447*67e74705SXin Li   /// Offsets - Keeps track of methods and their offsets.
448*67e74705SXin Li   // FIXME: This should be a real map and not a vector.
449*67e74705SXin Li   SmallVector<MethodAndOffsetPairTy, 16> Offsets;
450*67e74705SXin Li 
451*67e74705SXin Li   /// MethodsCanShareVCallOffset - Returns whether two virtual member functions
452*67e74705SXin Li   /// can share the same vcall offset.
453*67e74705SXin Li   static bool MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
454*67e74705SXin Li                                          const CXXMethodDecl *RHS);
455*67e74705SXin Li 
456*67e74705SXin Li public:
457*67e74705SXin Li   /// AddVCallOffset - Adds a vcall offset to the map. Returns true if the
458*67e74705SXin Li   /// add was successful, or false if there was already a member function with
459*67e74705SXin Li   /// the same signature in the map.
460*67e74705SXin Li   bool AddVCallOffset(const CXXMethodDecl *MD, CharUnits OffsetOffset);
461*67e74705SXin Li 
462*67e74705SXin Li   /// getVCallOffsetOffset - Returns the vcall offset offset (relative to the
463*67e74705SXin Li   /// vtable address point) for the given virtual member function.
464*67e74705SXin Li   CharUnits getVCallOffsetOffset(const CXXMethodDecl *MD);
465*67e74705SXin Li 
466*67e74705SXin Li   // empty - Return whether the offset map is empty or not.
empty__anon965a958e0111::VCallOffsetMap467*67e74705SXin Li   bool empty() const { return Offsets.empty(); }
468*67e74705SXin Li };
469*67e74705SXin Li 
HasSameVirtualSignature(const CXXMethodDecl * LHS,const CXXMethodDecl * RHS)470*67e74705SXin Li static bool HasSameVirtualSignature(const CXXMethodDecl *LHS,
471*67e74705SXin Li                                     const CXXMethodDecl *RHS) {
472*67e74705SXin Li   const FunctionProtoType *LT =
473*67e74705SXin Li     cast<FunctionProtoType>(LHS->getType().getCanonicalType());
474*67e74705SXin Li   const FunctionProtoType *RT =
475*67e74705SXin Li     cast<FunctionProtoType>(RHS->getType().getCanonicalType());
476*67e74705SXin Li 
477*67e74705SXin Li   // Fast-path matches in the canonical types.
478*67e74705SXin Li   if (LT == RT) return true;
479*67e74705SXin Li 
480*67e74705SXin Li   // Force the signatures to match.  We can't rely on the overrides
481*67e74705SXin Li   // list here because there isn't necessarily an inheritance
482*67e74705SXin Li   // relationship between the two methods.
483*67e74705SXin Li   if (LT->getTypeQuals() != RT->getTypeQuals())
484*67e74705SXin Li     return false;
485*67e74705SXin Li   return LT->getParamTypes() == RT->getParamTypes();
486*67e74705SXin Li }
487*67e74705SXin Li 
MethodsCanShareVCallOffset(const CXXMethodDecl * LHS,const CXXMethodDecl * RHS)488*67e74705SXin Li bool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
489*67e74705SXin Li                                                 const CXXMethodDecl *RHS) {
490*67e74705SXin Li   assert(LHS->isVirtual() && "LHS must be virtual!");
491*67e74705SXin Li   assert(RHS->isVirtual() && "LHS must be virtual!");
492*67e74705SXin Li 
493*67e74705SXin Li   // A destructor can share a vcall offset with another destructor.
494*67e74705SXin Li   if (isa<CXXDestructorDecl>(LHS))
495*67e74705SXin Li     return isa<CXXDestructorDecl>(RHS);
496*67e74705SXin Li 
497*67e74705SXin Li   // FIXME: We need to check more things here.
498*67e74705SXin Li 
499*67e74705SXin Li   // The methods must have the same name.
500*67e74705SXin Li   DeclarationName LHSName = LHS->getDeclName();
501*67e74705SXin Li   DeclarationName RHSName = RHS->getDeclName();
502*67e74705SXin Li   if (LHSName != RHSName)
503*67e74705SXin Li     return false;
504*67e74705SXin Li 
505*67e74705SXin Li   // And the same signatures.
506*67e74705SXin Li   return HasSameVirtualSignature(LHS, RHS);
507*67e74705SXin Li }
508*67e74705SXin Li 
AddVCallOffset(const CXXMethodDecl * MD,CharUnits OffsetOffset)509*67e74705SXin Li bool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl *MD,
510*67e74705SXin Li                                     CharUnits OffsetOffset) {
511*67e74705SXin Li   // Check if we can reuse an offset.
512*67e74705SXin Li   for (const auto &OffsetPair : Offsets) {
513*67e74705SXin Li     if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
514*67e74705SXin Li       return false;
515*67e74705SXin Li   }
516*67e74705SXin Li 
517*67e74705SXin Li   // Add the offset.
518*67e74705SXin Li   Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset));
519*67e74705SXin Li   return true;
520*67e74705SXin Li }
521*67e74705SXin Li 
getVCallOffsetOffset(const CXXMethodDecl * MD)522*67e74705SXin Li CharUnits VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) {
523*67e74705SXin Li   // Look for an offset.
524*67e74705SXin Li   for (const auto &OffsetPair : Offsets) {
525*67e74705SXin Li     if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
526*67e74705SXin Li       return OffsetPair.second;
527*67e74705SXin Li   }
528*67e74705SXin Li 
529*67e74705SXin Li   llvm_unreachable("Should always find a vcall offset offset!");
530*67e74705SXin Li }
531*67e74705SXin Li 
532*67e74705SXin Li /// VCallAndVBaseOffsetBuilder - Class for building vcall and vbase offsets.
533*67e74705SXin Li class VCallAndVBaseOffsetBuilder {
534*67e74705SXin Li public:
535*67e74705SXin Li   typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
536*67e74705SXin Li     VBaseOffsetOffsetsMapTy;
537*67e74705SXin Li 
538*67e74705SXin Li private:
539*67e74705SXin Li   /// MostDerivedClass - The most derived class for which we're building vcall
540*67e74705SXin Li   /// and vbase offsets.
541*67e74705SXin Li   const CXXRecordDecl *MostDerivedClass;
542*67e74705SXin Li 
543*67e74705SXin Li   /// LayoutClass - The class we're using for layout information. Will be
544*67e74705SXin Li   /// different than the most derived class if we're building a construction
545*67e74705SXin Li   /// vtable.
546*67e74705SXin Li   const CXXRecordDecl *LayoutClass;
547*67e74705SXin Li 
548*67e74705SXin Li   /// Context - The ASTContext which we will use for layout information.
549*67e74705SXin Li   ASTContext &Context;
550*67e74705SXin Li 
551*67e74705SXin Li   /// Components - vcall and vbase offset components
552*67e74705SXin Li   typedef SmallVector<VTableComponent, 64> VTableComponentVectorTy;
553*67e74705SXin Li   VTableComponentVectorTy Components;
554*67e74705SXin Li 
555*67e74705SXin Li   /// VisitedVirtualBases - Visited virtual bases.
556*67e74705SXin Li   llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
557*67e74705SXin Li 
558*67e74705SXin Li   /// VCallOffsets - Keeps track of vcall offsets.
559*67e74705SXin Li   VCallOffsetMap VCallOffsets;
560*67e74705SXin Li 
561*67e74705SXin Li 
562*67e74705SXin Li   /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets,
563*67e74705SXin Li   /// relative to the address point.
564*67e74705SXin Li   VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
565*67e74705SXin Li 
566*67e74705SXin Li   /// FinalOverriders - The final overriders of the most derived class.
567*67e74705SXin Li   /// (Can be null when we're not building a vtable of the most derived class).
568*67e74705SXin Li   const FinalOverriders *Overriders;
569*67e74705SXin Li 
570*67e74705SXin Li   /// AddVCallAndVBaseOffsets - Add vcall offsets and vbase offsets for the
571*67e74705SXin Li   /// given base subobject.
572*67e74705SXin Li   void AddVCallAndVBaseOffsets(BaseSubobject Base, bool BaseIsVirtual,
573*67e74705SXin Li                                CharUnits RealBaseOffset);
574*67e74705SXin Li 
575*67e74705SXin Li   /// AddVCallOffsets - Add vcall offsets for the given base subobject.
576*67e74705SXin Li   void AddVCallOffsets(BaseSubobject Base, CharUnits VBaseOffset);
577*67e74705SXin Li 
578*67e74705SXin Li   /// AddVBaseOffsets - Add vbase offsets for the given class.
579*67e74705SXin Li   void AddVBaseOffsets(const CXXRecordDecl *Base,
580*67e74705SXin Li                        CharUnits OffsetInLayoutClass);
581*67e74705SXin Li 
582*67e74705SXin Li   /// getCurrentOffsetOffset - Get the current vcall or vbase offset offset in
583*67e74705SXin Li   /// chars, relative to the vtable address point.
584*67e74705SXin Li   CharUnits getCurrentOffsetOffset() const;
585*67e74705SXin Li 
586*67e74705SXin Li public:
VCallAndVBaseOffsetBuilder(const CXXRecordDecl * MostDerivedClass,const CXXRecordDecl * LayoutClass,const FinalOverriders * Overriders,BaseSubobject Base,bool BaseIsVirtual,CharUnits OffsetInLayoutClass)587*67e74705SXin Li   VCallAndVBaseOffsetBuilder(const CXXRecordDecl *MostDerivedClass,
588*67e74705SXin Li                              const CXXRecordDecl *LayoutClass,
589*67e74705SXin Li                              const FinalOverriders *Overriders,
590*67e74705SXin Li                              BaseSubobject Base, bool BaseIsVirtual,
591*67e74705SXin Li                              CharUnits OffsetInLayoutClass)
592*67e74705SXin Li     : MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass),
593*67e74705SXin Li     Context(MostDerivedClass->getASTContext()), Overriders(Overriders) {
594*67e74705SXin Li 
595*67e74705SXin Li     // Add vcall and vbase offsets.
596*67e74705SXin Li     AddVCallAndVBaseOffsets(Base, BaseIsVirtual, OffsetInLayoutClass);
597*67e74705SXin Li   }
598*67e74705SXin Li 
599*67e74705SXin Li   /// Methods for iterating over the components.
600*67e74705SXin Li   typedef VTableComponentVectorTy::const_reverse_iterator const_iterator;
components_begin() const601*67e74705SXin Li   const_iterator components_begin() const { return Components.rbegin(); }
components_end() const602*67e74705SXin Li   const_iterator components_end() const { return Components.rend(); }
603*67e74705SXin Li 
getVCallOffsets() const604*67e74705SXin Li   const VCallOffsetMap &getVCallOffsets() const { return VCallOffsets; }
getVBaseOffsetOffsets() const605*67e74705SXin Li   const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const {
606*67e74705SXin Li     return VBaseOffsetOffsets;
607*67e74705SXin Li   }
608*67e74705SXin Li };
609*67e74705SXin Li 
610*67e74705SXin Li void
AddVCallAndVBaseOffsets(BaseSubobject Base,bool BaseIsVirtual,CharUnits RealBaseOffset)611*67e74705SXin Li VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base,
612*67e74705SXin Li                                                     bool BaseIsVirtual,
613*67e74705SXin Li                                                     CharUnits RealBaseOffset) {
614*67e74705SXin Li   const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base.getBase());
615*67e74705SXin Li 
616*67e74705SXin Li   // Itanium C++ ABI 2.5.2:
617*67e74705SXin Li   //   ..in classes sharing a virtual table with a primary base class, the vcall
618*67e74705SXin Li   //   and vbase offsets added by the derived class all come before the vcall
619*67e74705SXin Li   //   and vbase offsets required by the base class, so that the latter may be
620*67e74705SXin Li   //   laid out as required by the base class without regard to additions from
621*67e74705SXin Li   //   the derived class(es).
622*67e74705SXin Li 
623*67e74705SXin Li   // (Since we're emitting the vcall and vbase offsets in reverse order, we'll
624*67e74705SXin Li   // emit them for the primary base first).
625*67e74705SXin Li   if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
626*67e74705SXin Li     bool PrimaryBaseIsVirtual = Layout.isPrimaryBaseVirtual();
627*67e74705SXin Li 
628*67e74705SXin Li     CharUnits PrimaryBaseOffset;
629*67e74705SXin Li 
630*67e74705SXin Li     // Get the base offset of the primary base.
631*67e74705SXin Li     if (PrimaryBaseIsVirtual) {
632*67e74705SXin Li       assert(Layout.getVBaseClassOffset(PrimaryBase).isZero() &&
633*67e74705SXin Li              "Primary vbase should have a zero offset!");
634*67e74705SXin Li 
635*67e74705SXin Li       const ASTRecordLayout &MostDerivedClassLayout =
636*67e74705SXin Li         Context.getASTRecordLayout(MostDerivedClass);
637*67e74705SXin Li 
638*67e74705SXin Li       PrimaryBaseOffset =
639*67e74705SXin Li         MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
640*67e74705SXin Li     } else {
641*67e74705SXin Li       assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
642*67e74705SXin Li              "Primary base should have a zero offset!");
643*67e74705SXin Li 
644*67e74705SXin Li       PrimaryBaseOffset = Base.getBaseOffset();
645*67e74705SXin Li     }
646*67e74705SXin Li 
647*67e74705SXin Li     AddVCallAndVBaseOffsets(
648*67e74705SXin Li       BaseSubobject(PrimaryBase,PrimaryBaseOffset),
649*67e74705SXin Li       PrimaryBaseIsVirtual, RealBaseOffset);
650*67e74705SXin Li   }
651*67e74705SXin Li 
652*67e74705SXin Li   AddVBaseOffsets(Base.getBase(), RealBaseOffset);
653*67e74705SXin Li 
654*67e74705SXin Li   // We only want to add vcall offsets for virtual bases.
655*67e74705SXin Li   if (BaseIsVirtual)
656*67e74705SXin Li     AddVCallOffsets(Base, RealBaseOffset);
657*67e74705SXin Li }
658*67e74705SXin Li 
getCurrentOffsetOffset() const659*67e74705SXin Li CharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset() const {
660*67e74705SXin Li   // OffsetIndex is the index of this vcall or vbase offset, relative to the
661*67e74705SXin Li   // vtable address point. (We subtract 3 to account for the information just
662*67e74705SXin Li   // above the address point, the RTTI info, the offset to top, and the
663*67e74705SXin Li   // vcall offset itself).
664*67e74705SXin Li   int64_t OffsetIndex = -(int64_t)(3 + Components.size());
665*67e74705SXin Li 
666*67e74705SXin Li   CharUnits PointerWidth =
667*67e74705SXin Li     Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
668*67e74705SXin Li   CharUnits OffsetOffset = PointerWidth * OffsetIndex;
669*67e74705SXin Li   return OffsetOffset;
670*67e74705SXin Li }
671*67e74705SXin Li 
AddVCallOffsets(BaseSubobject Base,CharUnits VBaseOffset)672*67e74705SXin Li void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
673*67e74705SXin Li                                                  CharUnits VBaseOffset) {
674*67e74705SXin Li   const CXXRecordDecl *RD = Base.getBase();
675*67e74705SXin Li   const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
676*67e74705SXin Li 
677*67e74705SXin Li   const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
678*67e74705SXin Li 
679*67e74705SXin Li   // Handle the primary base first.
680*67e74705SXin Li   // We only want to add vcall offsets if the base is non-virtual; a virtual
681*67e74705SXin Li   // primary base will have its vcall and vbase offsets emitted already.
682*67e74705SXin Li   if (PrimaryBase && !Layout.isPrimaryBaseVirtual()) {
683*67e74705SXin Li     // Get the base offset of the primary base.
684*67e74705SXin Li     assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
685*67e74705SXin Li            "Primary base should have a zero offset!");
686*67e74705SXin Li 
687*67e74705SXin Li     AddVCallOffsets(BaseSubobject(PrimaryBase, Base.getBaseOffset()),
688*67e74705SXin Li                     VBaseOffset);
689*67e74705SXin Li   }
690*67e74705SXin Li 
691*67e74705SXin Li   // Add the vcall offsets.
692*67e74705SXin Li   for (const auto *MD : RD->methods()) {
693*67e74705SXin Li     if (!MD->isVirtual())
694*67e74705SXin Li       continue;
695*67e74705SXin Li     MD = MD->getCanonicalDecl();
696*67e74705SXin Li 
697*67e74705SXin Li     CharUnits OffsetOffset = getCurrentOffsetOffset();
698*67e74705SXin Li 
699*67e74705SXin Li     // Don't add a vcall offset if we already have one for this member function
700*67e74705SXin Li     // signature.
701*67e74705SXin Li     if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
702*67e74705SXin Li       continue;
703*67e74705SXin Li 
704*67e74705SXin Li     CharUnits Offset = CharUnits::Zero();
705*67e74705SXin Li 
706*67e74705SXin Li     if (Overriders) {
707*67e74705SXin Li       // Get the final overrider.
708*67e74705SXin Li       FinalOverriders::OverriderInfo Overrider =
709*67e74705SXin Li         Overriders->getOverrider(MD, Base.getBaseOffset());
710*67e74705SXin Li 
711*67e74705SXin Li       /// The vcall offset is the offset from the virtual base to the object
712*67e74705SXin Li       /// where the function was overridden.
713*67e74705SXin Li       Offset = Overrider.Offset - VBaseOffset;
714*67e74705SXin Li     }
715*67e74705SXin Li 
716*67e74705SXin Li     Components.push_back(
717*67e74705SXin Li       VTableComponent::MakeVCallOffset(Offset));
718*67e74705SXin Li   }
719*67e74705SXin Li 
720*67e74705SXin Li   // And iterate over all non-virtual bases (ignoring the primary base).
721*67e74705SXin Li   for (const auto &B : RD->bases()) {
722*67e74705SXin Li     if (B.isVirtual())
723*67e74705SXin Li       continue;
724*67e74705SXin Li 
725*67e74705SXin Li     const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
726*67e74705SXin Li     if (BaseDecl == PrimaryBase)
727*67e74705SXin Li       continue;
728*67e74705SXin Li 
729*67e74705SXin Li     // Get the base offset of this base.
730*67e74705SXin Li     CharUnits BaseOffset = Base.getBaseOffset() +
731*67e74705SXin Li       Layout.getBaseClassOffset(BaseDecl);
732*67e74705SXin Li 
733*67e74705SXin Li     AddVCallOffsets(BaseSubobject(BaseDecl, BaseOffset),
734*67e74705SXin Li                     VBaseOffset);
735*67e74705SXin Li   }
736*67e74705SXin Li }
737*67e74705SXin Li 
738*67e74705SXin Li void
AddVBaseOffsets(const CXXRecordDecl * RD,CharUnits OffsetInLayoutClass)739*67e74705SXin Li VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
740*67e74705SXin Li                                             CharUnits OffsetInLayoutClass) {
741*67e74705SXin Li   const ASTRecordLayout &LayoutClassLayout =
742*67e74705SXin Li     Context.getASTRecordLayout(LayoutClass);
743*67e74705SXin Li 
744*67e74705SXin Li   // Add vbase offsets.
745*67e74705SXin Li   for (const auto &B : RD->bases()) {
746*67e74705SXin Li     const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
747*67e74705SXin Li 
748*67e74705SXin Li     // Check if this is a virtual base that we haven't visited before.
749*67e74705SXin Li     if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl).second) {
750*67e74705SXin Li       CharUnits Offset =
751*67e74705SXin Li         LayoutClassLayout.getVBaseClassOffset(BaseDecl) - OffsetInLayoutClass;
752*67e74705SXin Li 
753*67e74705SXin Li       // Add the vbase offset offset.
754*67e74705SXin Li       assert(!VBaseOffsetOffsets.count(BaseDecl) &&
755*67e74705SXin Li              "vbase offset offset already exists!");
756*67e74705SXin Li 
757*67e74705SXin Li       CharUnits VBaseOffsetOffset = getCurrentOffsetOffset();
758*67e74705SXin Li       VBaseOffsetOffsets.insert(
759*67e74705SXin Li           std::make_pair(BaseDecl, VBaseOffsetOffset));
760*67e74705SXin Li 
761*67e74705SXin Li       Components.push_back(
762*67e74705SXin Li           VTableComponent::MakeVBaseOffset(Offset));
763*67e74705SXin Li     }
764*67e74705SXin Li 
765*67e74705SXin Li     // Check the base class looking for more vbase offsets.
766*67e74705SXin Li     AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
767*67e74705SXin Li   }
768*67e74705SXin Li }
769*67e74705SXin Li 
770*67e74705SXin Li /// ItaniumVTableBuilder - Class for building vtable layout information.
771*67e74705SXin Li class ItaniumVTableBuilder {
772*67e74705SXin Li public:
773*67e74705SXin Li   /// PrimaryBasesSetVectorTy - A set vector of direct and indirect
774*67e74705SXin Li   /// primary bases.
775*67e74705SXin Li   typedef llvm::SmallSetVector<const CXXRecordDecl *, 8>
776*67e74705SXin Li     PrimaryBasesSetVectorTy;
777*67e74705SXin Li 
778*67e74705SXin Li   typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
779*67e74705SXin Li     VBaseOffsetOffsetsMapTy;
780*67e74705SXin Li 
781*67e74705SXin Li   typedef llvm::DenseMap<BaseSubobject, uint64_t>
782*67e74705SXin Li     AddressPointsMapTy;
783*67e74705SXin Li 
784*67e74705SXin Li   typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
785*67e74705SXin Li 
786*67e74705SXin Li private:
787*67e74705SXin Li   /// VTables - Global vtable information.
788*67e74705SXin Li   ItaniumVTableContext &VTables;
789*67e74705SXin Li 
790*67e74705SXin Li   /// MostDerivedClass - The most derived class for which we're building this
791*67e74705SXin Li   /// vtable.
792*67e74705SXin Li   const CXXRecordDecl *MostDerivedClass;
793*67e74705SXin Li 
794*67e74705SXin Li   /// MostDerivedClassOffset - If we're building a construction vtable, this
795*67e74705SXin Li   /// holds the offset from the layout class to the most derived class.
796*67e74705SXin Li   const CharUnits MostDerivedClassOffset;
797*67e74705SXin Li 
798*67e74705SXin Li   /// MostDerivedClassIsVirtual - Whether the most derived class is a virtual
799*67e74705SXin Li   /// base. (This only makes sense when building a construction vtable).
800*67e74705SXin Li   bool MostDerivedClassIsVirtual;
801*67e74705SXin Li 
802*67e74705SXin Li   /// LayoutClass - The class we're using for layout information. Will be
803*67e74705SXin Li   /// different than the most derived class if we're building a construction
804*67e74705SXin Li   /// vtable.
805*67e74705SXin Li   const CXXRecordDecl *LayoutClass;
806*67e74705SXin Li 
807*67e74705SXin Li   /// Context - The ASTContext which we will use for layout information.
808*67e74705SXin Li   ASTContext &Context;
809*67e74705SXin Li 
810*67e74705SXin Li   /// FinalOverriders - The final overriders of the most derived class.
811*67e74705SXin Li   const FinalOverriders Overriders;
812*67e74705SXin Li 
813*67e74705SXin Li   /// VCallOffsetsForVBases - Keeps track of vcall offsets for the virtual
814*67e74705SXin Li   /// bases in this vtable.
815*67e74705SXin Li   llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
816*67e74705SXin Li 
817*67e74705SXin Li   /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for
818*67e74705SXin Li   /// the most derived class.
819*67e74705SXin Li   VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
820*67e74705SXin Li 
821*67e74705SXin Li   /// Components - The components of the vtable being built.
822*67e74705SXin Li   SmallVector<VTableComponent, 64> Components;
823*67e74705SXin Li 
824*67e74705SXin Li   /// AddressPoints - Address points for the vtable being built.
825*67e74705SXin Li   AddressPointsMapTy AddressPoints;
826*67e74705SXin Li 
827*67e74705SXin Li   /// MethodInfo - Contains information about a method in a vtable.
828*67e74705SXin Li   /// (Used for computing 'this' pointer adjustment thunks.
829*67e74705SXin Li   struct MethodInfo {
830*67e74705SXin Li     /// BaseOffset - The base offset of this method.
831*67e74705SXin Li     const CharUnits BaseOffset;
832*67e74705SXin Li 
833*67e74705SXin Li     /// BaseOffsetInLayoutClass - The base offset in the layout class of this
834*67e74705SXin Li     /// method.
835*67e74705SXin Li     const CharUnits BaseOffsetInLayoutClass;
836*67e74705SXin Li 
837*67e74705SXin Li     /// VTableIndex - The index in the vtable that this method has.
838*67e74705SXin Li     /// (For destructors, this is the index of the complete destructor).
839*67e74705SXin Li     const uint64_t VTableIndex;
840*67e74705SXin Li 
MethodInfo__anon965a958e0111::ItaniumVTableBuilder::MethodInfo841*67e74705SXin Li     MethodInfo(CharUnits BaseOffset, CharUnits BaseOffsetInLayoutClass,
842*67e74705SXin Li                uint64_t VTableIndex)
843*67e74705SXin Li       : BaseOffset(BaseOffset),
844*67e74705SXin Li       BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
845*67e74705SXin Li       VTableIndex(VTableIndex) { }
846*67e74705SXin Li 
MethodInfo__anon965a958e0111::ItaniumVTableBuilder::MethodInfo847*67e74705SXin Li     MethodInfo()
848*67e74705SXin Li       : BaseOffset(CharUnits::Zero()),
849*67e74705SXin Li       BaseOffsetInLayoutClass(CharUnits::Zero()),
850*67e74705SXin Li       VTableIndex(0) { }
851*67e74705SXin Li   };
852*67e74705SXin Li 
853*67e74705SXin Li   typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
854*67e74705SXin Li 
855*67e74705SXin Li   /// MethodInfoMap - The information for all methods in the vtable we're
856*67e74705SXin Li   /// currently building.
857*67e74705SXin Li   MethodInfoMapTy MethodInfoMap;
858*67e74705SXin Li 
859*67e74705SXin Li   /// MethodVTableIndices - Contains the index (relative to the vtable address
860*67e74705SXin Li   /// point) where the function pointer for a virtual function is stored.
861*67e74705SXin Li   MethodVTableIndicesTy MethodVTableIndices;
862*67e74705SXin Li 
863*67e74705SXin Li   typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
864*67e74705SXin Li 
865*67e74705SXin Li   /// VTableThunks - The thunks by vtable index in the vtable currently being
866*67e74705SXin Li   /// built.
867*67e74705SXin Li   VTableThunksMapTy VTableThunks;
868*67e74705SXin Li 
869*67e74705SXin Li   typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
870*67e74705SXin Li   typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
871*67e74705SXin Li 
872*67e74705SXin Li   /// Thunks - A map that contains all the thunks needed for all methods in the
873*67e74705SXin Li   /// most derived class for which the vtable is currently being built.
874*67e74705SXin Li   ThunksMapTy Thunks;
875*67e74705SXin Li 
876*67e74705SXin Li   /// AddThunk - Add a thunk for the given method.
877*67e74705SXin Li   void AddThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk);
878*67e74705SXin Li 
879*67e74705SXin Li   /// ComputeThisAdjustments - Compute the 'this' pointer adjustments for the
880*67e74705SXin Li   /// part of the vtable we're currently building.
881*67e74705SXin Li   void ComputeThisAdjustments();
882*67e74705SXin Li 
883*67e74705SXin Li   typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
884*67e74705SXin Li 
885*67e74705SXin Li   /// PrimaryVirtualBases - All known virtual bases who are a primary base of
886*67e74705SXin Li   /// some other base.
887*67e74705SXin Li   VisitedVirtualBasesSetTy PrimaryVirtualBases;
888*67e74705SXin Li 
889*67e74705SXin Li   /// ComputeReturnAdjustment - Compute the return adjustment given a return
890*67e74705SXin Li   /// adjustment base offset.
891*67e74705SXin Li   ReturnAdjustment ComputeReturnAdjustment(BaseOffset Offset);
892*67e74705SXin Li 
893*67e74705SXin Li   /// ComputeThisAdjustmentBaseOffset - Compute the base offset for adjusting
894*67e74705SXin Li   /// the 'this' pointer from the base subobject to the derived subobject.
895*67e74705SXin Li   BaseOffset ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
896*67e74705SXin Li                                              BaseSubobject Derived) const;
897*67e74705SXin Li 
898*67e74705SXin Li   /// ComputeThisAdjustment - Compute the 'this' pointer adjustment for the
899*67e74705SXin Li   /// given virtual member function, its offset in the layout class and its
900*67e74705SXin Li   /// final overrider.
901*67e74705SXin Li   ThisAdjustment
902*67e74705SXin Li   ComputeThisAdjustment(const CXXMethodDecl *MD,
903*67e74705SXin Li                         CharUnits BaseOffsetInLayoutClass,
904*67e74705SXin Li                         FinalOverriders::OverriderInfo Overrider);
905*67e74705SXin Li 
906*67e74705SXin Li   /// AddMethod - Add a single virtual member function to the vtable
907*67e74705SXin Li   /// components vector.
908*67e74705SXin Li   void AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment);
909*67e74705SXin Li 
910*67e74705SXin Li   /// IsOverriderUsed - Returns whether the overrider will ever be used in this
911*67e74705SXin Li   /// part of the vtable.
912*67e74705SXin Li   ///
913*67e74705SXin Li   /// Itanium C++ ABI 2.5.2:
914*67e74705SXin Li   ///
915*67e74705SXin Li   ///   struct A { virtual void f(); };
916*67e74705SXin Li   ///   struct B : virtual public A { int i; };
917*67e74705SXin Li   ///   struct C : virtual public A { int j; };
918*67e74705SXin Li   ///   struct D : public B, public C {};
919*67e74705SXin Li   ///
920*67e74705SXin Li   ///   When B and C are declared, A is a primary base in each case, so although
921*67e74705SXin Li   ///   vcall offsets are allocated in the A-in-B and A-in-C vtables, no this
922*67e74705SXin Li   ///   adjustment is required and no thunk is generated. However, inside D
923*67e74705SXin Li   ///   objects, A is no longer a primary base of C, so if we allowed calls to
924*67e74705SXin Li   ///   C::f() to use the copy of A's vtable in the C subobject, we would need
925*67e74705SXin Li   ///   to adjust this from C* to B::A*, which would require a third-party
926*67e74705SXin Li   ///   thunk. Since we require that a call to C::f() first convert to A*,
927*67e74705SXin Li   ///   C-in-D's copy of A's vtable is never referenced, so this is not
928*67e74705SXin Li   ///   necessary.
929*67e74705SXin Li   bool IsOverriderUsed(const CXXMethodDecl *Overrider,
930*67e74705SXin Li                        CharUnits BaseOffsetInLayoutClass,
931*67e74705SXin Li                        const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
932*67e74705SXin Li                        CharUnits FirstBaseOffsetInLayoutClass) const;
933*67e74705SXin Li 
934*67e74705SXin Li 
935*67e74705SXin Li   /// AddMethods - Add the methods of this base subobject and all its
936*67e74705SXin Li   /// primary bases to the vtable components vector.
937*67e74705SXin Li   void AddMethods(BaseSubobject Base, CharUnits BaseOffsetInLayoutClass,
938*67e74705SXin Li                   const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
939*67e74705SXin Li                   CharUnits FirstBaseOffsetInLayoutClass,
940*67e74705SXin Li                   PrimaryBasesSetVectorTy &PrimaryBases);
941*67e74705SXin Li 
942*67e74705SXin Li   // LayoutVTable - Layout the vtable for the given base class, including its
943*67e74705SXin Li   // secondary vtables and any vtables for virtual bases.
944*67e74705SXin Li   void LayoutVTable();
945*67e74705SXin Li 
946*67e74705SXin Li   /// LayoutPrimaryAndSecondaryVTables - Layout the primary vtable for the
947*67e74705SXin Li   /// given base subobject, as well as all its secondary vtables.
948*67e74705SXin Li   ///
949*67e74705SXin Li   /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
950*67e74705SXin Li   /// or a direct or indirect base of a virtual base.
951*67e74705SXin Li   ///
952*67e74705SXin Li   /// \param BaseIsVirtualInLayoutClass - Whether the base subobject is virtual
953*67e74705SXin Li   /// in the layout class.
954*67e74705SXin Li   void LayoutPrimaryAndSecondaryVTables(BaseSubobject Base,
955*67e74705SXin Li                                         bool BaseIsMorallyVirtual,
956*67e74705SXin Li                                         bool BaseIsVirtualInLayoutClass,
957*67e74705SXin Li                                         CharUnits OffsetInLayoutClass);
958*67e74705SXin Li 
959*67e74705SXin Li   /// LayoutSecondaryVTables - Layout the secondary vtables for the given base
960*67e74705SXin Li   /// subobject.
961*67e74705SXin Li   ///
962*67e74705SXin Li   /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
963*67e74705SXin Li   /// or a direct or indirect base of a virtual base.
964*67e74705SXin Li   void LayoutSecondaryVTables(BaseSubobject Base, bool BaseIsMorallyVirtual,
965*67e74705SXin Li                               CharUnits OffsetInLayoutClass);
966*67e74705SXin Li 
967*67e74705SXin Li   /// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this
968*67e74705SXin Li   /// class hierarchy.
969*67e74705SXin Li   void DeterminePrimaryVirtualBases(const CXXRecordDecl *RD,
970*67e74705SXin Li                                     CharUnits OffsetInLayoutClass,
971*67e74705SXin Li                                     VisitedVirtualBasesSetTy &VBases);
972*67e74705SXin Li 
973*67e74705SXin Li   /// LayoutVTablesForVirtualBases - Layout vtables for all virtual bases of the
974*67e74705SXin Li   /// given base (excluding any primary bases).
975*67e74705SXin Li   void LayoutVTablesForVirtualBases(const CXXRecordDecl *RD,
976*67e74705SXin Li                                     VisitedVirtualBasesSetTy &VBases);
977*67e74705SXin Li 
978*67e74705SXin Li   /// isBuildingConstructionVTable - Return whether this vtable builder is
979*67e74705SXin Li   /// building a construction vtable.
isBuildingConstructorVTable() const980*67e74705SXin Li   bool isBuildingConstructorVTable() const {
981*67e74705SXin Li     return MostDerivedClass != LayoutClass;
982*67e74705SXin Li   }
983*67e74705SXin Li 
984*67e74705SXin Li public:
ItaniumVTableBuilder(ItaniumVTableContext & VTables,const CXXRecordDecl * MostDerivedClass,CharUnits MostDerivedClassOffset,bool MostDerivedClassIsVirtual,const CXXRecordDecl * LayoutClass)985*67e74705SXin Li   ItaniumVTableBuilder(ItaniumVTableContext &VTables,
986*67e74705SXin Li                        const CXXRecordDecl *MostDerivedClass,
987*67e74705SXin Li                        CharUnits MostDerivedClassOffset,
988*67e74705SXin Li                        bool MostDerivedClassIsVirtual,
989*67e74705SXin Li                        const CXXRecordDecl *LayoutClass)
990*67e74705SXin Li       : VTables(VTables), MostDerivedClass(MostDerivedClass),
991*67e74705SXin Li         MostDerivedClassOffset(MostDerivedClassOffset),
992*67e74705SXin Li         MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
993*67e74705SXin Li         LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()),
994*67e74705SXin Li         Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) {
995*67e74705SXin Li     assert(!Context.getTargetInfo().getCXXABI().isMicrosoft());
996*67e74705SXin Li 
997*67e74705SXin Li     LayoutVTable();
998*67e74705SXin Li 
999*67e74705SXin Li     if (Context.getLangOpts().DumpVTableLayouts)
1000*67e74705SXin Li       dumpLayout(llvm::outs());
1001*67e74705SXin Li   }
1002*67e74705SXin Li 
getNumThunks() const1003*67e74705SXin Li   uint64_t getNumThunks() const {
1004*67e74705SXin Li     return Thunks.size();
1005*67e74705SXin Li   }
1006*67e74705SXin Li 
thunks_begin() const1007*67e74705SXin Li   ThunksMapTy::const_iterator thunks_begin() const {
1008*67e74705SXin Li     return Thunks.begin();
1009*67e74705SXin Li   }
1010*67e74705SXin Li 
thunks_end() const1011*67e74705SXin Li   ThunksMapTy::const_iterator thunks_end() const {
1012*67e74705SXin Li     return Thunks.end();
1013*67e74705SXin Li   }
1014*67e74705SXin Li 
getVBaseOffsetOffsets() const1015*67e74705SXin Li   const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const {
1016*67e74705SXin Li     return VBaseOffsetOffsets;
1017*67e74705SXin Li   }
1018*67e74705SXin Li 
getAddressPoints() const1019*67e74705SXin Li   const AddressPointsMapTy &getAddressPoints() const {
1020*67e74705SXin Li     return AddressPoints;
1021*67e74705SXin Li   }
1022*67e74705SXin Li 
vtable_indices_begin() const1023*67e74705SXin Li   MethodVTableIndicesTy::const_iterator vtable_indices_begin() const {
1024*67e74705SXin Li     return MethodVTableIndices.begin();
1025*67e74705SXin Li   }
1026*67e74705SXin Li 
vtable_indices_end() const1027*67e74705SXin Li   MethodVTableIndicesTy::const_iterator vtable_indices_end() const {
1028*67e74705SXin Li     return MethodVTableIndices.end();
1029*67e74705SXin Li   }
1030*67e74705SXin Li 
1031*67e74705SXin Li   /// getNumVTableComponents - Return the number of components in the vtable
1032*67e74705SXin Li   /// currently built.
getNumVTableComponents() const1033*67e74705SXin Li   uint64_t getNumVTableComponents() const {
1034*67e74705SXin Li     return Components.size();
1035*67e74705SXin Li   }
1036*67e74705SXin Li 
vtable_component_begin() const1037*67e74705SXin Li   const VTableComponent *vtable_component_begin() const {
1038*67e74705SXin Li     return Components.begin();
1039*67e74705SXin Li   }
1040*67e74705SXin Li 
vtable_component_end() const1041*67e74705SXin Li   const VTableComponent *vtable_component_end() const {
1042*67e74705SXin Li     return Components.end();
1043*67e74705SXin Li   }
1044*67e74705SXin Li 
address_points_begin() const1045*67e74705SXin Li   AddressPointsMapTy::const_iterator address_points_begin() const {
1046*67e74705SXin Li     return AddressPoints.begin();
1047*67e74705SXin Li   }
1048*67e74705SXin Li 
address_points_end() const1049*67e74705SXin Li   AddressPointsMapTy::const_iterator address_points_end() const {
1050*67e74705SXin Li     return AddressPoints.end();
1051*67e74705SXin Li   }
1052*67e74705SXin Li 
vtable_thunks_begin() const1053*67e74705SXin Li   VTableThunksMapTy::const_iterator vtable_thunks_begin() const {
1054*67e74705SXin Li     return VTableThunks.begin();
1055*67e74705SXin Li   }
1056*67e74705SXin Li 
vtable_thunks_end() const1057*67e74705SXin Li   VTableThunksMapTy::const_iterator vtable_thunks_end() const {
1058*67e74705SXin Li     return VTableThunks.end();
1059*67e74705SXin Li   }
1060*67e74705SXin Li 
1061*67e74705SXin Li   /// dumpLayout - Dump the vtable layout.
1062*67e74705SXin Li   void dumpLayout(raw_ostream&);
1063*67e74705SXin Li };
1064*67e74705SXin Li 
AddThunk(const CXXMethodDecl * MD,const ThunkInfo & Thunk)1065*67e74705SXin Li void ItaniumVTableBuilder::AddThunk(const CXXMethodDecl *MD,
1066*67e74705SXin Li                                     const ThunkInfo &Thunk) {
1067*67e74705SXin Li   assert(!isBuildingConstructorVTable() &&
1068*67e74705SXin Li          "Can't add thunks for construction vtable");
1069*67e74705SXin Li 
1070*67e74705SXin Li   SmallVectorImpl<ThunkInfo> &ThunksVector = Thunks[MD];
1071*67e74705SXin Li 
1072*67e74705SXin Li   // Check if we have this thunk already.
1073*67e74705SXin Li   if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
1074*67e74705SXin Li       ThunksVector.end())
1075*67e74705SXin Li     return;
1076*67e74705SXin Li 
1077*67e74705SXin Li   ThunksVector.push_back(Thunk);
1078*67e74705SXin Li }
1079*67e74705SXin Li 
1080*67e74705SXin Li typedef llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverriddenMethodsSetTy;
1081*67e74705SXin Li 
1082*67e74705SXin Li /// Visit all the methods overridden by the given method recursively,
1083*67e74705SXin Li /// in a depth-first pre-order. The Visitor's visitor method returns a bool
1084*67e74705SXin Li /// indicating whether to continue the recursion for the given overridden
1085*67e74705SXin Li /// method (i.e. returning false stops the iteration).
1086*67e74705SXin Li template <class VisitorTy>
1087*67e74705SXin Li static void
visitAllOverriddenMethods(const CXXMethodDecl * MD,VisitorTy & Visitor)1088*67e74705SXin Li visitAllOverriddenMethods(const CXXMethodDecl *MD, VisitorTy &Visitor) {
1089*67e74705SXin Li   assert(MD->isVirtual() && "Method is not virtual!");
1090*67e74705SXin Li 
1091*67e74705SXin Li   for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
1092*67e74705SXin Li        E = MD->end_overridden_methods(); I != E; ++I) {
1093*67e74705SXin Li     const CXXMethodDecl *OverriddenMD = *I;
1094*67e74705SXin Li     if (!Visitor(OverriddenMD))
1095*67e74705SXin Li       continue;
1096*67e74705SXin Li     visitAllOverriddenMethods(OverriddenMD, Visitor);
1097*67e74705SXin Li   }
1098*67e74705SXin Li }
1099*67e74705SXin Li 
1100*67e74705SXin Li /// ComputeAllOverriddenMethods - Given a method decl, will return a set of all
1101*67e74705SXin Li /// the overridden methods that the function decl overrides.
1102*67e74705SXin Li static void
ComputeAllOverriddenMethods(const CXXMethodDecl * MD,OverriddenMethodsSetTy & OverriddenMethods)1103*67e74705SXin Li ComputeAllOverriddenMethods(const CXXMethodDecl *MD,
1104*67e74705SXin Li                             OverriddenMethodsSetTy& OverriddenMethods) {
1105*67e74705SXin Li   auto OverriddenMethodsCollector = [&](const CXXMethodDecl *MD) {
1106*67e74705SXin Li     // Don't recurse on this method if we've already collected it.
1107*67e74705SXin Li     return OverriddenMethods.insert(MD).second;
1108*67e74705SXin Li   };
1109*67e74705SXin Li   visitAllOverriddenMethods(MD, OverriddenMethodsCollector);
1110*67e74705SXin Li }
1111*67e74705SXin Li 
ComputeThisAdjustments()1112*67e74705SXin Li void ItaniumVTableBuilder::ComputeThisAdjustments() {
1113*67e74705SXin Li   // Now go through the method info map and see if any of the methods need
1114*67e74705SXin Li   // 'this' pointer adjustments.
1115*67e74705SXin Li   for (const auto &MI : MethodInfoMap) {
1116*67e74705SXin Li     const CXXMethodDecl *MD = MI.first;
1117*67e74705SXin Li     const MethodInfo &MethodInfo = MI.second;
1118*67e74705SXin Li 
1119*67e74705SXin Li     // Ignore adjustments for unused function pointers.
1120*67e74705SXin Li     uint64_t VTableIndex = MethodInfo.VTableIndex;
1121*67e74705SXin Li     if (Components[VTableIndex].getKind() ==
1122*67e74705SXin Li         VTableComponent::CK_UnusedFunctionPointer)
1123*67e74705SXin Li       continue;
1124*67e74705SXin Li 
1125*67e74705SXin Li     // Get the final overrider for this method.
1126*67e74705SXin Li     FinalOverriders::OverriderInfo Overrider =
1127*67e74705SXin Li       Overriders.getOverrider(MD, MethodInfo.BaseOffset);
1128*67e74705SXin Li 
1129*67e74705SXin Li     // Check if we need an adjustment at all.
1130*67e74705SXin Li     if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) {
1131*67e74705SXin Li       // When a return thunk is needed by a derived class that overrides a
1132*67e74705SXin Li       // virtual base, gcc uses a virtual 'this' adjustment as well.
1133*67e74705SXin Li       // While the thunk itself might be needed by vtables in subclasses or
1134*67e74705SXin Li       // in construction vtables, there doesn't seem to be a reason for using
1135*67e74705SXin Li       // the thunk in this vtable. Still, we do so to match gcc.
1136*67e74705SXin Li       if (VTableThunks.lookup(VTableIndex).Return.isEmpty())
1137*67e74705SXin Li         continue;
1138*67e74705SXin Li     }
1139*67e74705SXin Li 
1140*67e74705SXin Li     ThisAdjustment ThisAdjustment =
1141*67e74705SXin Li       ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
1142*67e74705SXin Li 
1143*67e74705SXin Li     if (ThisAdjustment.isEmpty())
1144*67e74705SXin Li       continue;
1145*67e74705SXin Li 
1146*67e74705SXin Li     // Add it.
1147*67e74705SXin Li     VTableThunks[VTableIndex].This = ThisAdjustment;
1148*67e74705SXin Li 
1149*67e74705SXin Li     if (isa<CXXDestructorDecl>(MD)) {
1150*67e74705SXin Li       // Add an adjustment for the deleting destructor as well.
1151*67e74705SXin Li       VTableThunks[VTableIndex + 1].This = ThisAdjustment;
1152*67e74705SXin Li     }
1153*67e74705SXin Li   }
1154*67e74705SXin Li 
1155*67e74705SXin Li   /// Clear the method info map.
1156*67e74705SXin Li   MethodInfoMap.clear();
1157*67e74705SXin Li 
1158*67e74705SXin Li   if (isBuildingConstructorVTable()) {
1159*67e74705SXin Li     // We don't need to store thunk information for construction vtables.
1160*67e74705SXin Li     return;
1161*67e74705SXin Li   }
1162*67e74705SXin Li 
1163*67e74705SXin Li   for (const auto &TI : VTableThunks) {
1164*67e74705SXin Li     const VTableComponent &Component = Components[TI.first];
1165*67e74705SXin Li     const ThunkInfo &Thunk = TI.second;
1166*67e74705SXin Li     const CXXMethodDecl *MD;
1167*67e74705SXin Li 
1168*67e74705SXin Li     switch (Component.getKind()) {
1169*67e74705SXin Li     default:
1170*67e74705SXin Li       llvm_unreachable("Unexpected vtable component kind!");
1171*67e74705SXin Li     case VTableComponent::CK_FunctionPointer:
1172*67e74705SXin Li       MD = Component.getFunctionDecl();
1173*67e74705SXin Li       break;
1174*67e74705SXin Li     case VTableComponent::CK_CompleteDtorPointer:
1175*67e74705SXin Li       MD = Component.getDestructorDecl();
1176*67e74705SXin Li       break;
1177*67e74705SXin Li     case VTableComponent::CK_DeletingDtorPointer:
1178*67e74705SXin Li       // We've already added the thunk when we saw the complete dtor pointer.
1179*67e74705SXin Li       continue;
1180*67e74705SXin Li     }
1181*67e74705SXin Li 
1182*67e74705SXin Li     if (MD->getParent() == MostDerivedClass)
1183*67e74705SXin Li       AddThunk(MD, Thunk);
1184*67e74705SXin Li   }
1185*67e74705SXin Li }
1186*67e74705SXin Li 
1187*67e74705SXin Li ReturnAdjustment
ComputeReturnAdjustment(BaseOffset Offset)1188*67e74705SXin Li ItaniumVTableBuilder::ComputeReturnAdjustment(BaseOffset Offset) {
1189*67e74705SXin Li   ReturnAdjustment Adjustment;
1190*67e74705SXin Li 
1191*67e74705SXin Li   if (!Offset.isEmpty()) {
1192*67e74705SXin Li     if (Offset.VirtualBase) {
1193*67e74705SXin Li       // Get the virtual base offset offset.
1194*67e74705SXin Li       if (Offset.DerivedClass == MostDerivedClass) {
1195*67e74705SXin Li         // We can get the offset offset directly from our map.
1196*67e74705SXin Li         Adjustment.Virtual.Itanium.VBaseOffsetOffset =
1197*67e74705SXin Li           VBaseOffsetOffsets.lookup(Offset.VirtualBase).getQuantity();
1198*67e74705SXin Li       } else {
1199*67e74705SXin Li         Adjustment.Virtual.Itanium.VBaseOffsetOffset =
1200*67e74705SXin Li           VTables.getVirtualBaseOffsetOffset(Offset.DerivedClass,
1201*67e74705SXin Li                                              Offset.VirtualBase).getQuantity();
1202*67e74705SXin Li       }
1203*67e74705SXin Li     }
1204*67e74705SXin Li 
1205*67e74705SXin Li     Adjustment.NonVirtual = Offset.NonVirtualOffset.getQuantity();
1206*67e74705SXin Li   }
1207*67e74705SXin Li 
1208*67e74705SXin Li   return Adjustment;
1209*67e74705SXin Li }
1210*67e74705SXin Li 
ComputeThisAdjustmentBaseOffset(BaseSubobject Base,BaseSubobject Derived) const1211*67e74705SXin Li BaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
1212*67e74705SXin Li     BaseSubobject Base, BaseSubobject Derived) const {
1213*67e74705SXin Li   const CXXRecordDecl *BaseRD = Base.getBase();
1214*67e74705SXin Li   const CXXRecordDecl *DerivedRD = Derived.getBase();
1215*67e74705SXin Li 
1216*67e74705SXin Li   CXXBasePaths Paths(/*FindAmbiguities=*/true,
1217*67e74705SXin Li                      /*RecordPaths=*/true, /*DetectVirtual=*/true);
1218*67e74705SXin Li 
1219*67e74705SXin Li   if (!DerivedRD->isDerivedFrom(BaseRD, Paths))
1220*67e74705SXin Li     llvm_unreachable("Class must be derived from the passed in base class!");
1221*67e74705SXin Li 
1222*67e74705SXin Li   // We have to go through all the paths, and see which one leads us to the
1223*67e74705SXin Li   // right base subobject.
1224*67e74705SXin Li   for (const CXXBasePath &Path : Paths) {
1225*67e74705SXin Li     BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, Path);
1226*67e74705SXin Li 
1227*67e74705SXin Li     CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset;
1228*67e74705SXin Li 
1229*67e74705SXin Li     if (Offset.VirtualBase) {
1230*67e74705SXin Li       // If we have a virtual base class, the non-virtual offset is relative
1231*67e74705SXin Li       // to the virtual base class offset.
1232*67e74705SXin Li       const ASTRecordLayout &LayoutClassLayout =
1233*67e74705SXin Li         Context.getASTRecordLayout(LayoutClass);
1234*67e74705SXin Li 
1235*67e74705SXin Li       /// Get the virtual base offset, relative to the most derived class
1236*67e74705SXin Li       /// layout.
1237*67e74705SXin Li       OffsetToBaseSubobject +=
1238*67e74705SXin Li         LayoutClassLayout.getVBaseClassOffset(Offset.VirtualBase);
1239*67e74705SXin Li     } else {
1240*67e74705SXin Li       // Otherwise, the non-virtual offset is relative to the derived class
1241*67e74705SXin Li       // offset.
1242*67e74705SXin Li       OffsetToBaseSubobject += Derived.getBaseOffset();
1243*67e74705SXin Li     }
1244*67e74705SXin Li 
1245*67e74705SXin Li     // Check if this path gives us the right base subobject.
1246*67e74705SXin Li     if (OffsetToBaseSubobject == Base.getBaseOffset()) {
1247*67e74705SXin Li       // Since we're going from the base class _to_ the derived class, we'll
1248*67e74705SXin Li       // invert the non-virtual offset here.
1249*67e74705SXin Li       Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
1250*67e74705SXin Li       return Offset;
1251*67e74705SXin Li     }
1252*67e74705SXin Li   }
1253*67e74705SXin Li 
1254*67e74705SXin Li   return BaseOffset();
1255*67e74705SXin Li }
1256*67e74705SXin Li 
ComputeThisAdjustment(const CXXMethodDecl * MD,CharUnits BaseOffsetInLayoutClass,FinalOverriders::OverriderInfo Overrider)1257*67e74705SXin Li ThisAdjustment ItaniumVTableBuilder::ComputeThisAdjustment(
1258*67e74705SXin Li     const CXXMethodDecl *MD, CharUnits BaseOffsetInLayoutClass,
1259*67e74705SXin Li     FinalOverriders::OverriderInfo Overrider) {
1260*67e74705SXin Li   // Ignore adjustments for pure virtual member functions.
1261*67e74705SXin Li   if (Overrider.Method->isPure())
1262*67e74705SXin Li     return ThisAdjustment();
1263*67e74705SXin Li 
1264*67e74705SXin Li   BaseSubobject OverriddenBaseSubobject(MD->getParent(),
1265*67e74705SXin Li                                         BaseOffsetInLayoutClass);
1266*67e74705SXin Li 
1267*67e74705SXin Li   BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
1268*67e74705SXin Li                                        Overrider.Offset);
1269*67e74705SXin Li 
1270*67e74705SXin Li   // Compute the adjustment offset.
1271*67e74705SXin Li   BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
1272*67e74705SXin Li                                                       OverriderBaseSubobject);
1273*67e74705SXin Li   if (Offset.isEmpty())
1274*67e74705SXin Li     return ThisAdjustment();
1275*67e74705SXin Li 
1276*67e74705SXin Li   ThisAdjustment Adjustment;
1277*67e74705SXin Li 
1278*67e74705SXin Li   if (Offset.VirtualBase) {
1279*67e74705SXin Li     // Get the vcall offset map for this virtual base.
1280*67e74705SXin Li     VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
1281*67e74705SXin Li 
1282*67e74705SXin Li     if (VCallOffsets.empty()) {
1283*67e74705SXin Li       // We don't have vcall offsets for this virtual base, go ahead and
1284*67e74705SXin Li       // build them.
1285*67e74705SXin Li       VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass,
1286*67e74705SXin Li                                          /*FinalOverriders=*/nullptr,
1287*67e74705SXin Li                                          BaseSubobject(Offset.VirtualBase,
1288*67e74705SXin Li                                                        CharUnits::Zero()),
1289*67e74705SXin Li                                          /*BaseIsVirtual=*/true,
1290*67e74705SXin Li                                          /*OffsetInLayoutClass=*/
1291*67e74705SXin Li                                              CharUnits::Zero());
1292*67e74705SXin Li 
1293*67e74705SXin Li       VCallOffsets = Builder.getVCallOffsets();
1294*67e74705SXin Li     }
1295*67e74705SXin Li 
1296*67e74705SXin Li     Adjustment.Virtual.Itanium.VCallOffsetOffset =
1297*67e74705SXin Li       VCallOffsets.getVCallOffsetOffset(MD).getQuantity();
1298*67e74705SXin Li   }
1299*67e74705SXin Li 
1300*67e74705SXin Li   // Set the non-virtual part of the adjustment.
1301*67e74705SXin Li   Adjustment.NonVirtual = Offset.NonVirtualOffset.getQuantity();
1302*67e74705SXin Li 
1303*67e74705SXin Li   return Adjustment;
1304*67e74705SXin Li }
1305*67e74705SXin Li 
AddMethod(const CXXMethodDecl * MD,ReturnAdjustment ReturnAdjustment)1306*67e74705SXin Li void ItaniumVTableBuilder::AddMethod(const CXXMethodDecl *MD,
1307*67e74705SXin Li                                      ReturnAdjustment ReturnAdjustment) {
1308*67e74705SXin Li   if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1309*67e74705SXin Li     assert(ReturnAdjustment.isEmpty() &&
1310*67e74705SXin Li            "Destructor can't have return adjustment!");
1311*67e74705SXin Li 
1312*67e74705SXin Li     // Add both the complete destructor and the deleting destructor.
1313*67e74705SXin Li     Components.push_back(VTableComponent::MakeCompleteDtor(DD));
1314*67e74705SXin Li     Components.push_back(VTableComponent::MakeDeletingDtor(DD));
1315*67e74705SXin Li   } else {
1316*67e74705SXin Li     // Add the return adjustment if necessary.
1317*67e74705SXin Li     if (!ReturnAdjustment.isEmpty())
1318*67e74705SXin Li       VTableThunks[Components.size()].Return = ReturnAdjustment;
1319*67e74705SXin Li 
1320*67e74705SXin Li     // Add the function.
1321*67e74705SXin Li     Components.push_back(VTableComponent::MakeFunction(MD));
1322*67e74705SXin Li   }
1323*67e74705SXin Li }
1324*67e74705SXin Li 
1325*67e74705SXin Li /// OverridesIndirectMethodInBase - Return whether the given member function
1326*67e74705SXin Li /// overrides any methods in the set of given bases.
1327*67e74705SXin Li /// Unlike OverridesMethodInBase, this checks "overriders of overriders".
1328*67e74705SXin Li /// For example, if we have:
1329*67e74705SXin Li ///
1330*67e74705SXin Li /// struct A { virtual void f(); }
1331*67e74705SXin Li /// struct B : A { virtual void f(); }
1332*67e74705SXin Li /// struct C : B { virtual void f(); }
1333*67e74705SXin Li ///
1334*67e74705SXin Li /// OverridesIndirectMethodInBase will return true if given C::f as the method
1335*67e74705SXin Li /// and { A } as the set of bases.
OverridesIndirectMethodInBases(const CXXMethodDecl * MD,ItaniumVTableBuilder::PrimaryBasesSetVectorTy & Bases)1336*67e74705SXin Li static bool OverridesIndirectMethodInBases(
1337*67e74705SXin Li     const CXXMethodDecl *MD,
1338*67e74705SXin Li     ItaniumVTableBuilder::PrimaryBasesSetVectorTy &Bases) {
1339*67e74705SXin Li   if (Bases.count(MD->getParent()))
1340*67e74705SXin Li     return true;
1341*67e74705SXin Li 
1342*67e74705SXin Li   for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
1343*67e74705SXin Li        E = MD->end_overridden_methods(); I != E; ++I) {
1344*67e74705SXin Li     const CXXMethodDecl *OverriddenMD = *I;
1345*67e74705SXin Li 
1346*67e74705SXin Li     // Check "indirect overriders".
1347*67e74705SXin Li     if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
1348*67e74705SXin Li       return true;
1349*67e74705SXin Li   }
1350*67e74705SXin Li 
1351*67e74705SXin Li   return false;
1352*67e74705SXin Li }
1353*67e74705SXin Li 
IsOverriderUsed(const CXXMethodDecl * Overrider,CharUnits BaseOffsetInLayoutClass,const CXXRecordDecl * FirstBaseInPrimaryBaseChain,CharUnits FirstBaseOffsetInLayoutClass) const1354*67e74705SXin Li bool ItaniumVTableBuilder::IsOverriderUsed(
1355*67e74705SXin Li     const CXXMethodDecl *Overrider, CharUnits BaseOffsetInLayoutClass,
1356*67e74705SXin Li     const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
1357*67e74705SXin Li     CharUnits FirstBaseOffsetInLayoutClass) const {
1358*67e74705SXin Li   // If the base and the first base in the primary base chain have the same
1359*67e74705SXin Li   // offsets, then this overrider will be used.
1360*67e74705SXin Li   if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass)
1361*67e74705SXin Li    return true;
1362*67e74705SXin Li 
1363*67e74705SXin Li   // We know now that Base (or a direct or indirect base of it) is a primary
1364*67e74705SXin Li   // base in part of the class hierarchy, but not a primary base in the most
1365*67e74705SXin Li   // derived class.
1366*67e74705SXin Li 
1367*67e74705SXin Li   // If the overrider is the first base in the primary base chain, we know
1368*67e74705SXin Li   // that the overrider will be used.
1369*67e74705SXin Li   if (Overrider->getParent() == FirstBaseInPrimaryBaseChain)
1370*67e74705SXin Li     return true;
1371*67e74705SXin Li 
1372*67e74705SXin Li   ItaniumVTableBuilder::PrimaryBasesSetVectorTy PrimaryBases;
1373*67e74705SXin Li 
1374*67e74705SXin Li   const CXXRecordDecl *RD = FirstBaseInPrimaryBaseChain;
1375*67e74705SXin Li   PrimaryBases.insert(RD);
1376*67e74705SXin Li 
1377*67e74705SXin Li   // Now traverse the base chain, starting with the first base, until we find
1378*67e74705SXin Li   // the base that is no longer a primary base.
1379*67e74705SXin Li   while (true) {
1380*67e74705SXin Li     const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1381*67e74705SXin Li     const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1382*67e74705SXin Li 
1383*67e74705SXin Li     if (!PrimaryBase)
1384*67e74705SXin Li       break;
1385*67e74705SXin Li 
1386*67e74705SXin Li     if (Layout.isPrimaryBaseVirtual()) {
1387*67e74705SXin Li       assert(Layout.getVBaseClassOffset(PrimaryBase).isZero() &&
1388*67e74705SXin Li              "Primary base should always be at offset 0!");
1389*67e74705SXin Li 
1390*67e74705SXin Li       const ASTRecordLayout &LayoutClassLayout =
1391*67e74705SXin Li         Context.getASTRecordLayout(LayoutClass);
1392*67e74705SXin Li 
1393*67e74705SXin Li       // Now check if this is the primary base that is not a primary base in the
1394*67e74705SXin Li       // most derived class.
1395*67e74705SXin Li       if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) !=
1396*67e74705SXin Li           FirstBaseOffsetInLayoutClass) {
1397*67e74705SXin Li         // We found it, stop walking the chain.
1398*67e74705SXin Li         break;
1399*67e74705SXin Li       }
1400*67e74705SXin Li     } else {
1401*67e74705SXin Li       assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
1402*67e74705SXin Li              "Primary base should always be at offset 0!");
1403*67e74705SXin Li     }
1404*67e74705SXin Li 
1405*67e74705SXin Li     if (!PrimaryBases.insert(PrimaryBase))
1406*67e74705SXin Li       llvm_unreachable("Found a duplicate primary base!");
1407*67e74705SXin Li 
1408*67e74705SXin Li     RD = PrimaryBase;
1409*67e74705SXin Li   }
1410*67e74705SXin Li 
1411*67e74705SXin Li   // If the final overrider is an override of one of the primary bases,
1412*67e74705SXin Li   // then we know that it will be used.
1413*67e74705SXin Li   return OverridesIndirectMethodInBases(Overrider, PrimaryBases);
1414*67e74705SXin Li }
1415*67e74705SXin Li 
1416*67e74705SXin Li typedef llvm::SmallSetVector<const CXXRecordDecl *, 8> BasesSetVectorTy;
1417*67e74705SXin Li 
1418*67e74705SXin Li /// FindNearestOverriddenMethod - Given a method, returns the overridden method
1419*67e74705SXin Li /// from the nearest base. Returns null if no method was found.
1420*67e74705SXin Li /// The Bases are expected to be sorted in a base-to-derived order.
1421*67e74705SXin Li static const CXXMethodDecl *
FindNearestOverriddenMethod(const CXXMethodDecl * MD,BasesSetVectorTy & Bases)1422*67e74705SXin Li FindNearestOverriddenMethod(const CXXMethodDecl *MD,
1423*67e74705SXin Li                             BasesSetVectorTy &Bases) {
1424*67e74705SXin Li   OverriddenMethodsSetTy OverriddenMethods;
1425*67e74705SXin Li   ComputeAllOverriddenMethods(MD, OverriddenMethods);
1426*67e74705SXin Li 
1427*67e74705SXin Li   for (const CXXRecordDecl *PrimaryBase :
1428*67e74705SXin Li        llvm::make_range(Bases.rbegin(), Bases.rend())) {
1429*67e74705SXin Li     // Now check the overridden methods.
1430*67e74705SXin Li     for (const CXXMethodDecl *OverriddenMD : OverriddenMethods) {
1431*67e74705SXin Li       // We found our overridden method.
1432*67e74705SXin Li       if (OverriddenMD->getParent() == PrimaryBase)
1433*67e74705SXin Li         return OverriddenMD;
1434*67e74705SXin Li     }
1435*67e74705SXin Li   }
1436*67e74705SXin Li 
1437*67e74705SXin Li   return nullptr;
1438*67e74705SXin Li }
1439*67e74705SXin Li 
AddMethods(BaseSubobject Base,CharUnits BaseOffsetInLayoutClass,const CXXRecordDecl * FirstBaseInPrimaryBaseChain,CharUnits FirstBaseOffsetInLayoutClass,PrimaryBasesSetVectorTy & PrimaryBases)1440*67e74705SXin Li void ItaniumVTableBuilder::AddMethods(
1441*67e74705SXin Li     BaseSubobject Base, CharUnits BaseOffsetInLayoutClass,
1442*67e74705SXin Li     const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
1443*67e74705SXin Li     CharUnits FirstBaseOffsetInLayoutClass,
1444*67e74705SXin Li     PrimaryBasesSetVectorTy &PrimaryBases) {
1445*67e74705SXin Li   // Itanium C++ ABI 2.5.2:
1446*67e74705SXin Li   //   The order of the virtual function pointers in a virtual table is the
1447*67e74705SXin Li   //   order of declaration of the corresponding member functions in the class.
1448*67e74705SXin Li   //
1449*67e74705SXin Li   //   There is an entry for any virtual function declared in a class,
1450*67e74705SXin Li   //   whether it is a new function or overrides a base class function,
1451*67e74705SXin Li   //   unless it overrides a function from the primary base, and conversion
1452*67e74705SXin Li   //   between their return types does not require an adjustment.
1453*67e74705SXin Li 
1454*67e74705SXin Li   const CXXRecordDecl *RD = Base.getBase();
1455*67e74705SXin Li   const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1456*67e74705SXin Li 
1457*67e74705SXin Li   if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
1458*67e74705SXin Li     CharUnits PrimaryBaseOffset;
1459*67e74705SXin Li     CharUnits PrimaryBaseOffsetInLayoutClass;
1460*67e74705SXin Li     if (Layout.isPrimaryBaseVirtual()) {
1461*67e74705SXin Li       assert(Layout.getVBaseClassOffset(PrimaryBase).isZero() &&
1462*67e74705SXin Li              "Primary vbase should have a zero offset!");
1463*67e74705SXin Li 
1464*67e74705SXin Li       const ASTRecordLayout &MostDerivedClassLayout =
1465*67e74705SXin Li         Context.getASTRecordLayout(MostDerivedClass);
1466*67e74705SXin Li 
1467*67e74705SXin Li       PrimaryBaseOffset =
1468*67e74705SXin Li         MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
1469*67e74705SXin Li 
1470*67e74705SXin Li       const ASTRecordLayout &LayoutClassLayout =
1471*67e74705SXin Li         Context.getASTRecordLayout(LayoutClass);
1472*67e74705SXin Li 
1473*67e74705SXin Li       PrimaryBaseOffsetInLayoutClass =
1474*67e74705SXin Li         LayoutClassLayout.getVBaseClassOffset(PrimaryBase);
1475*67e74705SXin Li     } else {
1476*67e74705SXin Li       assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
1477*67e74705SXin Li              "Primary base should have a zero offset!");
1478*67e74705SXin Li 
1479*67e74705SXin Li       PrimaryBaseOffset = Base.getBaseOffset();
1480*67e74705SXin Li       PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass;
1481*67e74705SXin Li     }
1482*67e74705SXin Li 
1483*67e74705SXin Li     AddMethods(BaseSubobject(PrimaryBase, PrimaryBaseOffset),
1484*67e74705SXin Li                PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
1485*67e74705SXin Li                FirstBaseOffsetInLayoutClass, PrimaryBases);
1486*67e74705SXin Li 
1487*67e74705SXin Li     if (!PrimaryBases.insert(PrimaryBase))
1488*67e74705SXin Li       llvm_unreachable("Found a duplicate primary base!");
1489*67e74705SXin Li   }
1490*67e74705SXin Li 
1491*67e74705SXin Li   const CXXDestructorDecl *ImplicitVirtualDtor = nullptr;
1492*67e74705SXin Li 
1493*67e74705SXin Li   typedef llvm::SmallVector<const CXXMethodDecl *, 8> NewVirtualFunctionsTy;
1494*67e74705SXin Li   NewVirtualFunctionsTy NewVirtualFunctions;
1495*67e74705SXin Li 
1496*67e74705SXin Li   // Now go through all virtual member functions and add them.
1497*67e74705SXin Li   for (const auto *MD : RD->methods()) {
1498*67e74705SXin Li     if (!MD->isVirtual())
1499*67e74705SXin Li       continue;
1500*67e74705SXin Li     MD = MD->getCanonicalDecl();
1501*67e74705SXin Li 
1502*67e74705SXin Li     // Get the final overrider.
1503*67e74705SXin Li     FinalOverriders::OverriderInfo Overrider =
1504*67e74705SXin Li       Overriders.getOverrider(MD, Base.getBaseOffset());
1505*67e74705SXin Li 
1506*67e74705SXin Li     // Check if this virtual member function overrides a method in a primary
1507*67e74705SXin Li     // base. If this is the case, and the return type doesn't require adjustment
1508*67e74705SXin Li     // then we can just use the member function from the primary base.
1509*67e74705SXin Li     if (const CXXMethodDecl *OverriddenMD =
1510*67e74705SXin Li           FindNearestOverriddenMethod(MD, PrimaryBases)) {
1511*67e74705SXin Li       if (ComputeReturnAdjustmentBaseOffset(Context, MD,
1512*67e74705SXin Li                                             OverriddenMD).isEmpty()) {
1513*67e74705SXin Li         // Replace the method info of the overridden method with our own
1514*67e74705SXin Li         // method.
1515*67e74705SXin Li         assert(MethodInfoMap.count(OverriddenMD) &&
1516*67e74705SXin Li                "Did not find the overridden method!");
1517*67e74705SXin Li         MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
1518*67e74705SXin Li 
1519*67e74705SXin Li         MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass,
1520*67e74705SXin Li                               OverriddenMethodInfo.VTableIndex);
1521*67e74705SXin Li 
1522*67e74705SXin Li         assert(!MethodInfoMap.count(MD) &&
1523*67e74705SXin Li                "Should not have method info for this method yet!");
1524*67e74705SXin Li 
1525*67e74705SXin Li         MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1526*67e74705SXin Li         MethodInfoMap.erase(OverriddenMD);
1527*67e74705SXin Li 
1528*67e74705SXin Li         // If the overridden method exists in a virtual base class or a direct
1529*67e74705SXin Li         // or indirect base class of a virtual base class, we need to emit a
1530*67e74705SXin Li         // thunk if we ever have a class hierarchy where the base class is not
1531*67e74705SXin Li         // a primary base in the complete object.
1532*67e74705SXin Li         if (!isBuildingConstructorVTable() && OverriddenMD != MD) {
1533*67e74705SXin Li           // Compute the this adjustment.
1534*67e74705SXin Li           ThisAdjustment ThisAdjustment =
1535*67e74705SXin Li             ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
1536*67e74705SXin Li                                   Overrider);
1537*67e74705SXin Li 
1538*67e74705SXin Li           if (ThisAdjustment.Virtual.Itanium.VCallOffsetOffset &&
1539*67e74705SXin Li               Overrider.Method->getParent() == MostDerivedClass) {
1540*67e74705SXin Li 
1541*67e74705SXin Li             // There's no return adjustment from OverriddenMD and MD,
1542*67e74705SXin Li             // but that doesn't mean there isn't one between MD and
1543*67e74705SXin Li             // the final overrider.
1544*67e74705SXin Li             BaseOffset ReturnAdjustmentOffset =
1545*67e74705SXin Li               ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
1546*67e74705SXin Li             ReturnAdjustment ReturnAdjustment =
1547*67e74705SXin Li               ComputeReturnAdjustment(ReturnAdjustmentOffset);
1548*67e74705SXin Li 
1549*67e74705SXin Li             // This is a virtual thunk for the most derived class, add it.
1550*67e74705SXin Li             AddThunk(Overrider.Method,
1551*67e74705SXin Li                      ThunkInfo(ThisAdjustment, ReturnAdjustment));
1552*67e74705SXin Li           }
1553*67e74705SXin Li         }
1554*67e74705SXin Li 
1555*67e74705SXin Li         continue;
1556*67e74705SXin Li       }
1557*67e74705SXin Li     }
1558*67e74705SXin Li 
1559*67e74705SXin Li     if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1560*67e74705SXin Li       if (MD->isImplicit()) {
1561*67e74705SXin Li         // Itanium C++ ABI 2.5.2:
1562*67e74705SXin Li         //   If a class has an implicitly-defined virtual destructor,
1563*67e74705SXin Li         //   its entries come after the declared virtual function pointers.
1564*67e74705SXin Li 
1565*67e74705SXin Li         assert(!ImplicitVirtualDtor &&
1566*67e74705SXin Li                "Did already see an implicit virtual dtor!");
1567*67e74705SXin Li         ImplicitVirtualDtor = DD;
1568*67e74705SXin Li         continue;
1569*67e74705SXin Li       }
1570*67e74705SXin Li     }
1571*67e74705SXin Li 
1572*67e74705SXin Li     NewVirtualFunctions.push_back(MD);
1573*67e74705SXin Li   }
1574*67e74705SXin Li 
1575*67e74705SXin Li   if (ImplicitVirtualDtor)
1576*67e74705SXin Li     NewVirtualFunctions.push_back(ImplicitVirtualDtor);
1577*67e74705SXin Li 
1578*67e74705SXin Li   for (const CXXMethodDecl *MD : NewVirtualFunctions) {
1579*67e74705SXin Li     // Get the final overrider.
1580*67e74705SXin Li     FinalOverriders::OverriderInfo Overrider =
1581*67e74705SXin Li       Overriders.getOverrider(MD, Base.getBaseOffset());
1582*67e74705SXin Li 
1583*67e74705SXin Li     // Insert the method info for this method.
1584*67e74705SXin Li     MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass,
1585*67e74705SXin Li                           Components.size());
1586*67e74705SXin Li 
1587*67e74705SXin Li     assert(!MethodInfoMap.count(MD) &&
1588*67e74705SXin Li            "Should not have method info for this method yet!");
1589*67e74705SXin Li     MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1590*67e74705SXin Li 
1591*67e74705SXin Li     // Check if this overrider is going to be used.
1592*67e74705SXin Li     const CXXMethodDecl *OverriderMD = Overrider.Method;
1593*67e74705SXin Li     if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass,
1594*67e74705SXin Li                          FirstBaseInPrimaryBaseChain,
1595*67e74705SXin Li                          FirstBaseOffsetInLayoutClass)) {
1596*67e74705SXin Li       Components.push_back(VTableComponent::MakeUnusedFunction(OverriderMD));
1597*67e74705SXin Li       continue;
1598*67e74705SXin Li     }
1599*67e74705SXin Li 
1600*67e74705SXin Li     // Check if this overrider needs a return adjustment.
1601*67e74705SXin Li     // We don't want to do this for pure virtual member functions.
1602*67e74705SXin Li     BaseOffset ReturnAdjustmentOffset;
1603*67e74705SXin Li     if (!OverriderMD->isPure()) {
1604*67e74705SXin Li       ReturnAdjustmentOffset =
1605*67e74705SXin Li         ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
1606*67e74705SXin Li     }
1607*67e74705SXin Li 
1608*67e74705SXin Li     ReturnAdjustment ReturnAdjustment =
1609*67e74705SXin Li       ComputeReturnAdjustment(ReturnAdjustmentOffset);
1610*67e74705SXin Li 
1611*67e74705SXin Li     AddMethod(Overrider.Method, ReturnAdjustment);
1612*67e74705SXin Li   }
1613*67e74705SXin Li }
1614*67e74705SXin Li 
LayoutVTable()1615*67e74705SXin Li void ItaniumVTableBuilder::LayoutVTable() {
1616*67e74705SXin Li   LayoutPrimaryAndSecondaryVTables(BaseSubobject(MostDerivedClass,
1617*67e74705SXin Li                                                  CharUnits::Zero()),
1618*67e74705SXin Li                                    /*BaseIsMorallyVirtual=*/false,
1619*67e74705SXin Li                                    MostDerivedClassIsVirtual,
1620*67e74705SXin Li                                    MostDerivedClassOffset);
1621*67e74705SXin Li 
1622*67e74705SXin Li   VisitedVirtualBasesSetTy VBases;
1623*67e74705SXin Li 
1624*67e74705SXin Li   // Determine the primary virtual bases.
1625*67e74705SXin Li   DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
1626*67e74705SXin Li                                VBases);
1627*67e74705SXin Li   VBases.clear();
1628*67e74705SXin Li 
1629*67e74705SXin Li   LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
1630*67e74705SXin Li 
1631*67e74705SXin Li   // -fapple-kext adds an extra entry at end of vtbl.
1632*67e74705SXin Li   bool IsAppleKext = Context.getLangOpts().AppleKext;
1633*67e74705SXin Li   if (IsAppleKext)
1634*67e74705SXin Li     Components.push_back(VTableComponent::MakeVCallOffset(CharUnits::Zero()));
1635*67e74705SXin Li }
1636*67e74705SXin Li 
LayoutPrimaryAndSecondaryVTables(BaseSubobject Base,bool BaseIsMorallyVirtual,bool BaseIsVirtualInLayoutClass,CharUnits OffsetInLayoutClass)1637*67e74705SXin Li void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
1638*67e74705SXin Li     BaseSubobject Base, bool BaseIsMorallyVirtual,
1639*67e74705SXin Li     bool BaseIsVirtualInLayoutClass, CharUnits OffsetInLayoutClass) {
1640*67e74705SXin Li   assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!");
1641*67e74705SXin Li 
1642*67e74705SXin Li   // Add vcall and vbase offsets for this vtable.
1643*67e74705SXin Li   VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders,
1644*67e74705SXin Li                                      Base, BaseIsVirtualInLayoutClass,
1645*67e74705SXin Li                                      OffsetInLayoutClass);
1646*67e74705SXin Li   Components.append(Builder.components_begin(), Builder.components_end());
1647*67e74705SXin Li 
1648*67e74705SXin Li   // Check if we need to add these vcall offsets.
1649*67e74705SXin Li   if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) {
1650*67e74705SXin Li     VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Base.getBase()];
1651*67e74705SXin Li 
1652*67e74705SXin Li     if (VCallOffsets.empty())
1653*67e74705SXin Li       VCallOffsets = Builder.getVCallOffsets();
1654*67e74705SXin Li   }
1655*67e74705SXin Li 
1656*67e74705SXin Li   // If we're laying out the most derived class we want to keep track of the
1657*67e74705SXin Li   // virtual base class offset offsets.
1658*67e74705SXin Li   if (Base.getBase() == MostDerivedClass)
1659*67e74705SXin Li     VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
1660*67e74705SXin Li 
1661*67e74705SXin Li   // Add the offset to top.
1662*67e74705SXin Li   CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
1663*67e74705SXin Li   Components.push_back(VTableComponent::MakeOffsetToTop(OffsetToTop));
1664*67e74705SXin Li 
1665*67e74705SXin Li   // Next, add the RTTI.
1666*67e74705SXin Li   Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
1667*67e74705SXin Li 
1668*67e74705SXin Li   uint64_t AddressPoint = Components.size();
1669*67e74705SXin Li 
1670*67e74705SXin Li   // Now go through all virtual member functions and add them.
1671*67e74705SXin Li   PrimaryBasesSetVectorTy PrimaryBases;
1672*67e74705SXin Li   AddMethods(Base, OffsetInLayoutClass,
1673*67e74705SXin Li              Base.getBase(), OffsetInLayoutClass,
1674*67e74705SXin Li              PrimaryBases);
1675*67e74705SXin Li 
1676*67e74705SXin Li   const CXXRecordDecl *RD = Base.getBase();
1677*67e74705SXin Li   if (RD == MostDerivedClass) {
1678*67e74705SXin Li     assert(MethodVTableIndices.empty());
1679*67e74705SXin Li     for (const auto &I : MethodInfoMap) {
1680*67e74705SXin Li       const CXXMethodDecl *MD = I.first;
1681*67e74705SXin Li       const MethodInfo &MI = I.second;
1682*67e74705SXin Li       if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1683*67e74705SXin Li         MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
1684*67e74705SXin Li             = MI.VTableIndex - AddressPoint;
1685*67e74705SXin Li         MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
1686*67e74705SXin Li             = MI.VTableIndex + 1 - AddressPoint;
1687*67e74705SXin Li       } else {
1688*67e74705SXin Li         MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
1689*67e74705SXin Li       }
1690*67e74705SXin Li     }
1691*67e74705SXin Li   }
1692*67e74705SXin Li 
1693*67e74705SXin Li   // Compute 'this' pointer adjustments.
1694*67e74705SXin Li   ComputeThisAdjustments();
1695*67e74705SXin Li 
1696*67e74705SXin Li   // Add all address points.
1697*67e74705SXin Li   while (true) {
1698*67e74705SXin Li     AddressPoints.insert(std::make_pair(
1699*67e74705SXin Li       BaseSubobject(RD, OffsetInLayoutClass),
1700*67e74705SXin Li       AddressPoint));
1701*67e74705SXin Li 
1702*67e74705SXin Li     const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1703*67e74705SXin Li     const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1704*67e74705SXin Li 
1705*67e74705SXin Li     if (!PrimaryBase)
1706*67e74705SXin Li       break;
1707*67e74705SXin Li 
1708*67e74705SXin Li     if (Layout.isPrimaryBaseVirtual()) {
1709*67e74705SXin Li       // Check if this virtual primary base is a primary base in the layout
1710*67e74705SXin Li       // class. If it's not, we don't want to add it.
1711*67e74705SXin Li       const ASTRecordLayout &LayoutClassLayout =
1712*67e74705SXin Li         Context.getASTRecordLayout(LayoutClass);
1713*67e74705SXin Li 
1714*67e74705SXin Li       if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) !=
1715*67e74705SXin Li           OffsetInLayoutClass) {
1716*67e74705SXin Li         // We don't want to add this class (or any of its primary bases).
1717*67e74705SXin Li         break;
1718*67e74705SXin Li       }
1719*67e74705SXin Li     }
1720*67e74705SXin Li 
1721*67e74705SXin Li     RD = PrimaryBase;
1722*67e74705SXin Li   }
1723*67e74705SXin Li 
1724*67e74705SXin Li   // Layout secondary vtables.
1725*67e74705SXin Li   LayoutSecondaryVTables(Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
1726*67e74705SXin Li }
1727*67e74705SXin Li 
1728*67e74705SXin Li void
LayoutSecondaryVTables(BaseSubobject Base,bool BaseIsMorallyVirtual,CharUnits OffsetInLayoutClass)1729*67e74705SXin Li ItaniumVTableBuilder::LayoutSecondaryVTables(BaseSubobject Base,
1730*67e74705SXin Li                                              bool BaseIsMorallyVirtual,
1731*67e74705SXin Li                                              CharUnits OffsetInLayoutClass) {
1732*67e74705SXin Li   // Itanium C++ ABI 2.5.2:
1733*67e74705SXin Li   //   Following the primary virtual table of a derived class are secondary
1734*67e74705SXin Li   //   virtual tables for each of its proper base classes, except any primary
1735*67e74705SXin Li   //   base(s) with which it shares its primary virtual table.
1736*67e74705SXin Li 
1737*67e74705SXin Li   const CXXRecordDecl *RD = Base.getBase();
1738*67e74705SXin Li   const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1739*67e74705SXin Li   const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1740*67e74705SXin Li 
1741*67e74705SXin Li   for (const auto &B : RD->bases()) {
1742*67e74705SXin Li     // Ignore virtual bases, we'll emit them later.
1743*67e74705SXin Li     if (B.isVirtual())
1744*67e74705SXin Li       continue;
1745*67e74705SXin Li 
1746*67e74705SXin Li     const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1747*67e74705SXin Li 
1748*67e74705SXin Li     // Ignore bases that don't have a vtable.
1749*67e74705SXin Li     if (!BaseDecl->isDynamicClass())
1750*67e74705SXin Li       continue;
1751*67e74705SXin Li 
1752*67e74705SXin Li     if (isBuildingConstructorVTable()) {
1753*67e74705SXin Li       // Itanium C++ ABI 2.6.4:
1754*67e74705SXin Li       //   Some of the base class subobjects may not need construction virtual
1755*67e74705SXin Li       //   tables, which will therefore not be present in the construction
1756*67e74705SXin Li       //   virtual table group, even though the subobject virtual tables are
1757*67e74705SXin Li       //   present in the main virtual table group for the complete object.
1758*67e74705SXin Li       if (!BaseIsMorallyVirtual && !BaseDecl->getNumVBases())
1759*67e74705SXin Li         continue;
1760*67e74705SXin Li     }
1761*67e74705SXin Li 
1762*67e74705SXin Li     // Get the base offset of this base.
1763*67e74705SXin Li     CharUnits RelativeBaseOffset = Layout.getBaseClassOffset(BaseDecl);
1764*67e74705SXin Li     CharUnits BaseOffset = Base.getBaseOffset() + RelativeBaseOffset;
1765*67e74705SXin Li 
1766*67e74705SXin Li     CharUnits BaseOffsetInLayoutClass =
1767*67e74705SXin Li       OffsetInLayoutClass + RelativeBaseOffset;
1768*67e74705SXin Li 
1769*67e74705SXin Li     // Don't emit a secondary vtable for a primary base. We might however want
1770*67e74705SXin Li     // to emit secondary vtables for other bases of this base.
1771*67e74705SXin Li     if (BaseDecl == PrimaryBase) {
1772*67e74705SXin Li       LayoutSecondaryVTables(BaseSubobject(BaseDecl, BaseOffset),
1773*67e74705SXin Li                              BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
1774*67e74705SXin Li       continue;
1775*67e74705SXin Li     }
1776*67e74705SXin Li 
1777*67e74705SXin Li     // Layout the primary vtable (and any secondary vtables) for this base.
1778*67e74705SXin Li     LayoutPrimaryAndSecondaryVTables(
1779*67e74705SXin Li       BaseSubobject(BaseDecl, BaseOffset),
1780*67e74705SXin Li       BaseIsMorallyVirtual,
1781*67e74705SXin Li       /*BaseIsVirtualInLayoutClass=*/false,
1782*67e74705SXin Li       BaseOffsetInLayoutClass);
1783*67e74705SXin Li   }
1784*67e74705SXin Li }
1785*67e74705SXin Li 
DeterminePrimaryVirtualBases(const CXXRecordDecl * RD,CharUnits OffsetInLayoutClass,VisitedVirtualBasesSetTy & VBases)1786*67e74705SXin Li void ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
1787*67e74705SXin Li     const CXXRecordDecl *RD, CharUnits OffsetInLayoutClass,
1788*67e74705SXin Li     VisitedVirtualBasesSetTy &VBases) {
1789*67e74705SXin Li   const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1790*67e74705SXin Li 
1791*67e74705SXin Li   // Check if this base has a primary base.
1792*67e74705SXin Li   if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
1793*67e74705SXin Li 
1794*67e74705SXin Li     // Check if it's virtual.
1795*67e74705SXin Li     if (Layout.isPrimaryBaseVirtual()) {
1796*67e74705SXin Li       bool IsPrimaryVirtualBase = true;
1797*67e74705SXin Li 
1798*67e74705SXin Li       if (isBuildingConstructorVTable()) {
1799*67e74705SXin Li         // Check if the base is actually a primary base in the class we use for
1800*67e74705SXin Li         // layout.
1801*67e74705SXin Li         const ASTRecordLayout &LayoutClassLayout =
1802*67e74705SXin Li           Context.getASTRecordLayout(LayoutClass);
1803*67e74705SXin Li 
1804*67e74705SXin Li         CharUnits PrimaryBaseOffsetInLayoutClass =
1805*67e74705SXin Li           LayoutClassLayout.getVBaseClassOffset(PrimaryBase);
1806*67e74705SXin Li 
1807*67e74705SXin Li         // We know that the base is not a primary base in the layout class if
1808*67e74705SXin Li         // the base offsets are different.
1809*67e74705SXin Li         if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass)
1810*67e74705SXin Li           IsPrimaryVirtualBase = false;
1811*67e74705SXin Li       }
1812*67e74705SXin Li 
1813*67e74705SXin Li       if (IsPrimaryVirtualBase)
1814*67e74705SXin Li         PrimaryVirtualBases.insert(PrimaryBase);
1815*67e74705SXin Li     }
1816*67e74705SXin Li   }
1817*67e74705SXin Li 
1818*67e74705SXin Li   // Traverse bases, looking for more primary virtual bases.
1819*67e74705SXin Li   for (const auto &B : RD->bases()) {
1820*67e74705SXin Li     const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1821*67e74705SXin Li 
1822*67e74705SXin Li     CharUnits BaseOffsetInLayoutClass;
1823*67e74705SXin Li 
1824*67e74705SXin Li     if (B.isVirtual()) {
1825*67e74705SXin Li       if (!VBases.insert(BaseDecl).second)
1826*67e74705SXin Li         continue;
1827*67e74705SXin Li 
1828*67e74705SXin Li       const ASTRecordLayout &LayoutClassLayout =
1829*67e74705SXin Li         Context.getASTRecordLayout(LayoutClass);
1830*67e74705SXin Li 
1831*67e74705SXin Li       BaseOffsetInLayoutClass =
1832*67e74705SXin Li         LayoutClassLayout.getVBaseClassOffset(BaseDecl);
1833*67e74705SXin Li     } else {
1834*67e74705SXin Li       BaseOffsetInLayoutClass =
1835*67e74705SXin Li         OffsetInLayoutClass + Layout.getBaseClassOffset(BaseDecl);
1836*67e74705SXin Li     }
1837*67e74705SXin Li 
1838*67e74705SXin Li     DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases);
1839*67e74705SXin Li   }
1840*67e74705SXin Li }
1841*67e74705SXin Li 
LayoutVTablesForVirtualBases(const CXXRecordDecl * RD,VisitedVirtualBasesSetTy & VBases)1842*67e74705SXin Li void ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
1843*67e74705SXin Li     const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases) {
1844*67e74705SXin Li   // Itanium C++ ABI 2.5.2:
1845*67e74705SXin Li   //   Then come the virtual base virtual tables, also in inheritance graph
1846*67e74705SXin Li   //   order, and again excluding primary bases (which share virtual tables with
1847*67e74705SXin Li   //   the classes for which they are primary).
1848*67e74705SXin Li   for (const auto &B : RD->bases()) {
1849*67e74705SXin Li     const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1850*67e74705SXin Li 
1851*67e74705SXin Li     // Check if this base needs a vtable. (If it's virtual, not a primary base
1852*67e74705SXin Li     // of some other class, and we haven't visited it before).
1853*67e74705SXin Li     if (B.isVirtual() && BaseDecl->isDynamicClass() &&
1854*67e74705SXin Li         !PrimaryVirtualBases.count(BaseDecl) &&
1855*67e74705SXin Li         VBases.insert(BaseDecl).second) {
1856*67e74705SXin Li       const ASTRecordLayout &MostDerivedClassLayout =
1857*67e74705SXin Li         Context.getASTRecordLayout(MostDerivedClass);
1858*67e74705SXin Li       CharUnits BaseOffset =
1859*67e74705SXin Li         MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
1860*67e74705SXin Li 
1861*67e74705SXin Li       const ASTRecordLayout &LayoutClassLayout =
1862*67e74705SXin Li         Context.getASTRecordLayout(LayoutClass);
1863*67e74705SXin Li       CharUnits BaseOffsetInLayoutClass =
1864*67e74705SXin Li         LayoutClassLayout.getVBaseClassOffset(BaseDecl);
1865*67e74705SXin Li 
1866*67e74705SXin Li       LayoutPrimaryAndSecondaryVTables(
1867*67e74705SXin Li         BaseSubobject(BaseDecl, BaseOffset),
1868*67e74705SXin Li         /*BaseIsMorallyVirtual=*/true,
1869*67e74705SXin Li         /*BaseIsVirtualInLayoutClass=*/true,
1870*67e74705SXin Li         BaseOffsetInLayoutClass);
1871*67e74705SXin Li     }
1872*67e74705SXin Li 
1873*67e74705SXin Li     // We only need to check the base for virtual base vtables if it actually
1874*67e74705SXin Li     // has virtual bases.
1875*67e74705SXin Li     if (BaseDecl->getNumVBases())
1876*67e74705SXin Li       LayoutVTablesForVirtualBases(BaseDecl, VBases);
1877*67e74705SXin Li   }
1878*67e74705SXin Li }
1879*67e74705SXin Li 
1880*67e74705SXin Li /// dumpLayout - Dump the vtable layout.
dumpLayout(raw_ostream & Out)1881*67e74705SXin Li void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
1882*67e74705SXin Li   // FIXME: write more tests that actually use the dumpLayout output to prevent
1883*67e74705SXin Li   // ItaniumVTableBuilder regressions.
1884*67e74705SXin Li 
1885*67e74705SXin Li   if (isBuildingConstructorVTable()) {
1886*67e74705SXin Li     Out << "Construction vtable for ('";
1887*67e74705SXin Li     MostDerivedClass->printQualifiedName(Out);
1888*67e74705SXin Li     Out << "', ";
1889*67e74705SXin Li     Out << MostDerivedClassOffset.getQuantity() << ") in '";
1890*67e74705SXin Li     LayoutClass->printQualifiedName(Out);
1891*67e74705SXin Li   } else {
1892*67e74705SXin Li     Out << "Vtable for '";
1893*67e74705SXin Li     MostDerivedClass->printQualifiedName(Out);
1894*67e74705SXin Li   }
1895*67e74705SXin Li   Out << "' (" << Components.size() << " entries).\n";
1896*67e74705SXin Li 
1897*67e74705SXin Li   // Iterate through the address points and insert them into a new map where
1898*67e74705SXin Li   // they are keyed by the index and not the base object.
1899*67e74705SXin Li   // Since an address point can be shared by multiple subobjects, we use an
1900*67e74705SXin Li   // STL multimap.
1901*67e74705SXin Li   std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
1902*67e74705SXin Li   for (const auto &AP : AddressPoints) {
1903*67e74705SXin Li     const BaseSubobject &Base = AP.first;
1904*67e74705SXin Li     uint64_t Index = AP.second;
1905*67e74705SXin Li 
1906*67e74705SXin Li     AddressPointsByIndex.insert(std::make_pair(Index, Base));
1907*67e74705SXin Li   }
1908*67e74705SXin Li 
1909*67e74705SXin Li   for (unsigned I = 0, E = Components.size(); I != E; ++I) {
1910*67e74705SXin Li     uint64_t Index = I;
1911*67e74705SXin Li 
1912*67e74705SXin Li     Out << llvm::format("%4d | ", I);
1913*67e74705SXin Li 
1914*67e74705SXin Li     const VTableComponent &Component = Components[I];
1915*67e74705SXin Li 
1916*67e74705SXin Li     // Dump the component.
1917*67e74705SXin Li     switch (Component.getKind()) {
1918*67e74705SXin Li 
1919*67e74705SXin Li     case VTableComponent::CK_VCallOffset:
1920*67e74705SXin Li       Out << "vcall_offset ("
1921*67e74705SXin Li           << Component.getVCallOffset().getQuantity()
1922*67e74705SXin Li           << ")";
1923*67e74705SXin Li       break;
1924*67e74705SXin Li 
1925*67e74705SXin Li     case VTableComponent::CK_VBaseOffset:
1926*67e74705SXin Li       Out << "vbase_offset ("
1927*67e74705SXin Li           << Component.getVBaseOffset().getQuantity()
1928*67e74705SXin Li           << ")";
1929*67e74705SXin Li       break;
1930*67e74705SXin Li 
1931*67e74705SXin Li     case VTableComponent::CK_OffsetToTop:
1932*67e74705SXin Li       Out << "offset_to_top ("
1933*67e74705SXin Li           << Component.getOffsetToTop().getQuantity()
1934*67e74705SXin Li           << ")";
1935*67e74705SXin Li       break;
1936*67e74705SXin Li 
1937*67e74705SXin Li     case VTableComponent::CK_RTTI:
1938*67e74705SXin Li       Component.getRTTIDecl()->printQualifiedName(Out);
1939*67e74705SXin Li       Out << " RTTI";
1940*67e74705SXin Li       break;
1941*67e74705SXin Li 
1942*67e74705SXin Li     case VTableComponent::CK_FunctionPointer: {
1943*67e74705SXin Li       const CXXMethodDecl *MD = Component.getFunctionDecl();
1944*67e74705SXin Li 
1945*67e74705SXin Li       std::string Str =
1946*67e74705SXin Li         PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
1947*67e74705SXin Li                                     MD);
1948*67e74705SXin Li       Out << Str;
1949*67e74705SXin Li       if (MD->isPure())
1950*67e74705SXin Li         Out << " [pure]";
1951*67e74705SXin Li 
1952*67e74705SXin Li       if (MD->isDeleted())
1953*67e74705SXin Li         Out << " [deleted]";
1954*67e74705SXin Li 
1955*67e74705SXin Li       ThunkInfo Thunk = VTableThunks.lookup(I);
1956*67e74705SXin Li       if (!Thunk.isEmpty()) {
1957*67e74705SXin Li         // If this function pointer has a return adjustment, dump it.
1958*67e74705SXin Li         if (!Thunk.Return.isEmpty()) {
1959*67e74705SXin Li           Out << "\n       [return adjustment: ";
1960*67e74705SXin Li           Out << Thunk.Return.NonVirtual << " non-virtual";
1961*67e74705SXin Li 
1962*67e74705SXin Li           if (Thunk.Return.Virtual.Itanium.VBaseOffsetOffset) {
1963*67e74705SXin Li             Out << ", " << Thunk.Return.Virtual.Itanium.VBaseOffsetOffset;
1964*67e74705SXin Li             Out << " vbase offset offset";
1965*67e74705SXin Li           }
1966*67e74705SXin Li 
1967*67e74705SXin Li           Out << ']';
1968*67e74705SXin Li         }
1969*67e74705SXin Li 
1970*67e74705SXin Li         // If this function pointer has a 'this' pointer adjustment, dump it.
1971*67e74705SXin Li         if (!Thunk.This.isEmpty()) {
1972*67e74705SXin Li           Out << "\n       [this adjustment: ";
1973*67e74705SXin Li           Out << Thunk.This.NonVirtual << " non-virtual";
1974*67e74705SXin Li 
1975*67e74705SXin Li           if (Thunk.This.Virtual.Itanium.VCallOffsetOffset) {
1976*67e74705SXin Li             Out << ", " << Thunk.This.Virtual.Itanium.VCallOffsetOffset;
1977*67e74705SXin Li             Out << " vcall offset offset";
1978*67e74705SXin Li           }
1979*67e74705SXin Li 
1980*67e74705SXin Li           Out << ']';
1981*67e74705SXin Li         }
1982*67e74705SXin Li       }
1983*67e74705SXin Li 
1984*67e74705SXin Li       break;
1985*67e74705SXin Li     }
1986*67e74705SXin Li 
1987*67e74705SXin Li     case VTableComponent::CK_CompleteDtorPointer:
1988*67e74705SXin Li     case VTableComponent::CK_DeletingDtorPointer: {
1989*67e74705SXin Li       bool IsComplete =
1990*67e74705SXin Li         Component.getKind() == VTableComponent::CK_CompleteDtorPointer;
1991*67e74705SXin Li 
1992*67e74705SXin Li       const CXXDestructorDecl *DD = Component.getDestructorDecl();
1993*67e74705SXin Li 
1994*67e74705SXin Li       DD->printQualifiedName(Out);
1995*67e74705SXin Li       if (IsComplete)
1996*67e74705SXin Li         Out << "() [complete]";
1997*67e74705SXin Li       else
1998*67e74705SXin Li         Out << "() [deleting]";
1999*67e74705SXin Li 
2000*67e74705SXin Li       if (DD->isPure())
2001*67e74705SXin Li         Out << " [pure]";
2002*67e74705SXin Li 
2003*67e74705SXin Li       ThunkInfo Thunk = VTableThunks.lookup(I);
2004*67e74705SXin Li       if (!Thunk.isEmpty()) {
2005*67e74705SXin Li         // If this destructor has a 'this' pointer adjustment, dump it.
2006*67e74705SXin Li         if (!Thunk.This.isEmpty()) {
2007*67e74705SXin Li           Out << "\n       [this adjustment: ";
2008*67e74705SXin Li           Out << Thunk.This.NonVirtual << " non-virtual";
2009*67e74705SXin Li 
2010*67e74705SXin Li           if (Thunk.This.Virtual.Itanium.VCallOffsetOffset) {
2011*67e74705SXin Li             Out << ", " << Thunk.This.Virtual.Itanium.VCallOffsetOffset;
2012*67e74705SXin Li             Out << " vcall offset offset";
2013*67e74705SXin Li           }
2014*67e74705SXin Li 
2015*67e74705SXin Li           Out << ']';
2016*67e74705SXin Li         }
2017*67e74705SXin Li       }
2018*67e74705SXin Li 
2019*67e74705SXin Li       break;
2020*67e74705SXin Li     }
2021*67e74705SXin Li 
2022*67e74705SXin Li     case VTableComponent::CK_UnusedFunctionPointer: {
2023*67e74705SXin Li       const CXXMethodDecl *MD = Component.getUnusedFunctionDecl();
2024*67e74705SXin Li 
2025*67e74705SXin Li       std::string Str =
2026*67e74705SXin Li         PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
2027*67e74705SXin Li                                     MD);
2028*67e74705SXin Li       Out << "[unused] " << Str;
2029*67e74705SXin Li       if (MD->isPure())
2030*67e74705SXin Li         Out << " [pure]";
2031*67e74705SXin Li     }
2032*67e74705SXin Li 
2033*67e74705SXin Li     }
2034*67e74705SXin Li 
2035*67e74705SXin Li     Out << '\n';
2036*67e74705SXin Li 
2037*67e74705SXin Li     // Dump the next address point.
2038*67e74705SXin Li     uint64_t NextIndex = Index + 1;
2039*67e74705SXin Li     if (AddressPointsByIndex.count(NextIndex)) {
2040*67e74705SXin Li       if (AddressPointsByIndex.count(NextIndex) == 1) {
2041*67e74705SXin Li         const BaseSubobject &Base =
2042*67e74705SXin Li           AddressPointsByIndex.find(NextIndex)->second;
2043*67e74705SXin Li 
2044*67e74705SXin Li         Out << "       -- (";
2045*67e74705SXin Li         Base.getBase()->printQualifiedName(Out);
2046*67e74705SXin Li         Out << ", " << Base.getBaseOffset().getQuantity();
2047*67e74705SXin Li         Out << ") vtable address --\n";
2048*67e74705SXin Li       } else {
2049*67e74705SXin Li         CharUnits BaseOffset =
2050*67e74705SXin Li           AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
2051*67e74705SXin Li 
2052*67e74705SXin Li         // We store the class names in a set to get a stable order.
2053*67e74705SXin Li         std::set<std::string> ClassNames;
2054*67e74705SXin Li         for (const auto &I :
2055*67e74705SXin Li              llvm::make_range(AddressPointsByIndex.equal_range(NextIndex))) {
2056*67e74705SXin Li           assert(I.second.getBaseOffset() == BaseOffset &&
2057*67e74705SXin Li                  "Invalid base offset!");
2058*67e74705SXin Li           const CXXRecordDecl *RD = I.second.getBase();
2059*67e74705SXin Li           ClassNames.insert(RD->getQualifiedNameAsString());
2060*67e74705SXin Li         }
2061*67e74705SXin Li 
2062*67e74705SXin Li         for (const std::string &Name : ClassNames) {
2063*67e74705SXin Li           Out << "       -- (" << Name;
2064*67e74705SXin Li           Out << ", " << BaseOffset.getQuantity() << ") vtable address --\n";
2065*67e74705SXin Li         }
2066*67e74705SXin Li       }
2067*67e74705SXin Li     }
2068*67e74705SXin Li   }
2069*67e74705SXin Li 
2070*67e74705SXin Li   Out << '\n';
2071*67e74705SXin Li 
2072*67e74705SXin Li   if (isBuildingConstructorVTable())
2073*67e74705SXin Li     return;
2074*67e74705SXin Li 
2075*67e74705SXin Li   if (MostDerivedClass->getNumVBases()) {
2076*67e74705SXin Li     // We store the virtual base class names and their offsets in a map to get
2077*67e74705SXin Li     // a stable order.
2078*67e74705SXin Li 
2079*67e74705SXin Li     std::map<std::string, CharUnits> ClassNamesAndOffsets;
2080*67e74705SXin Li     for (const auto &I : VBaseOffsetOffsets) {
2081*67e74705SXin Li       std::string ClassName = I.first->getQualifiedNameAsString();
2082*67e74705SXin Li       CharUnits OffsetOffset = I.second;
2083*67e74705SXin Li       ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
2084*67e74705SXin Li     }
2085*67e74705SXin Li 
2086*67e74705SXin Li     Out << "Virtual base offset offsets for '";
2087*67e74705SXin Li     MostDerivedClass->printQualifiedName(Out);
2088*67e74705SXin Li     Out << "' (";
2089*67e74705SXin Li     Out << ClassNamesAndOffsets.size();
2090*67e74705SXin Li     Out << (ClassNamesAndOffsets.size() == 1 ? " entry" : " entries") << ").\n";
2091*67e74705SXin Li 
2092*67e74705SXin Li     for (const auto &I : ClassNamesAndOffsets)
2093*67e74705SXin Li       Out << "   " << I.first << " | " << I.second.getQuantity() << '\n';
2094*67e74705SXin Li 
2095*67e74705SXin Li     Out << "\n";
2096*67e74705SXin Li   }
2097*67e74705SXin Li 
2098*67e74705SXin Li   if (!Thunks.empty()) {
2099*67e74705SXin Li     // We store the method names in a map to get a stable order.
2100*67e74705SXin Li     std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
2101*67e74705SXin Li 
2102*67e74705SXin Li     for (const auto &I : Thunks) {
2103*67e74705SXin Li       const CXXMethodDecl *MD = I.first;
2104*67e74705SXin Li       std::string MethodName =
2105*67e74705SXin Li         PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
2106*67e74705SXin Li                                     MD);
2107*67e74705SXin Li 
2108*67e74705SXin Li       MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
2109*67e74705SXin Li     }
2110*67e74705SXin Li 
2111*67e74705SXin Li     for (const auto &I : MethodNamesAndDecls) {
2112*67e74705SXin Li       const std::string &MethodName = I.first;
2113*67e74705SXin Li       const CXXMethodDecl *MD = I.second;
2114*67e74705SXin Li 
2115*67e74705SXin Li       ThunkInfoVectorTy ThunksVector = Thunks[MD];
2116*67e74705SXin Li       std::sort(ThunksVector.begin(), ThunksVector.end(),
2117*67e74705SXin Li                 [](const ThunkInfo &LHS, const ThunkInfo &RHS) {
2118*67e74705SXin Li         assert(LHS.Method == nullptr && RHS.Method == nullptr);
2119*67e74705SXin Li         return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return);
2120*67e74705SXin Li       });
2121*67e74705SXin Li 
2122*67e74705SXin Li       Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size();
2123*67e74705SXin Li       Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n";
2124*67e74705SXin Li 
2125*67e74705SXin Li       for (unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
2126*67e74705SXin Li         const ThunkInfo &Thunk = ThunksVector[I];
2127*67e74705SXin Li 
2128*67e74705SXin Li         Out << llvm::format("%4d | ", I);
2129*67e74705SXin Li 
2130*67e74705SXin Li         // If this function pointer has a return pointer adjustment, dump it.
2131*67e74705SXin Li         if (!Thunk.Return.isEmpty()) {
2132*67e74705SXin Li           Out << "return adjustment: " << Thunk.Return.NonVirtual;
2133*67e74705SXin Li           Out << " non-virtual";
2134*67e74705SXin Li           if (Thunk.Return.Virtual.Itanium.VBaseOffsetOffset) {
2135*67e74705SXin Li             Out << ", " << Thunk.Return.Virtual.Itanium.VBaseOffsetOffset;
2136*67e74705SXin Li             Out << " vbase offset offset";
2137*67e74705SXin Li           }
2138*67e74705SXin Li 
2139*67e74705SXin Li           if (!Thunk.This.isEmpty())
2140*67e74705SXin Li             Out << "\n       ";
2141*67e74705SXin Li         }
2142*67e74705SXin Li 
2143*67e74705SXin Li         // If this function pointer has a 'this' pointer adjustment, dump it.
2144*67e74705SXin Li         if (!Thunk.This.isEmpty()) {
2145*67e74705SXin Li           Out << "this adjustment: ";
2146*67e74705SXin Li           Out << Thunk.This.NonVirtual << " non-virtual";
2147*67e74705SXin Li 
2148*67e74705SXin Li           if (Thunk.This.Virtual.Itanium.VCallOffsetOffset) {
2149*67e74705SXin Li             Out << ", " << Thunk.This.Virtual.Itanium.VCallOffsetOffset;
2150*67e74705SXin Li             Out << " vcall offset offset";
2151*67e74705SXin Li           }
2152*67e74705SXin Li         }
2153*67e74705SXin Li 
2154*67e74705SXin Li         Out << '\n';
2155*67e74705SXin Li       }
2156*67e74705SXin Li 
2157*67e74705SXin Li       Out << '\n';
2158*67e74705SXin Li     }
2159*67e74705SXin Li   }
2160*67e74705SXin Li 
2161*67e74705SXin Li   // Compute the vtable indices for all the member functions.
2162*67e74705SXin Li   // Store them in a map keyed by the index so we'll get a sorted table.
2163*67e74705SXin Li   std::map<uint64_t, std::string> IndicesMap;
2164*67e74705SXin Li 
2165*67e74705SXin Li   for (const auto *MD : MostDerivedClass->methods()) {
2166*67e74705SXin Li     // We only want virtual member functions.
2167*67e74705SXin Li     if (!MD->isVirtual())
2168*67e74705SXin Li       continue;
2169*67e74705SXin Li     MD = MD->getCanonicalDecl();
2170*67e74705SXin Li 
2171*67e74705SXin Li     std::string MethodName =
2172*67e74705SXin Li       PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
2173*67e74705SXin Li                                   MD);
2174*67e74705SXin Li 
2175*67e74705SXin Li     if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2176*67e74705SXin Li       GlobalDecl GD(DD, Dtor_Complete);
2177*67e74705SXin Li       assert(MethodVTableIndices.count(GD));
2178*67e74705SXin Li       uint64_t VTableIndex = MethodVTableIndices[GD];
2179*67e74705SXin Li       IndicesMap[VTableIndex] = MethodName + " [complete]";
2180*67e74705SXin Li       IndicesMap[VTableIndex + 1] = MethodName + " [deleting]";
2181*67e74705SXin Li     } else {
2182*67e74705SXin Li       assert(MethodVTableIndices.count(MD));
2183*67e74705SXin Li       IndicesMap[MethodVTableIndices[MD]] = MethodName;
2184*67e74705SXin Li     }
2185*67e74705SXin Li   }
2186*67e74705SXin Li 
2187*67e74705SXin Li   // Print the vtable indices for all the member functions.
2188*67e74705SXin Li   if (!IndicesMap.empty()) {
2189*67e74705SXin Li     Out << "VTable indices for '";
2190*67e74705SXin Li     MostDerivedClass->printQualifiedName(Out);
2191*67e74705SXin Li     Out << "' (" << IndicesMap.size() << " entries).\n";
2192*67e74705SXin Li 
2193*67e74705SXin Li     for (const auto &I : IndicesMap) {
2194*67e74705SXin Li       uint64_t VTableIndex = I.first;
2195*67e74705SXin Li       const std::string &MethodName = I.second;
2196*67e74705SXin Li 
2197*67e74705SXin Li       Out << llvm::format("%4" PRIu64 " | ", VTableIndex) << MethodName
2198*67e74705SXin Li           << '\n';
2199*67e74705SXin Li     }
2200*67e74705SXin Li   }
2201*67e74705SXin Li 
2202*67e74705SXin Li   Out << '\n';
2203*67e74705SXin Li }
2204*67e74705SXin Li }
2205*67e74705SXin Li 
VTableLayout(uint64_t NumVTableComponents,const VTableComponent * VTableComponents,uint64_t NumVTableThunks,const VTableThunkTy * VTableThunks,const AddressPointsMapTy & AddressPoints,bool IsMicrosoftABI)2206*67e74705SXin Li VTableLayout::VTableLayout(uint64_t NumVTableComponents,
2207*67e74705SXin Li                            const VTableComponent *VTableComponents,
2208*67e74705SXin Li                            uint64_t NumVTableThunks,
2209*67e74705SXin Li                            const VTableThunkTy *VTableThunks,
2210*67e74705SXin Li                            const AddressPointsMapTy &AddressPoints,
2211*67e74705SXin Li                            bool IsMicrosoftABI)
2212*67e74705SXin Li   : NumVTableComponents(NumVTableComponents),
2213*67e74705SXin Li     VTableComponents(new VTableComponent[NumVTableComponents]),
2214*67e74705SXin Li     NumVTableThunks(NumVTableThunks),
2215*67e74705SXin Li     VTableThunks(new VTableThunkTy[NumVTableThunks]),
2216*67e74705SXin Li     AddressPoints(AddressPoints),
2217*67e74705SXin Li     IsMicrosoftABI(IsMicrosoftABI) {
2218*67e74705SXin Li   std::copy(VTableComponents, VTableComponents+NumVTableComponents,
2219*67e74705SXin Li             this->VTableComponents.get());
2220*67e74705SXin Li   std::copy(VTableThunks, VTableThunks+NumVTableThunks,
2221*67e74705SXin Li             this->VTableThunks.get());
2222*67e74705SXin Li   std::sort(this->VTableThunks.get(),
2223*67e74705SXin Li             this->VTableThunks.get() + NumVTableThunks,
2224*67e74705SXin Li             [](const VTableLayout::VTableThunkTy &LHS,
2225*67e74705SXin Li                const VTableLayout::VTableThunkTy &RHS) {
2226*67e74705SXin Li     assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
2227*67e74705SXin Li            "Different thunks should have unique indices!");
2228*67e74705SXin Li     return LHS.first < RHS.first;
2229*67e74705SXin Li   });
2230*67e74705SXin Li }
2231*67e74705SXin Li 
~VTableLayout()2232*67e74705SXin Li VTableLayout::~VTableLayout() { }
2233*67e74705SXin Li 
ItaniumVTableContext(ASTContext & Context)2234*67e74705SXin Li ItaniumVTableContext::ItaniumVTableContext(ASTContext &Context)
2235*67e74705SXin Li     : VTableContextBase(/*MS=*/false) {}
2236*67e74705SXin Li 
~ItaniumVTableContext()2237*67e74705SXin Li ItaniumVTableContext::~ItaniumVTableContext() {
2238*67e74705SXin Li   llvm::DeleteContainerSeconds(VTableLayouts);
2239*67e74705SXin Li }
2240*67e74705SXin Li 
getMethodVTableIndex(GlobalDecl GD)2241*67e74705SXin Li uint64_t ItaniumVTableContext::getMethodVTableIndex(GlobalDecl GD) {
2242*67e74705SXin Li   MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
2243*67e74705SXin Li   if (I != MethodVTableIndices.end())
2244*67e74705SXin Li     return I->second;
2245*67e74705SXin Li 
2246*67e74705SXin Li   const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
2247*67e74705SXin Li 
2248*67e74705SXin Li   computeVTableRelatedInformation(RD);
2249*67e74705SXin Li 
2250*67e74705SXin Li   I = MethodVTableIndices.find(GD);
2251*67e74705SXin Li   assert(I != MethodVTableIndices.end() && "Did not find index!");
2252*67e74705SXin Li   return I->second;
2253*67e74705SXin Li }
2254*67e74705SXin Li 
2255*67e74705SXin Li CharUnits
getVirtualBaseOffsetOffset(const CXXRecordDecl * RD,const CXXRecordDecl * VBase)2256*67e74705SXin Li ItaniumVTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
2257*67e74705SXin Li                                                  const CXXRecordDecl *VBase) {
2258*67e74705SXin Li   ClassPairTy ClassPair(RD, VBase);
2259*67e74705SXin Li 
2260*67e74705SXin Li   VirtualBaseClassOffsetOffsetsMapTy::iterator I =
2261*67e74705SXin Li     VirtualBaseClassOffsetOffsets.find(ClassPair);
2262*67e74705SXin Li   if (I != VirtualBaseClassOffsetOffsets.end())
2263*67e74705SXin Li     return I->second;
2264*67e74705SXin Li 
2265*67e74705SXin Li   VCallAndVBaseOffsetBuilder Builder(RD, RD, /*FinalOverriders=*/nullptr,
2266*67e74705SXin Li                                      BaseSubobject(RD, CharUnits::Zero()),
2267*67e74705SXin Li                                      /*BaseIsVirtual=*/false,
2268*67e74705SXin Li                                      /*OffsetInLayoutClass=*/CharUnits::Zero());
2269*67e74705SXin Li 
2270*67e74705SXin Li   for (const auto &I : Builder.getVBaseOffsetOffsets()) {
2271*67e74705SXin Li     // Insert all types.
2272*67e74705SXin Li     ClassPairTy ClassPair(RD, I.first);
2273*67e74705SXin Li 
2274*67e74705SXin Li     VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2275*67e74705SXin Li   }
2276*67e74705SXin Li 
2277*67e74705SXin Li   I = VirtualBaseClassOffsetOffsets.find(ClassPair);
2278*67e74705SXin Li   assert(I != VirtualBaseClassOffsetOffsets.end() && "Did not find index!");
2279*67e74705SXin Li 
2280*67e74705SXin Li   return I->second;
2281*67e74705SXin Li }
2282*67e74705SXin Li 
CreateVTableLayout(const ItaniumVTableBuilder & Builder)2283*67e74705SXin Li static VTableLayout *CreateVTableLayout(const ItaniumVTableBuilder &Builder) {
2284*67e74705SXin Li   SmallVector<VTableLayout::VTableThunkTy, 1>
2285*67e74705SXin Li     VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
2286*67e74705SXin Li 
2287*67e74705SXin Li   return new VTableLayout(Builder.getNumVTableComponents(),
2288*67e74705SXin Li                           Builder.vtable_component_begin(),
2289*67e74705SXin Li                           VTableThunks.size(),
2290*67e74705SXin Li                           VTableThunks.data(),
2291*67e74705SXin Li                           Builder.getAddressPoints(),
2292*67e74705SXin Li                           /*IsMicrosoftABI=*/false);
2293*67e74705SXin Li }
2294*67e74705SXin Li 
2295*67e74705SXin Li void
computeVTableRelatedInformation(const CXXRecordDecl * RD)2296*67e74705SXin Li ItaniumVTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD) {
2297*67e74705SXin Li   const VTableLayout *&Entry = VTableLayouts[RD];
2298*67e74705SXin Li 
2299*67e74705SXin Li   // Check if we've computed this information before.
2300*67e74705SXin Li   if (Entry)
2301*67e74705SXin Li     return;
2302*67e74705SXin Li 
2303*67e74705SXin Li   ItaniumVTableBuilder Builder(*this, RD, CharUnits::Zero(),
2304*67e74705SXin Li                                /*MostDerivedClassIsVirtual=*/0, RD);
2305*67e74705SXin Li   Entry = CreateVTableLayout(Builder);
2306*67e74705SXin Li 
2307*67e74705SXin Li   MethodVTableIndices.insert(Builder.vtable_indices_begin(),
2308*67e74705SXin Li                              Builder.vtable_indices_end());
2309*67e74705SXin Li 
2310*67e74705SXin Li   // Add the known thunks.
2311*67e74705SXin Li   Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
2312*67e74705SXin Li 
2313*67e74705SXin Li   // If we don't have the vbase information for this class, insert it.
2314*67e74705SXin Li   // getVirtualBaseOffsetOffset will compute it separately without computing
2315*67e74705SXin Li   // the rest of the vtable related information.
2316*67e74705SXin Li   if (!RD->getNumVBases())
2317*67e74705SXin Li     return;
2318*67e74705SXin Li 
2319*67e74705SXin Li   const CXXRecordDecl *VBase =
2320*67e74705SXin Li     RD->vbases_begin()->getType()->getAsCXXRecordDecl();
2321*67e74705SXin Li 
2322*67e74705SXin Li   if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
2323*67e74705SXin Li     return;
2324*67e74705SXin Li 
2325*67e74705SXin Li   for (const auto &I : Builder.getVBaseOffsetOffsets()) {
2326*67e74705SXin Li     // Insert all types.
2327*67e74705SXin Li     ClassPairTy ClassPair(RD, I.first);
2328*67e74705SXin Li 
2329*67e74705SXin Li     VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2330*67e74705SXin Li   }
2331*67e74705SXin Li }
2332*67e74705SXin Li 
createConstructionVTableLayout(const CXXRecordDecl * MostDerivedClass,CharUnits MostDerivedClassOffset,bool MostDerivedClassIsVirtual,const CXXRecordDecl * LayoutClass)2333*67e74705SXin Li VTableLayout *ItaniumVTableContext::createConstructionVTableLayout(
2334*67e74705SXin Li     const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset,
2335*67e74705SXin Li     bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass) {
2336*67e74705SXin Li   ItaniumVTableBuilder Builder(*this, MostDerivedClass, MostDerivedClassOffset,
2337*67e74705SXin Li                                MostDerivedClassIsVirtual, LayoutClass);
2338*67e74705SXin Li   return CreateVTableLayout(Builder);
2339*67e74705SXin Li }
2340*67e74705SXin Li 
2341*67e74705SXin Li namespace {
2342*67e74705SXin Li 
2343*67e74705SXin Li // Vtables in the Microsoft ABI are different from the Itanium ABI.
2344*67e74705SXin Li //
2345*67e74705SXin Li // The main differences are:
2346*67e74705SXin Li //  1. Separate vftable and vbtable.
2347*67e74705SXin Li //
2348*67e74705SXin Li //  2. Each subobject with a vfptr gets its own vftable rather than an address
2349*67e74705SXin Li //     point in a single vtable shared between all the subobjects.
2350*67e74705SXin Li //     Each vftable is represented by a separate section and virtual calls
2351*67e74705SXin Li //     must be done using the vftable which has a slot for the function to be
2352*67e74705SXin Li //     called.
2353*67e74705SXin Li //
2354*67e74705SXin Li //  3. Virtual method definitions expect their 'this' parameter to point to the
2355*67e74705SXin Li //     first vfptr whose table provides a compatible overridden method.  In many
2356*67e74705SXin Li //     cases, this permits the original vf-table entry to directly call
2357*67e74705SXin Li //     the method instead of passing through a thunk.
2358*67e74705SXin Li //     See example before VFTableBuilder::ComputeThisOffset below.
2359*67e74705SXin Li //
2360*67e74705SXin Li //     A compatible overridden method is one which does not have a non-trivial
2361*67e74705SXin Li //     covariant-return adjustment.
2362*67e74705SXin Li //
2363*67e74705SXin Li //     The first vfptr is the one with the lowest offset in the complete-object
2364*67e74705SXin Li //     layout of the defining class, and the method definition will subtract
2365*67e74705SXin Li //     that constant offset from the parameter value to get the real 'this'
2366*67e74705SXin Li //     value.  Therefore, if the offset isn't really constant (e.g. if a virtual
2367*67e74705SXin Li //     function defined in a virtual base is overridden in a more derived
2368*67e74705SXin Li //     virtual base and these bases have a reverse order in the complete
2369*67e74705SXin Li //     object), the vf-table may require a this-adjustment thunk.
2370*67e74705SXin Li //
2371*67e74705SXin Li //  4. vftables do not contain new entries for overrides that merely require
2372*67e74705SXin Li //     this-adjustment.  Together with #3, this keeps vf-tables smaller and
2373*67e74705SXin Li //     eliminates the need for this-adjustment thunks in many cases, at the cost
2374*67e74705SXin Li //     of often requiring redundant work to adjust the "this" pointer.
2375*67e74705SXin Li //
2376*67e74705SXin Li //  5. Instead of VTT and constructor vtables, vbtables and vtordisps are used.
2377*67e74705SXin Li //     Vtordisps are emitted into the class layout if a class has
2378*67e74705SXin Li //      a) a user-defined ctor/dtor
2379*67e74705SXin Li //     and
2380*67e74705SXin Li //      b) a method overriding a method in a virtual base.
2381*67e74705SXin Li //
2382*67e74705SXin Li //  To get a better understanding of this code,
2383*67e74705SXin Li //  you might want to see examples in test/CodeGenCXX/microsoft-abi-vtables-*.cpp
2384*67e74705SXin Li 
2385*67e74705SXin Li class VFTableBuilder {
2386*67e74705SXin Li public:
2387*67e74705SXin Li   typedef MicrosoftVTableContext::MethodVFTableLocation MethodVFTableLocation;
2388*67e74705SXin Li 
2389*67e74705SXin Li   typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
2390*67e74705SXin Li     MethodVFTableLocationsTy;
2391*67e74705SXin Li 
2392*67e74705SXin Li   typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator>
2393*67e74705SXin Li     method_locations_range;
2394*67e74705SXin Li 
2395*67e74705SXin Li private:
2396*67e74705SXin Li   /// VTables - Global vtable information.
2397*67e74705SXin Li   MicrosoftVTableContext &VTables;
2398*67e74705SXin Li 
2399*67e74705SXin Li   /// Context - The ASTContext which we will use for layout information.
2400*67e74705SXin Li   ASTContext &Context;
2401*67e74705SXin Li 
2402*67e74705SXin Li   /// MostDerivedClass - The most derived class for which we're building this
2403*67e74705SXin Li   /// vtable.
2404*67e74705SXin Li   const CXXRecordDecl *MostDerivedClass;
2405*67e74705SXin Li 
2406*67e74705SXin Li   const ASTRecordLayout &MostDerivedClassLayout;
2407*67e74705SXin Li 
2408*67e74705SXin Li   const VPtrInfo &WhichVFPtr;
2409*67e74705SXin Li 
2410*67e74705SXin Li   /// FinalOverriders - The final overriders of the most derived class.
2411*67e74705SXin Li   const FinalOverriders Overriders;
2412*67e74705SXin Li 
2413*67e74705SXin Li   /// Components - The components of the vftable being built.
2414*67e74705SXin Li   SmallVector<VTableComponent, 64> Components;
2415*67e74705SXin Li 
2416*67e74705SXin Li   MethodVFTableLocationsTy MethodVFTableLocations;
2417*67e74705SXin Li 
2418*67e74705SXin Li   /// \brief Does this class have an RTTI component?
2419*67e74705SXin Li   bool HasRTTIComponent = false;
2420*67e74705SXin Li 
2421*67e74705SXin Li   /// MethodInfo - Contains information about a method in a vtable.
2422*67e74705SXin Li   /// (Used for computing 'this' pointer adjustment thunks.
2423*67e74705SXin Li   struct MethodInfo {
2424*67e74705SXin Li     /// VBTableIndex - The nonzero index in the vbtable that
2425*67e74705SXin Li     /// this method's base has, or zero.
2426*67e74705SXin Li     const uint64_t VBTableIndex;
2427*67e74705SXin Li 
2428*67e74705SXin Li     /// VFTableIndex - The index in the vftable that this method has.
2429*67e74705SXin Li     const uint64_t VFTableIndex;
2430*67e74705SXin Li 
2431*67e74705SXin Li     /// Shadowed - Indicates if this vftable slot is shadowed by
2432*67e74705SXin Li     /// a slot for a covariant-return override. If so, it shouldn't be printed
2433*67e74705SXin Li     /// or used for vcalls in the most derived class.
2434*67e74705SXin Li     bool Shadowed;
2435*67e74705SXin Li 
2436*67e74705SXin Li     /// UsesExtraSlot - Indicates if this vftable slot was created because
2437*67e74705SXin Li     /// any of the overridden slots required a return adjusting thunk.
2438*67e74705SXin Li     bool UsesExtraSlot;
2439*67e74705SXin Li 
MethodInfo__anon965a958e0511::VFTableBuilder::MethodInfo2440*67e74705SXin Li     MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex,
2441*67e74705SXin Li                bool UsesExtraSlot = false)
2442*67e74705SXin Li         : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
2443*67e74705SXin Li           Shadowed(false), UsesExtraSlot(UsesExtraSlot) {}
2444*67e74705SXin Li 
MethodInfo__anon965a958e0511::VFTableBuilder::MethodInfo2445*67e74705SXin Li     MethodInfo()
2446*67e74705SXin Li         : VBTableIndex(0), VFTableIndex(0), Shadowed(false),
2447*67e74705SXin Li           UsesExtraSlot(false) {}
2448*67e74705SXin Li   };
2449*67e74705SXin Li 
2450*67e74705SXin Li   typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
2451*67e74705SXin Li 
2452*67e74705SXin Li   /// MethodInfoMap - The information for all methods in the vftable we're
2453*67e74705SXin Li   /// currently building.
2454*67e74705SXin Li   MethodInfoMapTy MethodInfoMap;
2455*67e74705SXin Li 
2456*67e74705SXin Li   typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
2457*67e74705SXin Li 
2458*67e74705SXin Li   /// VTableThunks - The thunks by vftable index in the vftable currently being
2459*67e74705SXin Li   /// built.
2460*67e74705SXin Li   VTableThunksMapTy VTableThunks;
2461*67e74705SXin Li 
2462*67e74705SXin Li   typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
2463*67e74705SXin Li   typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
2464*67e74705SXin Li 
2465*67e74705SXin Li   /// Thunks - A map that contains all the thunks needed for all methods in the
2466*67e74705SXin Li   /// most derived class for which the vftable is currently being built.
2467*67e74705SXin Li   ThunksMapTy Thunks;
2468*67e74705SXin Li 
2469*67e74705SXin Li   /// AddThunk - Add a thunk for the given method.
AddThunk(const CXXMethodDecl * MD,const ThunkInfo & Thunk)2470*67e74705SXin Li   void AddThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk) {
2471*67e74705SXin Li     SmallVector<ThunkInfo, 1> &ThunksVector = Thunks[MD];
2472*67e74705SXin Li 
2473*67e74705SXin Li     // Check if we have this thunk already.
2474*67e74705SXin Li     if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
2475*67e74705SXin Li         ThunksVector.end())
2476*67e74705SXin Li       return;
2477*67e74705SXin Li 
2478*67e74705SXin Li     ThunksVector.push_back(Thunk);
2479*67e74705SXin Li   }
2480*67e74705SXin Li 
2481*67e74705SXin Li   /// ComputeThisOffset - Returns the 'this' argument offset for the given
2482*67e74705SXin Li   /// method, relative to the beginning of the MostDerivedClass.
2483*67e74705SXin Li   CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
2484*67e74705SXin Li 
2485*67e74705SXin Li   void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
2486*67e74705SXin Li                                    CharUnits ThisOffset, ThisAdjustment &TA);
2487*67e74705SXin Li 
2488*67e74705SXin Li   /// AddMethod - Add a single virtual member function to the vftable
2489*67e74705SXin Li   /// components vector.
AddMethod(const CXXMethodDecl * MD,ThunkInfo TI)2490*67e74705SXin Li   void AddMethod(const CXXMethodDecl *MD, ThunkInfo TI) {
2491*67e74705SXin Li     if (!TI.isEmpty()) {
2492*67e74705SXin Li       VTableThunks[Components.size()] = TI;
2493*67e74705SXin Li       AddThunk(MD, TI);
2494*67e74705SXin Li     }
2495*67e74705SXin Li     if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2496*67e74705SXin Li       assert(TI.Return.isEmpty() &&
2497*67e74705SXin Li              "Destructor can't have return adjustment!");
2498*67e74705SXin Li       Components.push_back(VTableComponent::MakeDeletingDtor(DD));
2499*67e74705SXin Li     } else {
2500*67e74705SXin Li       Components.push_back(VTableComponent::MakeFunction(MD));
2501*67e74705SXin Li     }
2502*67e74705SXin Li   }
2503*67e74705SXin Li 
2504*67e74705SXin Li   /// AddMethods - Add the methods of this base subobject and the relevant
2505*67e74705SXin Li   /// subbases to the vftable we're currently laying out.
2506*67e74705SXin Li   void AddMethods(BaseSubobject Base, unsigned BaseDepth,
2507*67e74705SXin Li                   const CXXRecordDecl *LastVBase,
2508*67e74705SXin Li                   BasesSetVectorTy &VisitedBases);
2509*67e74705SXin Li 
LayoutVFTable()2510*67e74705SXin Li   void LayoutVFTable() {
2511*67e74705SXin Li     // RTTI data goes before all other entries.
2512*67e74705SXin Li     if (HasRTTIComponent)
2513*67e74705SXin Li       Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
2514*67e74705SXin Li 
2515*67e74705SXin Li     BasesSetVectorTy VisitedBases;
2516*67e74705SXin Li     AddMethods(BaseSubobject(MostDerivedClass, CharUnits::Zero()), 0, nullptr,
2517*67e74705SXin Li                VisitedBases);
2518*67e74705SXin Li     assert((HasRTTIComponent ? Components.size() - 1 : Components.size()) &&
2519*67e74705SXin Li            "vftable can't be empty");
2520*67e74705SXin Li 
2521*67e74705SXin Li     assert(MethodVFTableLocations.empty());
2522*67e74705SXin Li     for (const auto &I : MethodInfoMap) {
2523*67e74705SXin Li       const CXXMethodDecl *MD = I.first;
2524*67e74705SXin Li       const MethodInfo &MI = I.second;
2525*67e74705SXin Li       // Skip the methods that the MostDerivedClass didn't override
2526*67e74705SXin Li       // and the entries shadowed by return adjusting thunks.
2527*67e74705SXin Li       if (MD->getParent() != MostDerivedClass || MI.Shadowed)
2528*67e74705SXin Li         continue;
2529*67e74705SXin Li       MethodVFTableLocation Loc(MI.VBTableIndex, WhichVFPtr.getVBaseWithVPtr(),
2530*67e74705SXin Li                                 WhichVFPtr.NonVirtualOffset, MI.VFTableIndex);
2531*67e74705SXin Li       if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2532*67e74705SXin Li         MethodVFTableLocations[GlobalDecl(DD, Dtor_Deleting)] = Loc;
2533*67e74705SXin Li       } else {
2534*67e74705SXin Li         MethodVFTableLocations[MD] = Loc;
2535*67e74705SXin Li       }
2536*67e74705SXin Li     }
2537*67e74705SXin Li   }
2538*67e74705SXin Li 
2539*67e74705SXin Li public:
VFTableBuilder(MicrosoftVTableContext & VTables,const CXXRecordDecl * MostDerivedClass,const VPtrInfo * Which)2540*67e74705SXin Li   VFTableBuilder(MicrosoftVTableContext &VTables,
2541*67e74705SXin Li                  const CXXRecordDecl *MostDerivedClass, const VPtrInfo *Which)
2542*67e74705SXin Li       : VTables(VTables),
2543*67e74705SXin Li         Context(MostDerivedClass->getASTContext()),
2544*67e74705SXin Li         MostDerivedClass(MostDerivedClass),
2545*67e74705SXin Li         MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)),
2546*67e74705SXin Li         WhichVFPtr(*Which),
2547*67e74705SXin Li         Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) {
2548*67e74705SXin Li     // Provide the RTTI component if RTTIData is enabled. If the vftable would
2549*67e74705SXin Li     // be available externally, we should not provide the RTTI componenent. It
2550*67e74705SXin Li     // is currently impossible to get available externally vftables with either
2551*67e74705SXin Li     // dllimport or extern template instantiations, but eventually we may add a
2552*67e74705SXin Li     // flag to support additional devirtualization that needs this.
2553*67e74705SXin Li     if (Context.getLangOpts().RTTIData)
2554*67e74705SXin Li       HasRTTIComponent = true;
2555*67e74705SXin Li 
2556*67e74705SXin Li     LayoutVFTable();
2557*67e74705SXin Li 
2558*67e74705SXin Li     if (Context.getLangOpts().DumpVTableLayouts)
2559*67e74705SXin Li       dumpLayout(llvm::outs());
2560*67e74705SXin Li   }
2561*67e74705SXin Li 
getNumThunks() const2562*67e74705SXin Li   uint64_t getNumThunks() const { return Thunks.size(); }
2563*67e74705SXin Li 
thunks_begin() const2564*67e74705SXin Li   ThunksMapTy::const_iterator thunks_begin() const { return Thunks.begin(); }
2565*67e74705SXin Li 
thunks_end() const2566*67e74705SXin Li   ThunksMapTy::const_iterator thunks_end() const { return Thunks.end(); }
2567*67e74705SXin Li 
vtable_locations() const2568*67e74705SXin Li   method_locations_range vtable_locations() const {
2569*67e74705SXin Li     return method_locations_range(MethodVFTableLocations.begin(),
2570*67e74705SXin Li                                   MethodVFTableLocations.end());
2571*67e74705SXin Li   }
2572*67e74705SXin Li 
getNumVTableComponents() const2573*67e74705SXin Li   uint64_t getNumVTableComponents() const { return Components.size(); }
2574*67e74705SXin Li 
vtable_component_begin() const2575*67e74705SXin Li   const VTableComponent *vtable_component_begin() const {
2576*67e74705SXin Li     return Components.begin();
2577*67e74705SXin Li   }
2578*67e74705SXin Li 
vtable_component_end() const2579*67e74705SXin Li   const VTableComponent *vtable_component_end() const {
2580*67e74705SXin Li     return Components.end();
2581*67e74705SXin Li   }
2582*67e74705SXin Li 
vtable_thunks_begin() const2583*67e74705SXin Li   VTableThunksMapTy::const_iterator vtable_thunks_begin() const {
2584*67e74705SXin Li     return VTableThunks.begin();
2585*67e74705SXin Li   }
2586*67e74705SXin Li 
vtable_thunks_end() const2587*67e74705SXin Li   VTableThunksMapTy::const_iterator vtable_thunks_end() const {
2588*67e74705SXin Li     return VTableThunks.end();
2589*67e74705SXin Li   }
2590*67e74705SXin Li 
2591*67e74705SXin Li   void dumpLayout(raw_ostream &);
2592*67e74705SXin Li };
2593*67e74705SXin Li 
2594*67e74705SXin Li } // end namespace
2595*67e74705SXin Li 
2596*67e74705SXin Li // Let's study one class hierarchy as an example:
2597*67e74705SXin Li //   struct A {
2598*67e74705SXin Li //     virtual void f();
2599*67e74705SXin Li //     int x;
2600*67e74705SXin Li //   };
2601*67e74705SXin Li //
2602*67e74705SXin Li //   struct B : virtual A {
2603*67e74705SXin Li //     virtual void f();
2604*67e74705SXin Li //   };
2605*67e74705SXin Li //
2606*67e74705SXin Li // Record layouts:
2607*67e74705SXin Li //   struct A:
2608*67e74705SXin Li //   0 |   (A vftable pointer)
2609*67e74705SXin Li //   4 |   int x
2610*67e74705SXin Li //
2611*67e74705SXin Li //   struct B:
2612*67e74705SXin Li //   0 |   (B vbtable pointer)
2613*67e74705SXin Li //   4 |   struct A (virtual base)
2614*67e74705SXin Li //   4 |     (A vftable pointer)
2615*67e74705SXin Li //   8 |     int x
2616*67e74705SXin Li //
2617*67e74705SXin Li // Let's assume we have a pointer to the A part of an object of dynamic type B:
2618*67e74705SXin Li //   B b;
2619*67e74705SXin Li //   A *a = (A*)&b;
2620*67e74705SXin Li //   a->f();
2621*67e74705SXin Li //
2622*67e74705SXin Li // In this hierarchy, f() belongs to the vftable of A, so B::f() expects
2623*67e74705SXin Li // "this" parameter to point at the A subobject, which is B+4.
2624*67e74705SXin Li // In the B::f() prologue, it adjusts "this" back to B by subtracting 4,
2625*67e74705SXin Li // performed as a *static* adjustment.
2626*67e74705SXin Li //
2627*67e74705SXin Li // Interesting thing happens when we alter the relative placement of A and B
2628*67e74705SXin Li // subobjects in a class:
2629*67e74705SXin Li //   struct C : virtual B { };
2630*67e74705SXin Li //
2631*67e74705SXin Li //   C c;
2632*67e74705SXin Li //   A *a = (A*)&c;
2633*67e74705SXin Li //   a->f();
2634*67e74705SXin Li //
2635*67e74705SXin Li // Respective record layout is:
2636*67e74705SXin Li //   0 |   (C vbtable pointer)
2637*67e74705SXin Li //   4 |   struct A (virtual base)
2638*67e74705SXin Li //   4 |     (A vftable pointer)
2639*67e74705SXin Li //   8 |     int x
2640*67e74705SXin Li //  12 |   struct B (virtual base)
2641*67e74705SXin Li //  12 |     (B vbtable pointer)
2642*67e74705SXin Li //
2643*67e74705SXin Li // The final overrider of f() in class C is still B::f(), so B+4 should be
2644*67e74705SXin Li // passed as "this" to that code.  However, "a" points at B-8, so the respective
2645*67e74705SXin Li // vftable entry should hold a thunk that adds 12 to the "this" argument before
2646*67e74705SXin Li // performing a tail call to B::f().
2647*67e74705SXin Li //
2648*67e74705SXin Li // With this example in mind, we can now calculate the 'this' argument offset
2649*67e74705SXin Li // for the given method, relative to the beginning of the MostDerivedClass.
2650*67e74705SXin Li CharUnits
ComputeThisOffset(FinalOverriders::OverriderInfo Overrider)2651*67e74705SXin Li VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
2652*67e74705SXin Li   BasesSetVectorTy Bases;
2653*67e74705SXin Li 
2654*67e74705SXin Li   {
2655*67e74705SXin Li     // Find the set of least derived bases that define the given method.
2656*67e74705SXin Li     OverriddenMethodsSetTy VisitedOverriddenMethods;
2657*67e74705SXin Li     auto InitialOverriddenDefinitionCollector = [&](
2658*67e74705SXin Li         const CXXMethodDecl *OverriddenMD) {
2659*67e74705SXin Li       if (OverriddenMD->size_overridden_methods() == 0)
2660*67e74705SXin Li         Bases.insert(OverriddenMD->getParent());
2661*67e74705SXin Li       // Don't recurse on this method if we've already collected it.
2662*67e74705SXin Li       return VisitedOverriddenMethods.insert(OverriddenMD).second;
2663*67e74705SXin Li     };
2664*67e74705SXin Li     visitAllOverriddenMethods(Overrider.Method,
2665*67e74705SXin Li                               InitialOverriddenDefinitionCollector);
2666*67e74705SXin Li   }
2667*67e74705SXin Li 
2668*67e74705SXin Li   // If there are no overrides then 'this' is located
2669*67e74705SXin Li   // in the base that defines the method.
2670*67e74705SXin Li   if (Bases.size() == 0)
2671*67e74705SXin Li     return Overrider.Offset;
2672*67e74705SXin Li 
2673*67e74705SXin Li   CXXBasePaths Paths;
2674*67e74705SXin Li   Overrider.Method->getParent()->lookupInBases(
2675*67e74705SXin Li       [&Bases](const CXXBaseSpecifier *Specifier, CXXBasePath &) {
2676*67e74705SXin Li         return Bases.count(Specifier->getType()->getAsCXXRecordDecl());
2677*67e74705SXin Li       },
2678*67e74705SXin Li       Paths);
2679*67e74705SXin Li 
2680*67e74705SXin Li   // This will hold the smallest this offset among overridees of MD.
2681*67e74705SXin Li   // This implies that an offset of a non-virtual base will dominate an offset
2682*67e74705SXin Li   // of a virtual base to potentially reduce the number of thunks required
2683*67e74705SXin Li   // in the derived classes that inherit this method.
2684*67e74705SXin Li   CharUnits Ret;
2685*67e74705SXin Li   bool First = true;
2686*67e74705SXin Li 
2687*67e74705SXin Li   const ASTRecordLayout &OverriderRDLayout =
2688*67e74705SXin Li       Context.getASTRecordLayout(Overrider.Method->getParent());
2689*67e74705SXin Li   for (const CXXBasePath &Path : Paths) {
2690*67e74705SXin Li     CharUnits ThisOffset = Overrider.Offset;
2691*67e74705SXin Li     CharUnits LastVBaseOffset;
2692*67e74705SXin Li 
2693*67e74705SXin Li     // For each path from the overrider to the parents of the overridden
2694*67e74705SXin Li     // methods, traverse the path, calculating the this offset in the most
2695*67e74705SXin Li     // derived class.
2696*67e74705SXin Li     for (const CXXBasePathElement &Element : Path) {
2697*67e74705SXin Li       QualType CurTy = Element.Base->getType();
2698*67e74705SXin Li       const CXXRecordDecl *PrevRD = Element.Class,
2699*67e74705SXin Li                           *CurRD = CurTy->getAsCXXRecordDecl();
2700*67e74705SXin Li       const ASTRecordLayout &Layout = Context.getASTRecordLayout(PrevRD);
2701*67e74705SXin Li 
2702*67e74705SXin Li       if (Element.Base->isVirtual()) {
2703*67e74705SXin Li         // The interesting things begin when you have virtual inheritance.
2704*67e74705SXin Li         // The final overrider will use a static adjustment equal to the offset
2705*67e74705SXin Li         // of the vbase in the final overrider class.
2706*67e74705SXin Li         // For example, if the final overrider is in a vbase B of the most
2707*67e74705SXin Li         // derived class and it overrides a method of the B's own vbase A,
2708*67e74705SXin Li         // it uses A* as "this".  In its prologue, it can cast A* to B* with
2709*67e74705SXin Li         // a static offset.  This offset is used regardless of the actual
2710*67e74705SXin Li         // offset of A from B in the most derived class, requiring an
2711*67e74705SXin Li         // this-adjusting thunk in the vftable if A and B are laid out
2712*67e74705SXin Li         // differently in the most derived class.
2713*67e74705SXin Li         LastVBaseOffset = ThisOffset =
2714*67e74705SXin Li             Overrider.Offset + OverriderRDLayout.getVBaseClassOffset(CurRD);
2715*67e74705SXin Li       } else {
2716*67e74705SXin Li         ThisOffset += Layout.getBaseClassOffset(CurRD);
2717*67e74705SXin Li       }
2718*67e74705SXin Li     }
2719*67e74705SXin Li 
2720*67e74705SXin Li     if (isa<CXXDestructorDecl>(Overrider.Method)) {
2721*67e74705SXin Li       if (LastVBaseOffset.isZero()) {
2722*67e74705SXin Li         // If a "Base" class has at least one non-virtual base with a virtual
2723*67e74705SXin Li         // destructor, the "Base" virtual destructor will take the address
2724*67e74705SXin Li         // of the "Base" subobject as the "this" argument.
2725*67e74705SXin Li         ThisOffset = Overrider.Offset;
2726*67e74705SXin Li       } else {
2727*67e74705SXin Li         // A virtual destructor of a virtual base takes the address of the
2728*67e74705SXin Li         // virtual base subobject as the "this" argument.
2729*67e74705SXin Li         ThisOffset = LastVBaseOffset;
2730*67e74705SXin Li       }
2731*67e74705SXin Li     }
2732*67e74705SXin Li 
2733*67e74705SXin Li     if (Ret > ThisOffset || First) {
2734*67e74705SXin Li       First = false;
2735*67e74705SXin Li       Ret = ThisOffset;
2736*67e74705SXin Li     }
2737*67e74705SXin Li   }
2738*67e74705SXin Li 
2739*67e74705SXin Li   assert(!First && "Method not found in the given subobject?");
2740*67e74705SXin Li   return Ret;
2741*67e74705SXin Li }
2742*67e74705SXin Li 
2743*67e74705SXin Li // Things are getting even more complex when the "this" adjustment has to
2744*67e74705SXin Li // use a dynamic offset instead of a static one, or even two dynamic offsets.
2745*67e74705SXin Li // This is sometimes required when a virtual call happens in the middle of
2746*67e74705SXin Li // a non-most-derived class construction or destruction.
2747*67e74705SXin Li //
2748*67e74705SXin Li // Let's take a look at the following example:
2749*67e74705SXin Li //   struct A {
2750*67e74705SXin Li //     virtual void f();
2751*67e74705SXin Li //   };
2752*67e74705SXin Li //
2753*67e74705SXin Li //   void foo(A *a) { a->f(); }  // Knows nothing about siblings of A.
2754*67e74705SXin Li //
2755*67e74705SXin Li //   struct B : virtual A {
2756*67e74705SXin Li //     virtual void f();
2757*67e74705SXin Li //     B() {
2758*67e74705SXin Li //       foo(this);
2759*67e74705SXin Li //     }
2760*67e74705SXin Li //   };
2761*67e74705SXin Li //
2762*67e74705SXin Li //   struct C : virtual B {
2763*67e74705SXin Li //     virtual void f();
2764*67e74705SXin Li //   };
2765*67e74705SXin Li //
2766*67e74705SXin Li // Record layouts for these classes are:
2767*67e74705SXin Li //   struct A
2768*67e74705SXin Li //   0 |   (A vftable pointer)
2769*67e74705SXin Li //
2770*67e74705SXin Li //   struct B
2771*67e74705SXin Li //   0 |   (B vbtable pointer)
2772*67e74705SXin Li //   4 |   (vtordisp for vbase A)
2773*67e74705SXin Li //   8 |   struct A (virtual base)
2774*67e74705SXin Li //   8 |     (A vftable pointer)
2775*67e74705SXin Li //
2776*67e74705SXin Li //   struct C
2777*67e74705SXin Li //   0 |   (C vbtable pointer)
2778*67e74705SXin Li //   4 |   (vtordisp for vbase A)
2779*67e74705SXin Li //   8 |   struct A (virtual base)  // A precedes B!
2780*67e74705SXin Li //   8 |     (A vftable pointer)
2781*67e74705SXin Li //  12 |   struct B (virtual base)
2782*67e74705SXin Li //  12 |     (B vbtable pointer)
2783*67e74705SXin Li //
2784*67e74705SXin Li // When one creates an object of type C, the C constructor:
2785*67e74705SXin Li // - initializes all the vbptrs, then
2786*67e74705SXin Li // - calls the A subobject constructor
2787*67e74705SXin Li //   (initializes A's vfptr with an address of A vftable), then
2788*67e74705SXin Li // - calls the B subobject constructor
2789*67e74705SXin Li //   (initializes A's vfptr with an address of B vftable and vtordisp for A),
2790*67e74705SXin Li //   that in turn calls foo(), then
2791*67e74705SXin Li // - initializes A's vfptr with an address of C vftable and zeroes out the
2792*67e74705SXin Li //   vtordisp
2793*67e74705SXin Li //   FIXME: if a structor knows it belongs to MDC, why doesn't it use a vftable
2794*67e74705SXin Li //   without vtordisp thunks?
2795*67e74705SXin Li //   FIXME: how are vtordisp handled in the presence of nooverride/final?
2796*67e74705SXin Li //
2797*67e74705SXin Li // When foo() is called, an object with a layout of class C has a vftable
2798*67e74705SXin Li // referencing B::f() that assumes a B layout, so the "this" adjustments are
2799*67e74705SXin Li // incorrect, unless an extra adjustment is done.  This adjustment is called
2800*67e74705SXin Li // "vtordisp adjustment".  Vtordisp basically holds the difference between the
2801*67e74705SXin Li // actual location of a vbase in the layout class and the location assumed by
2802*67e74705SXin Li // the vftable of the class being constructed/destructed.  Vtordisp is only
2803*67e74705SXin Li // needed if "this" escapes a
2804*67e74705SXin Li // structor (or we can't prove otherwise).
2805*67e74705SXin Li // [i.e. vtordisp is a dynamic adjustment for a static adjustment, which is an
2806*67e74705SXin Li // estimation of a dynamic adjustment]
2807*67e74705SXin Li //
2808*67e74705SXin Li // foo() gets a pointer to the A vbase and doesn't know anything about B or C,
2809*67e74705SXin Li // so it just passes that pointer as "this" in a virtual call.
2810*67e74705SXin Li // If there was no vtordisp, that would just dispatch to B::f().
2811*67e74705SXin Li // However, B::f() assumes B+8 is passed as "this",
2812*67e74705SXin Li // yet the pointer foo() passes along is B-4 (i.e. C+8).
2813*67e74705SXin Li // An extra adjustment is needed, so we emit a thunk into the B vftable.
2814*67e74705SXin Li // This vtordisp thunk subtracts the value of vtordisp
2815*67e74705SXin Li // from the "this" argument (-12) before making a tailcall to B::f().
2816*67e74705SXin Li //
2817*67e74705SXin Li // Let's consider an even more complex example:
2818*67e74705SXin Li //   struct D : virtual B, virtual C {
2819*67e74705SXin Li //     D() {
2820*67e74705SXin Li //       foo(this);
2821*67e74705SXin Li //     }
2822*67e74705SXin Li //   };
2823*67e74705SXin Li //
2824*67e74705SXin Li //   struct D
2825*67e74705SXin Li //   0 |   (D vbtable pointer)
2826*67e74705SXin Li //   4 |   (vtordisp for vbase A)
2827*67e74705SXin Li //   8 |   struct A (virtual base)  // A precedes both B and C!
2828*67e74705SXin Li //   8 |     (A vftable pointer)
2829*67e74705SXin Li //  12 |   struct B (virtual base)  // B precedes C!
2830*67e74705SXin Li //  12 |     (B vbtable pointer)
2831*67e74705SXin Li //  16 |   struct C (virtual base)
2832*67e74705SXin Li //  16 |     (C vbtable pointer)
2833*67e74705SXin Li //
2834*67e74705SXin Li // When D::D() calls foo(), we find ourselves in a thunk that should tailcall
2835*67e74705SXin Li // to C::f(), which assumes C+8 as its "this" parameter.  This time, foo()
2836*67e74705SXin Li // passes along A, which is C-8.  The A vtordisp holds
2837*67e74705SXin Li //   "D.vbptr[index_of_A] - offset_of_A_in_D"
2838*67e74705SXin Li // and we statically know offset_of_A_in_D, so can get a pointer to D.
2839*67e74705SXin Li // When we know it, we can make an extra vbtable lookup to locate the C vbase
2840*67e74705SXin Li // and one extra static adjustment to calculate the expected value of C+8.
CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,CharUnits ThisOffset,ThisAdjustment & TA)2841*67e74705SXin Li void VFTableBuilder::CalculateVtordispAdjustment(
2842*67e74705SXin Li     FinalOverriders::OverriderInfo Overrider, CharUnits ThisOffset,
2843*67e74705SXin Li     ThisAdjustment &TA) {
2844*67e74705SXin Li   const ASTRecordLayout::VBaseOffsetsMapTy &VBaseMap =
2845*67e74705SXin Li       MostDerivedClassLayout.getVBaseOffsetsMap();
2846*67e74705SXin Li   const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2847*67e74705SXin Li       VBaseMap.find(WhichVFPtr.getVBaseWithVPtr());
2848*67e74705SXin Li   assert(VBaseMapEntry != VBaseMap.end());
2849*67e74705SXin Li 
2850*67e74705SXin Li   // If there's no vtordisp or the final overrider is defined in the same vbase
2851*67e74705SXin Li   // as the initial declaration, we don't need any vtordisp adjustment.
2852*67e74705SXin Li   if (!VBaseMapEntry->second.hasVtorDisp() ||
2853*67e74705SXin Li       Overrider.VirtualBase == WhichVFPtr.getVBaseWithVPtr())
2854*67e74705SXin Li     return;
2855*67e74705SXin Li 
2856*67e74705SXin Li   // OK, now we know we need to use a vtordisp thunk.
2857*67e74705SXin Li   // The implicit vtordisp field is located right before the vbase.
2858*67e74705SXin Li   CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
2859*67e74705SXin Li   TA.Virtual.Microsoft.VtordispOffset =
2860*67e74705SXin Li       (OffsetOfVBaseWithVFPtr - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4;
2861*67e74705SXin Li 
2862*67e74705SXin Li   // A simple vtordisp thunk will suffice if the final overrider is defined
2863*67e74705SXin Li   // in either the most derived class or its non-virtual base.
2864*67e74705SXin Li   if (Overrider.Method->getParent() == MostDerivedClass ||
2865*67e74705SXin Li       !Overrider.VirtualBase)
2866*67e74705SXin Li     return;
2867*67e74705SXin Li 
2868*67e74705SXin Li   // Otherwise, we need to do use the dynamic offset of the final overrider
2869*67e74705SXin Li   // in order to get "this" adjustment right.
2870*67e74705SXin Li   TA.Virtual.Microsoft.VBPtrOffset =
2871*67e74705SXin Li       (OffsetOfVBaseWithVFPtr + WhichVFPtr.NonVirtualOffset -
2872*67e74705SXin Li        MostDerivedClassLayout.getVBPtrOffset()).getQuantity();
2873*67e74705SXin Li   TA.Virtual.Microsoft.VBOffsetOffset =
2874*67e74705SXin Li       Context.getTypeSizeInChars(Context.IntTy).getQuantity() *
2875*67e74705SXin Li       VTables.getVBTableIndex(MostDerivedClass, Overrider.VirtualBase);
2876*67e74705SXin Li 
2877*67e74705SXin Li   TA.NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
2878*67e74705SXin Li }
2879*67e74705SXin Li 
GroupNewVirtualOverloads(const CXXRecordDecl * RD,SmallVector<const CXXMethodDecl *,10> & VirtualMethods)2880*67e74705SXin Li static void GroupNewVirtualOverloads(
2881*67e74705SXin Li     const CXXRecordDecl *RD,
2882*67e74705SXin Li     SmallVector<const CXXMethodDecl *, 10> &VirtualMethods) {
2883*67e74705SXin Li   // Put the virtual methods into VirtualMethods in the proper order:
2884*67e74705SXin Li   // 1) Group overloads by declaration name. New groups are added to the
2885*67e74705SXin Li   //    vftable in the order of their first declarations in this class
2886*67e74705SXin Li   //    (including overrides, non-virtual methods and any other named decl that
2887*67e74705SXin Li   //    might be nested within the class).
2888*67e74705SXin Li   // 2) In each group, new overloads appear in the reverse order of declaration.
2889*67e74705SXin Li   typedef SmallVector<const CXXMethodDecl *, 1> MethodGroup;
2890*67e74705SXin Li   SmallVector<MethodGroup, 10> Groups;
2891*67e74705SXin Li   typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
2892*67e74705SXin Li   VisitedGroupIndicesTy VisitedGroupIndices;
2893*67e74705SXin Li   for (const auto *D : RD->decls()) {
2894*67e74705SXin Li     const auto *ND = dyn_cast<NamedDecl>(D);
2895*67e74705SXin Li     if (!ND)
2896*67e74705SXin Li       continue;
2897*67e74705SXin Li     VisitedGroupIndicesTy::iterator J;
2898*67e74705SXin Li     bool Inserted;
2899*67e74705SXin Li     std::tie(J, Inserted) = VisitedGroupIndices.insert(
2900*67e74705SXin Li         std::make_pair(ND->getDeclName(), Groups.size()));
2901*67e74705SXin Li     if (Inserted)
2902*67e74705SXin Li       Groups.push_back(MethodGroup());
2903*67e74705SXin Li     if (const auto *MD = dyn_cast<CXXMethodDecl>(ND))
2904*67e74705SXin Li       if (MD->isVirtual())
2905*67e74705SXin Li         Groups[J->second].push_back(MD->getCanonicalDecl());
2906*67e74705SXin Li   }
2907*67e74705SXin Li 
2908*67e74705SXin Li   for (const MethodGroup &Group : Groups)
2909*67e74705SXin Li     VirtualMethods.append(Group.rbegin(), Group.rend());
2910*67e74705SXin Li }
2911*67e74705SXin Li 
isDirectVBase(const CXXRecordDecl * Base,const CXXRecordDecl * RD)2912*67e74705SXin Li static bool isDirectVBase(const CXXRecordDecl *Base, const CXXRecordDecl *RD) {
2913*67e74705SXin Li   for (const auto &B : RD->bases()) {
2914*67e74705SXin Li     if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() == Base)
2915*67e74705SXin Li       return true;
2916*67e74705SXin Li   }
2917*67e74705SXin Li   return false;
2918*67e74705SXin Li }
2919*67e74705SXin Li 
AddMethods(BaseSubobject Base,unsigned BaseDepth,const CXXRecordDecl * LastVBase,BasesSetVectorTy & VisitedBases)2920*67e74705SXin Li void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
2921*67e74705SXin Li                                 const CXXRecordDecl *LastVBase,
2922*67e74705SXin Li                                 BasesSetVectorTy &VisitedBases) {
2923*67e74705SXin Li   const CXXRecordDecl *RD = Base.getBase();
2924*67e74705SXin Li   if (!RD->isPolymorphic())
2925*67e74705SXin Li     return;
2926*67e74705SXin Li 
2927*67e74705SXin Li   const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
2928*67e74705SXin Li 
2929*67e74705SXin Li   // See if this class expands a vftable of the base we look at, which is either
2930*67e74705SXin Li   // the one defined by the vfptr base path or the primary base of the current
2931*67e74705SXin Li   // class.
2932*67e74705SXin Li   const CXXRecordDecl *NextBase = nullptr, *NextLastVBase = LastVBase;
2933*67e74705SXin Li   CharUnits NextBaseOffset;
2934*67e74705SXin Li   if (BaseDepth < WhichVFPtr.PathToBaseWithVPtr.size()) {
2935*67e74705SXin Li     NextBase = WhichVFPtr.PathToBaseWithVPtr[BaseDepth];
2936*67e74705SXin Li     if (isDirectVBase(NextBase, RD)) {
2937*67e74705SXin Li       NextLastVBase = NextBase;
2938*67e74705SXin Li       NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(NextBase);
2939*67e74705SXin Li     } else {
2940*67e74705SXin Li       NextBaseOffset =
2941*67e74705SXin Li           Base.getBaseOffset() + Layout.getBaseClassOffset(NextBase);
2942*67e74705SXin Li     }
2943*67e74705SXin Li   } else if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
2944*67e74705SXin Li     assert(!Layout.isPrimaryBaseVirtual() &&
2945*67e74705SXin Li            "No primary virtual bases in this ABI");
2946*67e74705SXin Li     NextBase = PrimaryBase;
2947*67e74705SXin Li     NextBaseOffset = Base.getBaseOffset();
2948*67e74705SXin Li   }
2949*67e74705SXin Li 
2950*67e74705SXin Li   if (NextBase) {
2951*67e74705SXin Li     AddMethods(BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
2952*67e74705SXin Li                NextLastVBase, VisitedBases);
2953*67e74705SXin Li     if (!VisitedBases.insert(NextBase))
2954*67e74705SXin Li       llvm_unreachable("Found a duplicate primary base!");
2955*67e74705SXin Li   }
2956*67e74705SXin Li 
2957*67e74705SXin Li   SmallVector<const CXXMethodDecl*, 10> VirtualMethods;
2958*67e74705SXin Li   // Put virtual methods in the proper order.
2959*67e74705SXin Li   GroupNewVirtualOverloads(RD, VirtualMethods);
2960*67e74705SXin Li 
2961*67e74705SXin Li   // Now go through all virtual member functions and add them to the current
2962*67e74705SXin Li   // vftable. This is done by
2963*67e74705SXin Li   //  - replacing overridden methods in their existing slots, as long as they
2964*67e74705SXin Li   //    don't require return adjustment; calculating This adjustment if needed.
2965*67e74705SXin Li   //  - adding new slots for methods of the current base not present in any
2966*67e74705SXin Li   //    sub-bases;
2967*67e74705SXin Li   //  - adding new slots for methods that require Return adjustment.
2968*67e74705SXin Li   // We keep track of the methods visited in the sub-bases in MethodInfoMap.
2969*67e74705SXin Li   for (const CXXMethodDecl *MD : VirtualMethods) {
2970*67e74705SXin Li     FinalOverriders::OverriderInfo FinalOverrider =
2971*67e74705SXin Li         Overriders.getOverrider(MD, Base.getBaseOffset());
2972*67e74705SXin Li     const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
2973*67e74705SXin Li     const CXXMethodDecl *OverriddenMD =
2974*67e74705SXin Li         FindNearestOverriddenMethod(MD, VisitedBases);
2975*67e74705SXin Li 
2976*67e74705SXin Li     ThisAdjustment ThisAdjustmentOffset;
2977*67e74705SXin Li     bool ReturnAdjustingThunk = false, ForceReturnAdjustmentMangling = false;
2978*67e74705SXin Li     CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
2979*67e74705SXin Li     ThisAdjustmentOffset.NonVirtual =
2980*67e74705SXin Li         (ThisOffset - WhichVFPtr.FullOffsetInMDC).getQuantity();
2981*67e74705SXin Li     if ((OverriddenMD || FinalOverriderMD != MD) &&
2982*67e74705SXin Li         WhichVFPtr.getVBaseWithVPtr())
2983*67e74705SXin Li       CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
2984*67e74705SXin Li                                   ThisAdjustmentOffset);
2985*67e74705SXin Li 
2986*67e74705SXin Li     if (OverriddenMD) {
2987*67e74705SXin Li       // If MD overrides anything in this vftable, we need to update the
2988*67e74705SXin Li       // entries.
2989*67e74705SXin Li       MethodInfoMapTy::iterator OverriddenMDIterator =
2990*67e74705SXin Li           MethodInfoMap.find(OverriddenMD);
2991*67e74705SXin Li 
2992*67e74705SXin Li       // If the overridden method went to a different vftable, skip it.
2993*67e74705SXin Li       if (OverriddenMDIterator == MethodInfoMap.end())
2994*67e74705SXin Li         continue;
2995*67e74705SXin Li 
2996*67e74705SXin Li       MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
2997*67e74705SXin Li 
2998*67e74705SXin Li       // Let's check if the overrider requires any return adjustments.
2999*67e74705SXin Li       // We must create a new slot if the MD's return type is not trivially
3000*67e74705SXin Li       // convertible to the OverriddenMD's one.
3001*67e74705SXin Li       // Once a chain of method overrides adds a return adjusting vftable slot,
3002*67e74705SXin Li       // all subsequent overrides will also use an extra method slot.
3003*67e74705SXin Li       ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
3004*67e74705SXin Li                                   Context, MD, OverriddenMD).isEmpty() ||
3005*67e74705SXin Li                              OverriddenMethodInfo.UsesExtraSlot;
3006*67e74705SXin Li 
3007*67e74705SXin Li       if (!ReturnAdjustingThunk) {
3008*67e74705SXin Li         // No return adjustment needed - just replace the overridden method info
3009*67e74705SXin Li         // with the current info.
3010*67e74705SXin Li         MethodInfo MI(OverriddenMethodInfo.VBTableIndex,
3011*67e74705SXin Li                       OverriddenMethodInfo.VFTableIndex);
3012*67e74705SXin Li         MethodInfoMap.erase(OverriddenMDIterator);
3013*67e74705SXin Li 
3014*67e74705SXin Li         assert(!MethodInfoMap.count(MD) &&
3015*67e74705SXin Li                "Should not have method info for this method yet!");
3016*67e74705SXin Li         MethodInfoMap.insert(std::make_pair(MD, MI));
3017*67e74705SXin Li         continue;
3018*67e74705SXin Li       }
3019*67e74705SXin Li 
3020*67e74705SXin Li       // In case we need a return adjustment, we'll add a new slot for
3021*67e74705SXin Li       // the overrider. Mark the overriden method as shadowed by the new slot.
3022*67e74705SXin Li       OverriddenMethodInfo.Shadowed = true;
3023*67e74705SXin Li 
3024*67e74705SXin Li       // Force a special name mangling for a return-adjusting thunk
3025*67e74705SXin Li       // unless the method is the final overrider without this adjustment.
3026*67e74705SXin Li       ForceReturnAdjustmentMangling =
3027*67e74705SXin Li           !(MD == FinalOverriderMD && ThisAdjustmentOffset.isEmpty());
3028*67e74705SXin Li     } else if (Base.getBaseOffset() != WhichVFPtr.FullOffsetInMDC ||
3029*67e74705SXin Li                MD->size_overridden_methods()) {
3030*67e74705SXin Li       // Skip methods that don't belong to the vftable of the current class,
3031*67e74705SXin Li       // e.g. each method that wasn't seen in any of the visited sub-bases
3032*67e74705SXin Li       // but overrides multiple methods of other sub-bases.
3033*67e74705SXin Li       continue;
3034*67e74705SXin Li     }
3035*67e74705SXin Li 
3036*67e74705SXin Li     // If we got here, MD is a method not seen in any of the sub-bases or
3037*67e74705SXin Li     // it requires return adjustment. Insert the method info for this method.
3038*67e74705SXin Li     unsigned VBIndex =
3039*67e74705SXin Li         LastVBase ? VTables.getVBTableIndex(MostDerivedClass, LastVBase) : 0;
3040*67e74705SXin Li     MethodInfo MI(VBIndex,
3041*67e74705SXin Li                   HasRTTIComponent ? Components.size() - 1 : Components.size(),
3042*67e74705SXin Li                   ReturnAdjustingThunk);
3043*67e74705SXin Li 
3044*67e74705SXin Li     assert(!MethodInfoMap.count(MD) &&
3045*67e74705SXin Li            "Should not have method info for this method yet!");
3046*67e74705SXin Li     MethodInfoMap.insert(std::make_pair(MD, MI));
3047*67e74705SXin Li 
3048*67e74705SXin Li     // Check if this overrider needs a return adjustment.
3049*67e74705SXin Li     // We don't want to do this for pure virtual member functions.
3050*67e74705SXin Li     BaseOffset ReturnAdjustmentOffset;
3051*67e74705SXin Li     ReturnAdjustment ReturnAdjustment;
3052*67e74705SXin Li     if (!FinalOverriderMD->isPure()) {
3053*67e74705SXin Li       ReturnAdjustmentOffset =
3054*67e74705SXin Li           ComputeReturnAdjustmentBaseOffset(Context, FinalOverriderMD, MD);
3055*67e74705SXin Li     }
3056*67e74705SXin Li     if (!ReturnAdjustmentOffset.isEmpty()) {
3057*67e74705SXin Li       ForceReturnAdjustmentMangling = true;
3058*67e74705SXin Li       ReturnAdjustment.NonVirtual =
3059*67e74705SXin Li           ReturnAdjustmentOffset.NonVirtualOffset.getQuantity();
3060*67e74705SXin Li       if (ReturnAdjustmentOffset.VirtualBase) {
3061*67e74705SXin Li         const ASTRecordLayout &DerivedLayout =
3062*67e74705SXin Li             Context.getASTRecordLayout(ReturnAdjustmentOffset.DerivedClass);
3063*67e74705SXin Li         ReturnAdjustment.Virtual.Microsoft.VBPtrOffset =
3064*67e74705SXin Li             DerivedLayout.getVBPtrOffset().getQuantity();
3065*67e74705SXin Li         ReturnAdjustment.Virtual.Microsoft.VBIndex =
3066*67e74705SXin Li             VTables.getVBTableIndex(ReturnAdjustmentOffset.DerivedClass,
3067*67e74705SXin Li                                     ReturnAdjustmentOffset.VirtualBase);
3068*67e74705SXin Li       }
3069*67e74705SXin Li     }
3070*67e74705SXin Li 
3071*67e74705SXin Li     AddMethod(FinalOverriderMD,
3072*67e74705SXin Li               ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment,
3073*67e74705SXin Li                         ForceReturnAdjustmentMangling ? MD : nullptr));
3074*67e74705SXin Li   }
3075*67e74705SXin Li }
3076*67e74705SXin Li 
PrintBasePath(const VPtrInfo::BasePath & Path,raw_ostream & Out)3077*67e74705SXin Li static void PrintBasePath(const VPtrInfo::BasePath &Path, raw_ostream &Out) {
3078*67e74705SXin Li   for (const CXXRecordDecl *Elem :
3079*67e74705SXin Li        llvm::make_range(Path.rbegin(), Path.rend())) {
3080*67e74705SXin Li     Out << "'";
3081*67e74705SXin Li     Elem->printQualifiedName(Out);
3082*67e74705SXin Li     Out << "' in ";
3083*67e74705SXin Li   }
3084*67e74705SXin Li }
3085*67e74705SXin Li 
dumpMicrosoftThunkAdjustment(const ThunkInfo & TI,raw_ostream & Out,bool ContinueFirstLine)3086*67e74705SXin Li static void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out,
3087*67e74705SXin Li                                          bool ContinueFirstLine) {
3088*67e74705SXin Li   const ReturnAdjustment &R = TI.Return;
3089*67e74705SXin Li   bool Multiline = false;
3090*67e74705SXin Li   const char *LinePrefix = "\n       ";
3091*67e74705SXin Li   if (!R.isEmpty() || TI.Method) {
3092*67e74705SXin Li     if (!ContinueFirstLine)
3093*67e74705SXin Li       Out << LinePrefix;
3094*67e74705SXin Li     Out << "[return adjustment (to type '"
3095*67e74705SXin Li         << TI.Method->getReturnType().getCanonicalType().getAsString()
3096*67e74705SXin Li         << "'): ";
3097*67e74705SXin Li     if (R.Virtual.Microsoft.VBPtrOffset)
3098*67e74705SXin Li       Out << "vbptr at offset " << R.Virtual.Microsoft.VBPtrOffset << ", ";
3099*67e74705SXin Li     if (R.Virtual.Microsoft.VBIndex)
3100*67e74705SXin Li       Out << "vbase #" << R.Virtual.Microsoft.VBIndex << ", ";
3101*67e74705SXin Li     Out << R.NonVirtual << " non-virtual]";
3102*67e74705SXin Li     Multiline = true;
3103*67e74705SXin Li   }
3104*67e74705SXin Li 
3105*67e74705SXin Li   const ThisAdjustment &T = TI.This;
3106*67e74705SXin Li   if (!T.isEmpty()) {
3107*67e74705SXin Li     if (Multiline || !ContinueFirstLine)
3108*67e74705SXin Li       Out << LinePrefix;
3109*67e74705SXin Li     Out << "[this adjustment: ";
3110*67e74705SXin Li     if (!TI.This.Virtual.isEmpty()) {
3111*67e74705SXin Li       assert(T.Virtual.Microsoft.VtordispOffset < 0);
3112*67e74705SXin Li       Out << "vtordisp at " << T.Virtual.Microsoft.VtordispOffset << ", ";
3113*67e74705SXin Li       if (T.Virtual.Microsoft.VBPtrOffset) {
3114*67e74705SXin Li         Out << "vbptr at " << T.Virtual.Microsoft.VBPtrOffset
3115*67e74705SXin Li             << " to the left,";
3116*67e74705SXin Li         assert(T.Virtual.Microsoft.VBOffsetOffset > 0);
3117*67e74705SXin Li         Out << LinePrefix << " vboffset at "
3118*67e74705SXin Li             << T.Virtual.Microsoft.VBOffsetOffset << " in the vbtable, ";
3119*67e74705SXin Li       }
3120*67e74705SXin Li     }
3121*67e74705SXin Li     Out << T.NonVirtual << " non-virtual]";
3122*67e74705SXin Li   }
3123*67e74705SXin Li }
3124*67e74705SXin Li 
dumpLayout(raw_ostream & Out)3125*67e74705SXin Li void VFTableBuilder::dumpLayout(raw_ostream &Out) {
3126*67e74705SXin Li   Out << "VFTable for ";
3127*67e74705SXin Li   PrintBasePath(WhichVFPtr.PathToBaseWithVPtr, Out);
3128*67e74705SXin Li   Out << "'";
3129*67e74705SXin Li   MostDerivedClass->printQualifiedName(Out);
3130*67e74705SXin Li   Out << "' (" << Components.size()
3131*67e74705SXin Li       << (Components.size() == 1 ? " entry" : " entries") << ").\n";
3132*67e74705SXin Li 
3133*67e74705SXin Li   for (unsigned I = 0, E = Components.size(); I != E; ++I) {
3134*67e74705SXin Li     Out << llvm::format("%4d | ", I);
3135*67e74705SXin Li 
3136*67e74705SXin Li     const VTableComponent &Component = Components[I];
3137*67e74705SXin Li 
3138*67e74705SXin Li     // Dump the component.
3139*67e74705SXin Li     switch (Component.getKind()) {
3140*67e74705SXin Li     case VTableComponent::CK_RTTI:
3141*67e74705SXin Li       Component.getRTTIDecl()->printQualifiedName(Out);
3142*67e74705SXin Li       Out << " RTTI";
3143*67e74705SXin Li       break;
3144*67e74705SXin Li 
3145*67e74705SXin Li     case VTableComponent::CK_FunctionPointer: {
3146*67e74705SXin Li       const CXXMethodDecl *MD = Component.getFunctionDecl();
3147*67e74705SXin Li 
3148*67e74705SXin Li       // FIXME: Figure out how to print the real thunk type, since they can
3149*67e74705SXin Li       // differ in the return type.
3150*67e74705SXin Li       std::string Str = PredefinedExpr::ComputeName(
3151*67e74705SXin Li           PredefinedExpr::PrettyFunctionNoVirtual, MD);
3152*67e74705SXin Li       Out << Str;
3153*67e74705SXin Li       if (MD->isPure())
3154*67e74705SXin Li         Out << " [pure]";
3155*67e74705SXin Li 
3156*67e74705SXin Li       if (MD->isDeleted())
3157*67e74705SXin Li         Out << " [deleted]";
3158*67e74705SXin Li 
3159*67e74705SXin Li       ThunkInfo Thunk = VTableThunks.lookup(I);
3160*67e74705SXin Li       if (!Thunk.isEmpty())
3161*67e74705SXin Li         dumpMicrosoftThunkAdjustment(Thunk, Out, /*ContinueFirstLine=*/false);
3162*67e74705SXin Li 
3163*67e74705SXin Li       break;
3164*67e74705SXin Li     }
3165*67e74705SXin Li 
3166*67e74705SXin Li     case VTableComponent::CK_DeletingDtorPointer: {
3167*67e74705SXin Li       const CXXDestructorDecl *DD = Component.getDestructorDecl();
3168*67e74705SXin Li 
3169*67e74705SXin Li       DD->printQualifiedName(Out);
3170*67e74705SXin Li       Out << "() [scalar deleting]";
3171*67e74705SXin Li 
3172*67e74705SXin Li       if (DD->isPure())
3173*67e74705SXin Li         Out << " [pure]";
3174*67e74705SXin Li 
3175*67e74705SXin Li       ThunkInfo Thunk = VTableThunks.lookup(I);
3176*67e74705SXin Li       if (!Thunk.isEmpty()) {
3177*67e74705SXin Li         assert(Thunk.Return.isEmpty() &&
3178*67e74705SXin Li                "No return adjustment needed for destructors!");
3179*67e74705SXin Li         dumpMicrosoftThunkAdjustment(Thunk, Out, /*ContinueFirstLine=*/false);
3180*67e74705SXin Li       }
3181*67e74705SXin Li 
3182*67e74705SXin Li       break;
3183*67e74705SXin Li     }
3184*67e74705SXin Li 
3185*67e74705SXin Li     default:
3186*67e74705SXin Li       DiagnosticsEngine &Diags = Context.getDiagnostics();
3187*67e74705SXin Li       unsigned DiagID = Diags.getCustomDiagID(
3188*67e74705SXin Li           DiagnosticsEngine::Error,
3189*67e74705SXin Li           "Unexpected vftable component type %0 for component number %1");
3190*67e74705SXin Li       Diags.Report(MostDerivedClass->getLocation(), DiagID)
3191*67e74705SXin Li           << I << Component.getKind();
3192*67e74705SXin Li     }
3193*67e74705SXin Li 
3194*67e74705SXin Li     Out << '\n';
3195*67e74705SXin Li   }
3196*67e74705SXin Li 
3197*67e74705SXin Li   Out << '\n';
3198*67e74705SXin Li 
3199*67e74705SXin Li   if (!Thunks.empty()) {
3200*67e74705SXin Li     // We store the method names in a map to get a stable order.
3201*67e74705SXin Li     std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3202*67e74705SXin Li 
3203*67e74705SXin Li     for (const auto &I : Thunks) {
3204*67e74705SXin Li       const CXXMethodDecl *MD = I.first;
3205*67e74705SXin Li       std::string MethodName = PredefinedExpr::ComputeName(
3206*67e74705SXin Li           PredefinedExpr::PrettyFunctionNoVirtual, MD);
3207*67e74705SXin Li 
3208*67e74705SXin Li       MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3209*67e74705SXin Li     }
3210*67e74705SXin Li 
3211*67e74705SXin Li     for (const auto &MethodNameAndDecl : MethodNamesAndDecls) {
3212*67e74705SXin Li       const std::string &MethodName = MethodNameAndDecl.first;
3213*67e74705SXin Li       const CXXMethodDecl *MD = MethodNameAndDecl.second;
3214*67e74705SXin Li 
3215*67e74705SXin Li       ThunkInfoVectorTy ThunksVector = Thunks[MD];
3216*67e74705SXin Li       std::stable_sort(ThunksVector.begin(), ThunksVector.end(),
3217*67e74705SXin Li                        [](const ThunkInfo &LHS, const ThunkInfo &RHS) {
3218*67e74705SXin Li         // Keep different thunks with the same adjustments in the order they
3219*67e74705SXin Li         // were put into the vector.
3220*67e74705SXin Li         return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return);
3221*67e74705SXin Li       });
3222*67e74705SXin Li 
3223*67e74705SXin Li       Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size();
3224*67e74705SXin Li       Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n";
3225*67e74705SXin Li 
3226*67e74705SXin Li       for (unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
3227*67e74705SXin Li         const ThunkInfo &Thunk = ThunksVector[I];
3228*67e74705SXin Li 
3229*67e74705SXin Li         Out << llvm::format("%4d | ", I);
3230*67e74705SXin Li         dumpMicrosoftThunkAdjustment(Thunk, Out, /*ContinueFirstLine=*/true);
3231*67e74705SXin Li         Out << '\n';
3232*67e74705SXin Li       }
3233*67e74705SXin Li 
3234*67e74705SXin Li       Out << '\n';
3235*67e74705SXin Li     }
3236*67e74705SXin Li   }
3237*67e74705SXin Li 
3238*67e74705SXin Li   Out.flush();
3239*67e74705SXin Li }
3240*67e74705SXin Li 
setsIntersect(const llvm::SmallPtrSet<const CXXRecordDecl *,4> & A,ArrayRef<const CXXRecordDecl * > B)3241*67e74705SXin Li static bool setsIntersect(const llvm::SmallPtrSet<const CXXRecordDecl *, 4> &A,
3242*67e74705SXin Li                           ArrayRef<const CXXRecordDecl *> B) {
3243*67e74705SXin Li   for (const CXXRecordDecl *Decl : B) {
3244*67e74705SXin Li     if (A.count(Decl))
3245*67e74705SXin Li       return true;
3246*67e74705SXin Li   }
3247*67e74705SXin Li   return false;
3248*67e74705SXin Li }
3249*67e74705SXin Li 
3250*67e74705SXin Li static bool rebucketPaths(VPtrInfoVector &Paths);
3251*67e74705SXin Li 
3252*67e74705SXin Li /// Produces MSVC-compatible vbtable data.  The symbols produced by this
3253*67e74705SXin Li /// algorithm match those produced by MSVC 2012 and newer, which is different
3254*67e74705SXin Li /// from MSVC 2010.
3255*67e74705SXin Li ///
3256*67e74705SXin Li /// MSVC 2012 appears to minimize the vbtable names using the following
3257*67e74705SXin Li /// algorithm.  First, walk the class hierarchy in the usual order, depth first,
3258*67e74705SXin Li /// left to right, to find all of the subobjects which contain a vbptr field.
3259*67e74705SXin Li /// Visiting each class node yields a list of inheritance paths to vbptrs.  Each
3260*67e74705SXin Li /// record with a vbptr creates an initially empty path.
3261*67e74705SXin Li ///
3262*67e74705SXin Li /// To combine paths from child nodes, the paths are compared to check for
3263*67e74705SXin Li /// ambiguity.  Paths are "ambiguous" if multiple paths have the same set of
3264*67e74705SXin Li /// components in the same order.  Each group of ambiguous paths is extended by
3265*67e74705SXin Li /// appending the class of the base from which it came.  If the current class
3266*67e74705SXin Li /// node produced an ambiguous path, its path is extended with the current class.
3267*67e74705SXin Li /// After extending paths, MSVC again checks for ambiguity, and extends any
3268*67e74705SXin Li /// ambiguous path which wasn't already extended.  Because each node yields an
3269*67e74705SXin Li /// unambiguous set of paths, MSVC doesn't need to extend any path more than once
3270*67e74705SXin Li /// to produce an unambiguous set of paths.
3271*67e74705SXin Li ///
3272*67e74705SXin Li /// TODO: Presumably vftables use the same algorithm.
computeVTablePaths(bool ForVBTables,const CXXRecordDecl * RD,VPtrInfoVector & Paths)3273*67e74705SXin Li void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables,
3274*67e74705SXin Li                                                 const CXXRecordDecl *RD,
3275*67e74705SXin Li                                                 VPtrInfoVector &Paths) {
3276*67e74705SXin Li   assert(Paths.empty());
3277*67e74705SXin Li   const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3278*67e74705SXin Li 
3279*67e74705SXin Li   // Base case: this subobject has its own vptr.
3280*67e74705SXin Li   if (ForVBTables ? Layout.hasOwnVBPtr() : Layout.hasOwnVFPtr())
3281*67e74705SXin Li     Paths.push_back(new VPtrInfo(RD));
3282*67e74705SXin Li 
3283*67e74705SXin Li   // Recursive case: get all the vbtables from our bases and remove anything
3284*67e74705SXin Li   // that shares a virtual base.
3285*67e74705SXin Li   llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
3286*67e74705SXin Li   for (const auto &B : RD->bases()) {
3287*67e74705SXin Li     const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
3288*67e74705SXin Li     if (B.isVirtual() && VBasesSeen.count(Base))
3289*67e74705SXin Li       continue;
3290*67e74705SXin Li 
3291*67e74705SXin Li     if (!Base->isDynamicClass())
3292*67e74705SXin Li       continue;
3293*67e74705SXin Li 
3294*67e74705SXin Li     const VPtrInfoVector &BasePaths =
3295*67e74705SXin Li         ForVBTables ? enumerateVBTables(Base) : getVFPtrOffsets(Base);
3296*67e74705SXin Li 
3297*67e74705SXin Li     for (VPtrInfo *BaseInfo : BasePaths) {
3298*67e74705SXin Li       // Don't include the path if it goes through a virtual base that we've
3299*67e74705SXin Li       // already included.
3300*67e74705SXin Li       if (setsIntersect(VBasesSeen, BaseInfo->ContainingVBases))
3301*67e74705SXin Li         continue;
3302*67e74705SXin Li 
3303*67e74705SXin Li       // Copy the path and adjust it as necessary.
3304*67e74705SXin Li       VPtrInfo *P = new VPtrInfo(*BaseInfo);
3305*67e74705SXin Li 
3306*67e74705SXin Li       // We mangle Base into the path if the path would've been ambiguous and it
3307*67e74705SXin Li       // wasn't already extended with Base.
3308*67e74705SXin Li       if (P->MangledPath.empty() || P->MangledPath.back() != Base)
3309*67e74705SXin Li         P->NextBaseToMangle = Base;
3310*67e74705SXin Li 
3311*67e74705SXin Li       // Keep track of which vtable the derived class is going to extend with
3312*67e74705SXin Li       // new methods or bases.  We append to either the vftable of our primary
3313*67e74705SXin Li       // base, or the first non-virtual base that has a vbtable.
3314*67e74705SXin Li       if (P->ReusingBase == Base &&
3315*67e74705SXin Li           Base == (ForVBTables ? Layout.getBaseSharingVBPtr()
3316*67e74705SXin Li                                : Layout.getPrimaryBase()))
3317*67e74705SXin Li         P->ReusingBase = RD;
3318*67e74705SXin Li 
3319*67e74705SXin Li       // Keep track of the full adjustment from the MDC to this vtable.  The
3320*67e74705SXin Li       // adjustment is captured by an optional vbase and a non-virtual offset.
3321*67e74705SXin Li       if (B.isVirtual())
3322*67e74705SXin Li         P->ContainingVBases.push_back(Base);
3323*67e74705SXin Li       else if (P->ContainingVBases.empty())
3324*67e74705SXin Li         P->NonVirtualOffset += Layout.getBaseClassOffset(Base);
3325*67e74705SXin Li 
3326*67e74705SXin Li       // Update the full offset in the MDC.
3327*67e74705SXin Li       P->FullOffsetInMDC = P->NonVirtualOffset;
3328*67e74705SXin Li       if (const CXXRecordDecl *VB = P->getVBaseWithVPtr())
3329*67e74705SXin Li         P->FullOffsetInMDC += Layout.getVBaseClassOffset(VB);
3330*67e74705SXin Li 
3331*67e74705SXin Li       Paths.push_back(P);
3332*67e74705SXin Li     }
3333*67e74705SXin Li 
3334*67e74705SXin Li     if (B.isVirtual())
3335*67e74705SXin Li       VBasesSeen.insert(Base);
3336*67e74705SXin Li 
3337*67e74705SXin Li     // After visiting any direct base, we've transitively visited all of its
3338*67e74705SXin Li     // morally virtual bases.
3339*67e74705SXin Li     for (const auto &VB : Base->vbases())
3340*67e74705SXin Li       VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3341*67e74705SXin Li   }
3342*67e74705SXin Li 
3343*67e74705SXin Li   // Sort the paths into buckets, and if any of them are ambiguous, extend all
3344*67e74705SXin Li   // paths in ambiguous buckets.
3345*67e74705SXin Li   bool Changed = true;
3346*67e74705SXin Li   while (Changed)
3347*67e74705SXin Li     Changed = rebucketPaths(Paths);
3348*67e74705SXin Li }
3349*67e74705SXin Li 
extendPath(VPtrInfo * P)3350*67e74705SXin Li static bool extendPath(VPtrInfo *P) {
3351*67e74705SXin Li   if (P->NextBaseToMangle) {
3352*67e74705SXin Li     P->MangledPath.push_back(P->NextBaseToMangle);
3353*67e74705SXin Li     P->NextBaseToMangle = nullptr;// Prevent the path from being extended twice.
3354*67e74705SXin Li     return true;
3355*67e74705SXin Li   }
3356*67e74705SXin Li   return false;
3357*67e74705SXin Li }
3358*67e74705SXin Li 
rebucketPaths(VPtrInfoVector & Paths)3359*67e74705SXin Li static bool rebucketPaths(VPtrInfoVector &Paths) {
3360*67e74705SXin Li   // What we're essentially doing here is bucketing together ambiguous paths.
3361*67e74705SXin Li   // Any bucket with more than one path in it gets extended by NextBase, which
3362*67e74705SXin Li   // is usually the direct base of the inherited the vbptr.  This code uses a
3363*67e74705SXin Li   // sorted vector to implement a multiset to form the buckets.  Note that the
3364*67e74705SXin Li   // ordering is based on pointers, but it doesn't change our output order.  The
3365*67e74705SXin Li   // current algorithm is designed to match MSVC 2012's names.
3366*67e74705SXin Li   VPtrInfoVector PathsSorted(Paths);
3367*67e74705SXin Li   std::sort(PathsSorted.begin(), PathsSorted.end(),
3368*67e74705SXin Li             [](const VPtrInfo *LHS, const VPtrInfo *RHS) {
3369*67e74705SXin Li     return LHS->MangledPath < RHS->MangledPath;
3370*67e74705SXin Li   });
3371*67e74705SXin Li   bool Changed = false;
3372*67e74705SXin Li   for (size_t I = 0, E = PathsSorted.size(); I != E;) {
3373*67e74705SXin Li     // Scan forward to find the end of the bucket.
3374*67e74705SXin Li     size_t BucketStart = I;
3375*67e74705SXin Li     do {
3376*67e74705SXin Li       ++I;
3377*67e74705SXin Li     } while (I != E && PathsSorted[BucketStart]->MangledPath ==
3378*67e74705SXin Li                            PathsSorted[I]->MangledPath);
3379*67e74705SXin Li 
3380*67e74705SXin Li     // If this bucket has multiple paths, extend them all.
3381*67e74705SXin Li     if (I - BucketStart > 1) {
3382*67e74705SXin Li       for (size_t II = BucketStart; II != I; ++II)
3383*67e74705SXin Li         Changed |= extendPath(PathsSorted[II]);
3384*67e74705SXin Li       assert(Changed && "no paths were extended to fix ambiguity");
3385*67e74705SXin Li     }
3386*67e74705SXin Li   }
3387*67e74705SXin Li   return Changed;
3388*67e74705SXin Li }
3389*67e74705SXin Li 
~MicrosoftVTableContext()3390*67e74705SXin Li MicrosoftVTableContext::~MicrosoftVTableContext() {
3391*67e74705SXin Li   for (auto &P : VFPtrLocations)
3392*67e74705SXin Li     llvm::DeleteContainerPointers(*P.second);
3393*67e74705SXin Li   llvm::DeleteContainerSeconds(VFPtrLocations);
3394*67e74705SXin Li   llvm::DeleteContainerSeconds(VFTableLayouts);
3395*67e74705SXin Li   llvm::DeleteContainerSeconds(VBaseInfo);
3396*67e74705SXin Li }
3397*67e74705SXin Li 
3398*67e74705SXin Li namespace {
3399*67e74705SXin Li typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
3400*67e74705SXin Li                         llvm::DenseSet<BaseSubobject>> FullPathTy;
3401*67e74705SXin Li }
3402*67e74705SXin Li 
3403*67e74705SXin Li // This recursive function finds all paths from a subobject centered at
3404*67e74705SXin Li // (RD, Offset) to the subobject located at BaseWithVPtr.
findPathsToSubobject(ASTContext & Context,const ASTRecordLayout & MostDerivedLayout,const CXXRecordDecl * RD,CharUnits Offset,BaseSubobject BaseWithVPtr,FullPathTy & FullPath,std::list<FullPathTy> & Paths)3405*67e74705SXin Li static void findPathsToSubobject(ASTContext &Context,
3406*67e74705SXin Li                                  const ASTRecordLayout &MostDerivedLayout,
3407*67e74705SXin Li                                  const CXXRecordDecl *RD, CharUnits Offset,
3408*67e74705SXin Li                                  BaseSubobject BaseWithVPtr,
3409*67e74705SXin Li                                  FullPathTy &FullPath,
3410*67e74705SXin Li                                  std::list<FullPathTy> &Paths) {
3411*67e74705SXin Li   if (BaseSubobject(RD, Offset) == BaseWithVPtr) {
3412*67e74705SXin Li     Paths.push_back(FullPath);
3413*67e74705SXin Li     return;
3414*67e74705SXin Li   }
3415*67e74705SXin Li 
3416*67e74705SXin Li   const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3417*67e74705SXin Li 
3418*67e74705SXin Li   for (const CXXBaseSpecifier &BS : RD->bases()) {
3419*67e74705SXin Li     const CXXRecordDecl *Base = BS.getType()->getAsCXXRecordDecl();
3420*67e74705SXin Li     CharUnits NewOffset = BS.isVirtual()
3421*67e74705SXin Li                               ? MostDerivedLayout.getVBaseClassOffset(Base)
3422*67e74705SXin Li                               : Offset + Layout.getBaseClassOffset(Base);
3423*67e74705SXin Li     FullPath.insert(BaseSubobject(Base, NewOffset));
3424*67e74705SXin Li     findPathsToSubobject(Context, MostDerivedLayout, Base, NewOffset,
3425*67e74705SXin Li                          BaseWithVPtr, FullPath, Paths);
3426*67e74705SXin Li     FullPath.pop_back();
3427*67e74705SXin Li   }
3428*67e74705SXin Li }
3429*67e74705SXin Li 
3430*67e74705SXin Li // Return the paths which are not subsets of other paths.
removeRedundantPaths(std::list<FullPathTy> & FullPaths)3431*67e74705SXin Li static void removeRedundantPaths(std::list<FullPathTy> &FullPaths) {
3432*67e74705SXin Li   FullPaths.remove_if([&](const FullPathTy &SpecificPath) {
3433*67e74705SXin Li     for (const FullPathTy &OtherPath : FullPaths) {
3434*67e74705SXin Li       if (&SpecificPath == &OtherPath)
3435*67e74705SXin Li         continue;
3436*67e74705SXin Li       if (std::all_of(SpecificPath.begin(), SpecificPath.end(),
3437*67e74705SXin Li                       [&](const BaseSubobject &BSO) {
3438*67e74705SXin Li                         return OtherPath.count(BSO) != 0;
3439*67e74705SXin Li                       })) {
3440*67e74705SXin Li         return true;
3441*67e74705SXin Li       }
3442*67e74705SXin Li     }
3443*67e74705SXin Li     return false;
3444*67e74705SXin Li   });
3445*67e74705SXin Li }
3446*67e74705SXin Li 
getOffsetOfFullPath(ASTContext & Context,const CXXRecordDecl * RD,const FullPathTy & FullPath)3447*67e74705SXin Li static CharUnits getOffsetOfFullPath(ASTContext &Context,
3448*67e74705SXin Li                                      const CXXRecordDecl *RD,
3449*67e74705SXin Li                                      const FullPathTy &FullPath) {
3450*67e74705SXin Li   const ASTRecordLayout &MostDerivedLayout =
3451*67e74705SXin Li       Context.getASTRecordLayout(RD);
3452*67e74705SXin Li   CharUnits Offset = CharUnits::fromQuantity(-1);
3453*67e74705SXin Li   for (const BaseSubobject &BSO : FullPath) {
3454*67e74705SXin Li     const CXXRecordDecl *Base = BSO.getBase();
3455*67e74705SXin Li     // The first entry in the path is always the most derived record, skip it.
3456*67e74705SXin Li     if (Base == RD) {
3457*67e74705SXin Li       assert(Offset.getQuantity() == -1);
3458*67e74705SXin Li       Offset = CharUnits::Zero();
3459*67e74705SXin Li       continue;
3460*67e74705SXin Li     }
3461*67e74705SXin Li     assert(Offset.getQuantity() != -1);
3462*67e74705SXin Li     const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3463*67e74705SXin Li     // While we know which base has to be traversed, we don't know if that base
3464*67e74705SXin Li     // was a virtual base.
3465*67e74705SXin Li     const CXXBaseSpecifier *BaseBS = std::find_if(
3466*67e74705SXin Li         RD->bases_begin(), RD->bases_end(), [&](const CXXBaseSpecifier &BS) {
3467*67e74705SXin Li           return BS.getType()->getAsCXXRecordDecl() == Base;
3468*67e74705SXin Li         });
3469*67e74705SXin Li     Offset = BaseBS->isVirtual() ? MostDerivedLayout.getVBaseClassOffset(Base)
3470*67e74705SXin Li                                  : Offset + Layout.getBaseClassOffset(Base);
3471*67e74705SXin Li     RD = Base;
3472*67e74705SXin Li   }
3473*67e74705SXin Li   return Offset;
3474*67e74705SXin Li }
3475*67e74705SXin Li 
3476*67e74705SXin Li // We want to select the path which introduces the most covariant overrides.  If
3477*67e74705SXin Li // two paths introduce overrides which the other path doesn't contain, issue a
3478*67e74705SXin Li // diagnostic.
selectBestPath(ASTContext & Context,const CXXRecordDecl * RD,VPtrInfo * Info,std::list<FullPathTy> & FullPaths)3479*67e74705SXin Li static const FullPathTy *selectBestPath(ASTContext &Context,
3480*67e74705SXin Li                                         const CXXRecordDecl *RD, VPtrInfo *Info,
3481*67e74705SXin Li                                         std::list<FullPathTy> &FullPaths) {
3482*67e74705SXin Li   // Handle some easy cases first.
3483*67e74705SXin Li   if (FullPaths.empty())
3484*67e74705SXin Li     return nullptr;
3485*67e74705SXin Li   if (FullPaths.size() == 1)
3486*67e74705SXin Li     return &FullPaths.front();
3487*67e74705SXin Li 
3488*67e74705SXin Li   const FullPathTy *BestPath = nullptr;
3489*67e74705SXin Li   typedef std::set<const CXXMethodDecl *> OverriderSetTy;
3490*67e74705SXin Li   OverriderSetTy LastOverrides;
3491*67e74705SXin Li   for (const FullPathTy &SpecificPath : FullPaths) {
3492*67e74705SXin Li     assert(!SpecificPath.empty());
3493*67e74705SXin Li     OverriderSetTy CurrentOverrides;
3494*67e74705SXin Li     const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
3495*67e74705SXin Li     // Find the distance from the start of the path to the subobject with the
3496*67e74705SXin Li     // VPtr.
3497*67e74705SXin Li     CharUnits BaseOffset =
3498*67e74705SXin Li         getOffsetOfFullPath(Context, TopLevelRD, SpecificPath);
3499*67e74705SXin Li     FinalOverriders Overriders(TopLevelRD, CharUnits::Zero(), TopLevelRD);
3500*67e74705SXin Li     for (const CXXMethodDecl *MD : Info->BaseWithVPtr->methods()) {
3501*67e74705SXin Li       if (!MD->isVirtual())
3502*67e74705SXin Li         continue;
3503*67e74705SXin Li       FinalOverriders::OverriderInfo OI =
3504*67e74705SXin Li           Overriders.getOverrider(MD->getCanonicalDecl(), BaseOffset);
3505*67e74705SXin Li       const CXXMethodDecl *OverridingMethod = OI.Method;
3506*67e74705SXin Li       // Only overriders which have a return adjustment introduce problematic
3507*67e74705SXin Li       // thunks.
3508*67e74705SXin Li       if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
3509*67e74705SXin Li               .isEmpty())
3510*67e74705SXin Li         continue;
3511*67e74705SXin Li       // It's possible that the overrider isn't in this path.  If so, skip it
3512*67e74705SXin Li       // because this path didn't introduce it.
3513*67e74705SXin Li       const CXXRecordDecl *OverridingParent = OverridingMethod->getParent();
3514*67e74705SXin Li       if (std::none_of(SpecificPath.begin(), SpecificPath.end(),
3515*67e74705SXin Li                        [&](const BaseSubobject &BSO) {
3516*67e74705SXin Li                          return BSO.getBase() == OverridingParent;
3517*67e74705SXin Li                        }))
3518*67e74705SXin Li         continue;
3519*67e74705SXin Li       CurrentOverrides.insert(OverridingMethod);
3520*67e74705SXin Li     }
3521*67e74705SXin Li     OverriderSetTy NewOverrides =
3522*67e74705SXin Li         llvm::set_difference(CurrentOverrides, LastOverrides);
3523*67e74705SXin Li     if (NewOverrides.empty())
3524*67e74705SXin Li       continue;
3525*67e74705SXin Li     OverriderSetTy MissingOverrides =
3526*67e74705SXin Li         llvm::set_difference(LastOverrides, CurrentOverrides);
3527*67e74705SXin Li     if (MissingOverrides.empty()) {
3528*67e74705SXin Li       // This path is a strict improvement over the last path, let's use it.
3529*67e74705SXin Li       BestPath = &SpecificPath;
3530*67e74705SXin Li       std::swap(CurrentOverrides, LastOverrides);
3531*67e74705SXin Li     } else {
3532*67e74705SXin Li       // This path introduces an overrider with a conflicting covariant thunk.
3533*67e74705SXin Li       DiagnosticsEngine &Diags = Context.getDiagnostics();
3534*67e74705SXin Li       const CXXMethodDecl *CovariantMD = *NewOverrides.begin();
3535*67e74705SXin Li       const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
3536*67e74705SXin Li       Diags.Report(RD->getLocation(), diag::err_vftable_ambiguous_component)
3537*67e74705SXin Li           << RD;
3538*67e74705SXin Li       Diags.Report(CovariantMD->getLocation(), diag::note_covariant_thunk)
3539*67e74705SXin Li           << CovariantMD;
3540*67e74705SXin Li       Diags.Report(ConflictMD->getLocation(), diag::note_covariant_thunk)
3541*67e74705SXin Li           << ConflictMD;
3542*67e74705SXin Li     }
3543*67e74705SXin Li   }
3544*67e74705SXin Li   // Go with the path that introduced the most covariant overrides.  If there is
3545*67e74705SXin Li   // no such path, pick the first path.
3546*67e74705SXin Li   return BestPath ? BestPath : &FullPaths.front();
3547*67e74705SXin Li }
3548*67e74705SXin Li 
computeFullPathsForVFTables(ASTContext & Context,const CXXRecordDecl * RD,VPtrInfoVector & Paths)3549*67e74705SXin Li static void computeFullPathsForVFTables(ASTContext &Context,
3550*67e74705SXin Li                                         const CXXRecordDecl *RD,
3551*67e74705SXin Li                                         VPtrInfoVector &Paths) {
3552*67e74705SXin Li   const ASTRecordLayout &MostDerivedLayout = Context.getASTRecordLayout(RD);
3553*67e74705SXin Li   FullPathTy FullPath;
3554*67e74705SXin Li   std::list<FullPathTy> FullPaths;
3555*67e74705SXin Li   for (VPtrInfo *Info : Paths) {
3556*67e74705SXin Li     findPathsToSubobject(
3557*67e74705SXin Li         Context, MostDerivedLayout, RD, CharUnits::Zero(),
3558*67e74705SXin Li         BaseSubobject(Info->BaseWithVPtr, Info->FullOffsetInMDC), FullPath,
3559*67e74705SXin Li         FullPaths);
3560*67e74705SXin Li     FullPath.clear();
3561*67e74705SXin Li     removeRedundantPaths(FullPaths);
3562*67e74705SXin Li     Info->PathToBaseWithVPtr.clear();
3563*67e74705SXin Li     if (const FullPathTy *BestPath =
3564*67e74705SXin Li             selectBestPath(Context, RD, Info, FullPaths))
3565*67e74705SXin Li       for (const BaseSubobject &BSO : *BestPath)
3566*67e74705SXin Li         Info->PathToBaseWithVPtr.push_back(BSO.getBase());
3567*67e74705SXin Li     FullPaths.clear();
3568*67e74705SXin Li   }
3569*67e74705SXin Li }
3570*67e74705SXin Li 
computeVTableRelatedInformation(const CXXRecordDecl * RD)3571*67e74705SXin Li void MicrosoftVTableContext::computeVTableRelatedInformation(
3572*67e74705SXin Li     const CXXRecordDecl *RD) {
3573*67e74705SXin Li   assert(RD->isDynamicClass());
3574*67e74705SXin Li 
3575*67e74705SXin Li   // Check if we've computed this information before.
3576*67e74705SXin Li   if (VFPtrLocations.count(RD))
3577*67e74705SXin Li     return;
3578*67e74705SXin Li 
3579*67e74705SXin Li   const VTableLayout::AddressPointsMapTy EmptyAddressPointsMap;
3580*67e74705SXin Li 
3581*67e74705SXin Li   VPtrInfoVector *VFPtrs = new VPtrInfoVector();
3582*67e74705SXin Li   computeVTablePaths(/*ForVBTables=*/false, RD, *VFPtrs);
3583*67e74705SXin Li   computeFullPathsForVFTables(Context, RD, *VFPtrs);
3584*67e74705SXin Li   VFPtrLocations[RD] = VFPtrs;
3585*67e74705SXin Li 
3586*67e74705SXin Li   MethodVFTableLocationsTy NewMethodLocations;
3587*67e74705SXin Li   for (const VPtrInfo *VFPtr : *VFPtrs) {
3588*67e74705SXin Li     VFTableBuilder Builder(*this, RD, VFPtr);
3589*67e74705SXin Li 
3590*67e74705SXin Li     VFTableIdTy id(RD, VFPtr->FullOffsetInMDC);
3591*67e74705SXin Li     assert(VFTableLayouts.count(id) == 0);
3592*67e74705SXin Li     SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks(
3593*67e74705SXin Li         Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
3594*67e74705SXin Li     VFTableLayouts[id] = new VTableLayout(
3595*67e74705SXin Li         Builder.getNumVTableComponents(), Builder.vtable_component_begin(),
3596*67e74705SXin Li         VTableThunks.size(), VTableThunks.data(), EmptyAddressPointsMap, true);
3597*67e74705SXin Li     Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
3598*67e74705SXin Li 
3599*67e74705SXin Li     for (const auto &Loc : Builder.vtable_locations()) {
3600*67e74705SXin Li       GlobalDecl GD = Loc.first;
3601*67e74705SXin Li       MethodVFTableLocation NewLoc = Loc.second;
3602*67e74705SXin Li       auto M = NewMethodLocations.find(GD);
3603*67e74705SXin Li       if (M == NewMethodLocations.end() || NewLoc < M->second)
3604*67e74705SXin Li         NewMethodLocations[GD] = NewLoc;
3605*67e74705SXin Li     }
3606*67e74705SXin Li   }
3607*67e74705SXin Li 
3608*67e74705SXin Li   MethodVFTableLocations.insert(NewMethodLocations.begin(),
3609*67e74705SXin Li                                 NewMethodLocations.end());
3610*67e74705SXin Li   if (Context.getLangOpts().DumpVTableLayouts)
3611*67e74705SXin Li     dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3612*67e74705SXin Li }
3613*67e74705SXin Li 
dumpMethodLocations(const CXXRecordDecl * RD,const MethodVFTableLocationsTy & NewMethods,raw_ostream & Out)3614*67e74705SXin Li void MicrosoftVTableContext::dumpMethodLocations(
3615*67e74705SXin Li     const CXXRecordDecl *RD, const MethodVFTableLocationsTy &NewMethods,
3616*67e74705SXin Li     raw_ostream &Out) {
3617*67e74705SXin Li   // Compute the vtable indices for all the member functions.
3618*67e74705SXin Li   // Store them in a map keyed by the location so we'll get a sorted table.
3619*67e74705SXin Li   std::map<MethodVFTableLocation, std::string> IndicesMap;
3620*67e74705SXin Li   bool HasNonzeroOffset = false;
3621*67e74705SXin Li 
3622*67e74705SXin Li   for (const auto &I : NewMethods) {
3623*67e74705SXin Li     const CXXMethodDecl *MD = cast<const CXXMethodDecl>(I.first.getDecl());
3624*67e74705SXin Li     assert(MD->isVirtual());
3625*67e74705SXin Li 
3626*67e74705SXin Li     std::string MethodName = PredefinedExpr::ComputeName(
3627*67e74705SXin Li         PredefinedExpr::PrettyFunctionNoVirtual, MD);
3628*67e74705SXin Li 
3629*67e74705SXin Li     if (isa<CXXDestructorDecl>(MD)) {
3630*67e74705SXin Li       IndicesMap[I.second] = MethodName + " [scalar deleting]";
3631*67e74705SXin Li     } else {
3632*67e74705SXin Li       IndicesMap[I.second] = MethodName;
3633*67e74705SXin Li     }
3634*67e74705SXin Li 
3635*67e74705SXin Li     if (!I.second.VFPtrOffset.isZero() || I.second.VBTableIndex != 0)
3636*67e74705SXin Li       HasNonzeroOffset = true;
3637*67e74705SXin Li   }
3638*67e74705SXin Li 
3639*67e74705SXin Li   // Print the vtable indices for all the member functions.
3640*67e74705SXin Li   if (!IndicesMap.empty()) {
3641*67e74705SXin Li     Out << "VFTable indices for ";
3642*67e74705SXin Li     Out << "'";
3643*67e74705SXin Li     RD->printQualifiedName(Out);
3644*67e74705SXin Li     Out << "' (" << IndicesMap.size()
3645*67e74705SXin Li         << (IndicesMap.size() == 1 ? " entry" : " entries") << ").\n";
3646*67e74705SXin Li 
3647*67e74705SXin Li     CharUnits LastVFPtrOffset = CharUnits::fromQuantity(-1);
3648*67e74705SXin Li     uint64_t LastVBIndex = 0;
3649*67e74705SXin Li     for (const auto &I : IndicesMap) {
3650*67e74705SXin Li       CharUnits VFPtrOffset = I.first.VFPtrOffset;
3651*67e74705SXin Li       uint64_t VBIndex = I.first.VBTableIndex;
3652*67e74705SXin Li       if (HasNonzeroOffset &&
3653*67e74705SXin Li           (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3654*67e74705SXin Li         assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3655*67e74705SXin Li         Out << " -- accessible via ";
3656*67e74705SXin Li         if (VBIndex)
3657*67e74705SXin Li           Out << "vbtable index " << VBIndex << ", ";
3658*67e74705SXin Li         Out << "vfptr at offset " << VFPtrOffset.getQuantity() << " --\n";
3659*67e74705SXin Li         LastVFPtrOffset = VFPtrOffset;
3660*67e74705SXin Li         LastVBIndex = VBIndex;
3661*67e74705SXin Li       }
3662*67e74705SXin Li 
3663*67e74705SXin Li       uint64_t VTableIndex = I.first.Index;
3664*67e74705SXin Li       const std::string &MethodName = I.second;
3665*67e74705SXin Li       Out << llvm::format("%4" PRIu64 " | ", VTableIndex) << MethodName << '\n';
3666*67e74705SXin Li     }
3667*67e74705SXin Li     Out << '\n';
3668*67e74705SXin Li   }
3669*67e74705SXin Li 
3670*67e74705SXin Li   Out.flush();
3671*67e74705SXin Li }
3672*67e74705SXin Li 
computeVBTableRelatedInformation(const CXXRecordDecl * RD)3673*67e74705SXin Li const VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation(
3674*67e74705SXin Li     const CXXRecordDecl *RD) {
3675*67e74705SXin Li   VirtualBaseInfo *VBI;
3676*67e74705SXin Li 
3677*67e74705SXin Li   {
3678*67e74705SXin Li     // Get or create a VBI for RD.  Don't hold a reference to the DenseMap cell,
3679*67e74705SXin Li     // as it may be modified and rehashed under us.
3680*67e74705SXin Li     VirtualBaseInfo *&Entry = VBaseInfo[RD];
3681*67e74705SXin Li     if (Entry)
3682*67e74705SXin Li       return Entry;
3683*67e74705SXin Li     Entry = VBI = new VirtualBaseInfo();
3684*67e74705SXin Li   }
3685*67e74705SXin Li 
3686*67e74705SXin Li   computeVTablePaths(/*ForVBTables=*/true, RD, VBI->VBPtrPaths);
3687*67e74705SXin Li 
3688*67e74705SXin Li   // First, see if the Derived class shared the vbptr with a non-virtual base.
3689*67e74705SXin Li   const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3690*67e74705SXin Li   if (const CXXRecordDecl *VBPtrBase = Layout.getBaseSharingVBPtr()) {
3691*67e74705SXin Li     // If the Derived class shares the vbptr with a non-virtual base, the shared
3692*67e74705SXin Li     // virtual bases come first so that the layout is the same.
3693*67e74705SXin Li     const VirtualBaseInfo *BaseInfo =
3694*67e74705SXin Li         computeVBTableRelatedInformation(VBPtrBase);
3695*67e74705SXin Li     VBI->VBTableIndices.insert(BaseInfo->VBTableIndices.begin(),
3696*67e74705SXin Li                                BaseInfo->VBTableIndices.end());
3697*67e74705SXin Li   }
3698*67e74705SXin Li 
3699*67e74705SXin Li   // New vbases are added to the end of the vbtable.
3700*67e74705SXin Li   // Skip the self entry and vbases visited in the non-virtual base, if any.
3701*67e74705SXin Li   unsigned VBTableIndex = 1 + VBI->VBTableIndices.size();
3702*67e74705SXin Li   for (const auto &VB : RD->vbases()) {
3703*67e74705SXin Li     const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3704*67e74705SXin Li     if (!VBI->VBTableIndices.count(CurVBase))
3705*67e74705SXin Li       VBI->VBTableIndices[CurVBase] = VBTableIndex++;
3706*67e74705SXin Li   }
3707*67e74705SXin Li 
3708*67e74705SXin Li   return VBI;
3709*67e74705SXin Li }
3710*67e74705SXin Li 
getVBTableIndex(const CXXRecordDecl * Derived,const CXXRecordDecl * VBase)3711*67e74705SXin Li unsigned MicrosoftVTableContext::getVBTableIndex(const CXXRecordDecl *Derived,
3712*67e74705SXin Li                                                  const CXXRecordDecl *VBase) {
3713*67e74705SXin Li   const VirtualBaseInfo *VBInfo = computeVBTableRelatedInformation(Derived);
3714*67e74705SXin Li   assert(VBInfo->VBTableIndices.count(VBase));
3715*67e74705SXin Li   return VBInfo->VBTableIndices.find(VBase)->second;
3716*67e74705SXin Li }
3717*67e74705SXin Li 
3718*67e74705SXin Li const VPtrInfoVector &
enumerateVBTables(const CXXRecordDecl * RD)3719*67e74705SXin Li MicrosoftVTableContext::enumerateVBTables(const CXXRecordDecl *RD) {
3720*67e74705SXin Li   return computeVBTableRelatedInformation(RD)->VBPtrPaths;
3721*67e74705SXin Li }
3722*67e74705SXin Li 
3723*67e74705SXin Li const VPtrInfoVector &
getVFPtrOffsets(const CXXRecordDecl * RD)3724*67e74705SXin Li MicrosoftVTableContext::getVFPtrOffsets(const CXXRecordDecl *RD) {
3725*67e74705SXin Li   computeVTableRelatedInformation(RD);
3726*67e74705SXin Li 
3727*67e74705SXin Li   assert(VFPtrLocations.count(RD) && "Couldn't find vfptr locations");
3728*67e74705SXin Li   return *VFPtrLocations[RD];
3729*67e74705SXin Li }
3730*67e74705SXin Li 
3731*67e74705SXin Li const VTableLayout &
getVFTableLayout(const CXXRecordDecl * RD,CharUnits VFPtrOffset)3732*67e74705SXin Li MicrosoftVTableContext::getVFTableLayout(const CXXRecordDecl *RD,
3733*67e74705SXin Li                                          CharUnits VFPtrOffset) {
3734*67e74705SXin Li   computeVTableRelatedInformation(RD);
3735*67e74705SXin Li 
3736*67e74705SXin Li   VFTableIdTy id(RD, VFPtrOffset);
3737*67e74705SXin Li   assert(VFTableLayouts.count(id) && "Couldn't find a VFTable at this offset");
3738*67e74705SXin Li   return *VFTableLayouts[id];
3739*67e74705SXin Li }
3740*67e74705SXin Li 
3741*67e74705SXin Li const MicrosoftVTableContext::MethodVFTableLocation &
getMethodVFTableLocation(GlobalDecl GD)3742*67e74705SXin Li MicrosoftVTableContext::getMethodVFTableLocation(GlobalDecl GD) {
3743*67e74705SXin Li   assert(cast<CXXMethodDecl>(GD.getDecl())->isVirtual() &&
3744*67e74705SXin Li          "Only use this method for virtual methods or dtors");
3745*67e74705SXin Li   if (isa<CXXDestructorDecl>(GD.getDecl()))
3746*67e74705SXin Li     assert(GD.getDtorType() == Dtor_Deleting);
3747*67e74705SXin Li 
3748*67e74705SXin Li   MethodVFTableLocationsTy::iterator I = MethodVFTableLocations.find(GD);
3749*67e74705SXin Li   if (I != MethodVFTableLocations.end())
3750*67e74705SXin Li     return I->second;
3751*67e74705SXin Li 
3752*67e74705SXin Li   const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
3753*67e74705SXin Li 
3754*67e74705SXin Li   computeVTableRelatedInformation(RD);
3755*67e74705SXin Li 
3756*67e74705SXin Li   I = MethodVFTableLocations.find(GD);
3757*67e74705SXin Li   assert(I != MethodVFTableLocations.end() && "Did not find index!");
3758*67e74705SXin Li   return I->second;
3759*67e74705SXin Li }
3760