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