124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne//===--- VTableBuilder.cpp - C++ vtable layout builder --------------------===//
224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne//
324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne//                     The LLVM Compiler Infrastructure
424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne//
524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne// This file is distributed under the University of Illinois Open Source
624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne// License. See LICENSE.TXT for details.
724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne//
824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne//===----------------------------------------------------------------------===//
924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne//
1024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne// This contains code dealing with generation of the layout of virtual tables.
1124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne//
1224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne//===----------------------------------------------------------------------===//
1324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include "clang/AST/VTableBuilder.h"
15d4f5198ae07d9a4958d8191bac694ded12173ad9Benjamin Kramer#include "clang/AST/ASTContext.h"
1624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include "clang/AST/CXXInheritance.h"
1724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include "clang/AST/RecordLayout.h"
1824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include "clang/Basic/TargetInfo.h"
19651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/ADT/SmallPtrSet.h"
2024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include "llvm/Support/Format.h"
21a93d0f280693b8418bc88cf7a8c93325f7fcf4c6Benjamin Kramer#include "llvm/Support/raw_ostream.h"
2224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include <algorithm>
2324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include <cstdio>
2424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourneusing namespace clang;
2624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#define DUMP_OVERRIDERS 0
2824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2924018467ddb13857b764182f7753764d2f32f87dPeter Collingbournenamespace {
3024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
3124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// BaseOffset - Represents an offset from a derived class to a direct or
3224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// indirect base class.
3324018467ddb13857b764182f7753764d2f32f87dPeter Collingbournestruct BaseOffset {
3424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// DerivedClass - The derived class.
3524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *DerivedClass;
3624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
3724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// VirtualBase - If the path from the derived class to the base class
382fca8027fdfa09e99d1066f4694ca437b43ab6d4Timur Iskhodzhanov  /// involves virtual base classes, this holds the declaration of the last
392fca8027fdfa09e99d1066f4694ca437b43ab6d4Timur Iskhodzhanov  /// virtual base in this path (i.e. closest to the base class).
4024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *VirtualBase;
4124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
4224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// NonVirtualOffset - The offset from the derived class to the base class.
4324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// (Or the offset from the virtual base class to the base class, if the
4424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// path from the derived class to the base class involves a virtual base
4524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// class.
4624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  CharUnits NonVirtualOffset;
476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  BaseOffset() : DerivedClass(nullptr), VirtualBase(nullptr),
496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                 NonVirtualOffset(CharUnits::Zero()) { }
5024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  BaseOffset(const CXXRecordDecl *DerivedClass,
5124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             const CXXRecordDecl *VirtualBase, CharUnits NonVirtualOffset)
5224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    : DerivedClass(DerivedClass), VirtualBase(VirtualBase),
5324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    NonVirtualOffset(NonVirtualOffset) { }
5424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
5524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  bool isEmpty() const { return NonVirtualOffset.isZero() && !VirtualBase; }
5624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne};
5724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
5824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// FinalOverriders - Contains the final overrider member functions for all
5924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// member functions in the base subobjects of a class.
6024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourneclass FinalOverriders {
6124018467ddb13857b764182f7753764d2f32f87dPeter Collingbournepublic:
6224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// OverriderInfo - Information about a final overrider.
6324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  struct OverriderInfo {
6424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    /// Method - The method decl of the overrider.
6524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXMethodDecl *Method;
6624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
67176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    /// VirtualBase - The virtual base class subobject of this overrider.
686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    /// Note that this records the closest derived virtual base class subobject.
696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const CXXRecordDecl *VirtualBase;
706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
71635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    /// Offset - the base offset of the overrider's parent in the layout class.
7224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits Offset;
736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    OverriderInfo() : Method(nullptr), VirtualBase(nullptr),
756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                      Offset(CharUnits::Zero()) { }
7624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  };
7724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
7824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourneprivate:
7924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MostDerivedClass - The most derived class for which the final overriders
8024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// are stored.
8124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *MostDerivedClass;
8224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
8324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MostDerivedClassOffset - If we're building final overriders for a
8424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// construction vtable, this holds the offset from the layout class to the
8524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// most derived class.
8624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CharUnits MostDerivedClassOffset;
8724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
8824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// LayoutClass - The class we're using for layout information. Will be
8924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// different than the most derived class if the final overriders are for a
9024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// construction vtable.
9124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *LayoutClass;
9224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
9324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ASTContext &Context;
9424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
9524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MostDerivedClassLayout - the AST record layout of the most derived class.
9624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const ASTRecordLayout &MostDerivedClassLayout;
9724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
9824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MethodBaseOffsetPairTy - Uniquely identifies a member function
9924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// in a base subobject.
10024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef std::pair<const CXXMethodDecl *, CharUnits> MethodBaseOffsetPairTy;
10124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
10224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<MethodBaseOffsetPairTy,
10324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                         OverriderInfo> OverridersMapTy;
10424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
10524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// OverridersMap - The final overriders for all virtual member functions of
10624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// all the base subobjects of the most derived class.
10724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  OverridersMapTy OverridersMap;
10824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
10924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// SubobjectsToOffsetsMapTy - A mapping from a base subobject (represented
11024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// as a record decl and a subobject number) and its offsets in the most
11124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// derived class as well as the layout class.
11224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<std::pair<const CXXRecordDecl *, unsigned>,
11324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                         CharUnits> SubobjectOffsetMapTy;
11424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
11524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCountMapTy;
11624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
11724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// ComputeBaseOffsets - Compute the offsets for all base subobjects of the
11824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// given base.
11924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
12024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                          CharUnits OffsetInLayoutClass,
12124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                          SubobjectOffsetMapTy &SubobjectOffsets,
12224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                          SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
12324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                          SubobjectCountMapTy &SubobjectCounts);
12424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
12524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
12624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
12724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// dump - dump the final overriders for a base subobject, and all its direct
12824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// and indirect base subobjects.
12924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void dump(raw_ostream &Out, BaseSubobject Base,
13024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            VisitedVirtualBasesSetTy& VisitedVirtualBases);
13124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
13224018467ddb13857b764182f7753764d2f32f87dPeter Collingbournepublic:
13324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  FinalOverriders(const CXXRecordDecl *MostDerivedClass,
13424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                  CharUnits MostDerivedClassOffset,
13524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                  const CXXRecordDecl *LayoutClass);
13624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
13724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// getOverrider - Get the final overrider for the given method declaration in
13824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// the subobject with the given base offset.
13924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  OverriderInfo getOverrider(const CXXMethodDecl *MD,
14024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                             CharUnits BaseOffset) const {
14124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    assert(OverridersMap.count(std::make_pair(MD, BaseOffset)) &&
14224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne           "Did not find overrider!");
14324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
14424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return OverridersMap.lookup(std::make_pair(MD, BaseOffset));
14524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
14624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
14724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// dump - dump the final overriders.
14824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void dump() {
14924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VisitedVirtualBasesSetTy VisitedVirtualBases;
15024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    dump(llvm::errs(), BaseSubobject(MostDerivedClass, CharUnits::Zero()),
15124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne         VisitedVirtualBases);
15224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
15324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
15424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne};
15524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
15624018467ddb13857b764182f7753764d2f32f87dPeter CollingbourneFinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass,
15724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                 CharUnits MostDerivedClassOffset,
15824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                 const CXXRecordDecl *LayoutClass)
15924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  : MostDerivedClass(MostDerivedClass),
16024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass),
16124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Context(MostDerivedClass->getASTContext()),
16224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)) {
16324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
16424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Compute base offsets.
16524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  SubobjectOffsetMapTy SubobjectOffsets;
16624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  SubobjectOffsetMapTy SubobjectLayoutClassOffsets;
16724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  SubobjectCountMapTy SubobjectCounts;
16824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ComputeBaseOffsets(BaseSubobject(MostDerivedClass, CharUnits::Zero()),
16924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                     /*IsVirtual=*/false,
17024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                     MostDerivedClassOffset,
17124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                     SubobjectOffsets, SubobjectLayoutClassOffsets,
17224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                     SubobjectCounts);
17324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
174bed28ac1d1463adca3ecf24fca5c30646fa9dbb2Sylvestre Ledru  // Get the final overriders.
17524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  CXXFinalOverriderMap FinalOverriders;
17624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  MostDerivedClass->getFinalOverriders(FinalOverriders);
17724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
17824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  for (CXXFinalOverriderMap::const_iterator I = FinalOverriders.begin(),
17924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne       E = FinalOverriders.end(); I != E; ++I) {
18024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXMethodDecl *MD = I->first;
18124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const OverridingMethods& Methods = I->second;
18224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
18324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    for (OverridingMethods::const_iterator I = Methods.begin(),
18424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne         E = Methods.end(); I != E; ++I) {
18524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      unsigned SubobjectNumber = I->first;
18624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      assert(SubobjectOffsets.count(std::make_pair(MD->getParent(),
18724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                                   SubobjectNumber)) &&
18824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             "Did not find subobject offset!");
18924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
19024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      CharUnits BaseOffset = SubobjectOffsets[std::make_pair(MD->getParent(),
19124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                                            SubobjectNumber)];
19224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
19324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      assert(I->second.size() == 1 && "Final overrider is not unique!");
19424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const UniqueVirtualMethod &Method = I->second.front();
19524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
19624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const CXXRecordDecl *OverriderRD = Method.Method->getParent();
19724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      assert(SubobjectLayoutClassOffsets.count(
19824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             std::make_pair(OverriderRD, Method.Subobject))
19924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             && "Did not find subobject offset!");
20024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      CharUnits OverriderOffset =
20124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        SubobjectLayoutClassOffsets[std::make_pair(OverriderRD,
20224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                                   Method.Subobject)];
20324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
20424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      OverriderInfo& Overrider = OverridersMap[std::make_pair(MD, BaseOffset)];
20524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      assert(!Overrider.Method && "Overrider should not exist yet!");
20624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
20724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Overrider.Offset = OverriderOffset;
20824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Overrider.Method = Method.Method;
2096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      Overrider.VirtualBase = Method.InVirtualSubobject;
21024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
21124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
21224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
21324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#if DUMP_OVERRIDERS
21424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // And dump them (for now).
21524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  dump();
21624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#endif
21724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
21824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
21924018467ddb13857b764182f7753764d2f32f87dPeter Collingbournestatic BaseOffset ComputeBaseOffset(ASTContext &Context,
22024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    const CXXRecordDecl *DerivedRD,
22124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    const CXXBasePath &Path) {
22224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  CharUnits NonVirtualOffset = CharUnits::Zero();
22324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
22424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  unsigned NonVirtualStart = 0;
2256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  const CXXRecordDecl *VirtualBase = nullptr;
2266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
22724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // First, look for the virtual base class.
2282fca8027fdfa09e99d1066f4694ca437b43ab6d4Timur Iskhodzhanov  for (int I = Path.size(), E = 0; I != E; --I) {
2292fca8027fdfa09e99d1066f4694ca437b43ab6d4Timur Iskhodzhanov    const CXXBasePathElement &Element = Path[I - 1];
2302fca8027fdfa09e99d1066f4694ca437b43ab6d4Timur Iskhodzhanov
23124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (Element.Base->isVirtual()) {
2322fca8027fdfa09e99d1066f4694ca437b43ab6d4Timur Iskhodzhanov      NonVirtualStart = I;
23324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      QualType VBaseType = Element.Base->getType();
234432d488305492bd998dbcd200ed500389c7602f5Timur Iskhodzhanov      VirtualBase = VBaseType->getAsCXXRecordDecl();
2352fca8027fdfa09e99d1066f4694ca437b43ab6d4Timur Iskhodzhanov      break;
23624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
23724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
23824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
23924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Now compute the non-virtual offset.
24024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  for (unsigned I = NonVirtualStart, E = Path.size(); I != E; ++I) {
24124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXBasePathElement &Element = Path[I];
24224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
24324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check the base class offset.
24424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const ASTRecordLayout &Layout = Context.getASTRecordLayout(Element.Class);
24524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
246432d488305492bd998dbcd200ed500389c7602f5Timur Iskhodzhanov    const CXXRecordDecl *Base = Element.Base->getType()->getAsCXXRecordDecl();
24724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
24824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    NonVirtualOffset += Layout.getBaseClassOffset(Base);
24924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
25024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
25124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // FIXME: This should probably use CharUnits or something. Maybe we should
25224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // even change the base offsets in ASTRecordLayout to be specified in
25324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // CharUnits.
25424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return BaseOffset(DerivedRD, VirtualBase, NonVirtualOffset);
25524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
25624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
25724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
25824018467ddb13857b764182f7753764d2f32f87dPeter Collingbournestatic BaseOffset ComputeBaseOffset(ASTContext &Context,
25924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    const CXXRecordDecl *BaseRD,
26024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    const CXXRecordDecl *DerivedRD) {
26124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  CXXBasePaths Paths(/*FindAmbiguities=*/false,
26224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                     /*RecordPaths=*/true, /*DetectVirtual=*/false);
263922cec29a9366f70d593d6225aea01dcd3daf8cfBenjamin Kramer
264922cec29a9366f70d593d6225aea01dcd3daf8cfBenjamin Kramer  if (!DerivedRD->isDerivedFrom(BaseRD, Paths))
26524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    llvm_unreachable("Class must be derived from the passed in base class!");
26624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
26724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return ComputeBaseOffset(Context, DerivedRD, Paths.front());
26824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
26924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
27024018467ddb13857b764182f7753764d2f32f87dPeter Collingbournestatic BaseOffset
27124018467ddb13857b764182f7753764d2f32f87dPeter CollingbourneComputeReturnAdjustmentBaseOffset(ASTContext &Context,
27224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                  const CXXMethodDecl *DerivedMD,
27324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                  const CXXMethodDecl *BaseMD) {
27424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const FunctionType *BaseFT = BaseMD->getType()->getAs<FunctionType>();
27524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const FunctionType *DerivedFT = DerivedMD->getType()->getAs<FunctionType>();
27624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
27724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Canonicalize the return types.
278651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CanQualType CanDerivedReturnType =
279651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Context.getCanonicalType(DerivedFT->getReturnType());
280651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CanQualType CanBaseReturnType =
281651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Context.getCanonicalType(BaseFT->getReturnType());
282651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
28324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  assert(CanDerivedReturnType->getTypeClass() ==
28424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne         CanBaseReturnType->getTypeClass() &&
28524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne         "Types must have same type class!");
28624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
28724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (CanDerivedReturnType == CanBaseReturnType) {
28824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // No adjustment needed.
28924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return BaseOffset();
29024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
29124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
29224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (isa<ReferenceType>(CanDerivedReturnType)) {
29324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CanDerivedReturnType =
29424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      CanDerivedReturnType->getAs<ReferenceType>()->getPointeeType();
29524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CanBaseReturnType =
29624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      CanBaseReturnType->getAs<ReferenceType>()->getPointeeType();
29724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  } else if (isa<PointerType>(CanDerivedReturnType)) {
29824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CanDerivedReturnType =
29924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      CanDerivedReturnType->getAs<PointerType>()->getPointeeType();
30024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CanBaseReturnType =
30124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      CanBaseReturnType->getAs<PointerType>()->getPointeeType();
30224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  } else {
30324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    llvm_unreachable("Unexpected return type!");
30424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
30524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
30624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // We need to compare unqualified types here; consider
30724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   const T *Base::foo();
30824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   T *Derived::foo();
30924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (CanDerivedReturnType.getUnqualifiedType() ==
31024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      CanBaseReturnType.getUnqualifiedType()) {
31124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // No adjustment needed.
31224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return BaseOffset();
31324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
31424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
31524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *DerivedRD =
31624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    cast<CXXRecordDecl>(cast<RecordType>(CanDerivedReturnType)->getDecl());
31724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
31824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *BaseRD =
31924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    cast<CXXRecordDecl>(cast<RecordType>(CanBaseReturnType)->getDecl());
32024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
32124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return ComputeBaseOffset(Context, BaseRD, DerivedRD);
32224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
32324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
32424018467ddb13857b764182f7753764d2f32f87dPeter Collingbournevoid
32524018467ddb13857b764182f7753764d2f32f87dPeter CollingbourneFinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
32624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                              CharUnits OffsetInLayoutClass,
32724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                              SubobjectOffsetMapTy &SubobjectOffsets,
32824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                              SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
32924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                              SubobjectCountMapTy &SubobjectCounts) {
33024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *RD = Base.getBase();
33124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
33224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  unsigned SubobjectNumber = 0;
33324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (!IsVirtual)
33424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    SubobjectNumber = ++SubobjectCounts[RD];
33524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
33624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Set up the subobject to offset mapping.
33724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber))
33824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne         && "Subobject offset already exists!");
33924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber))
34024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne         && "Subobject offset already exists!");
34124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
34224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] = Base.getBaseOffset();
34324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] =
34424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    OffsetInLayoutClass;
34524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
34624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Traverse our bases.
347651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &B : RD->bases()) {
348651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
34924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
35024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits BaseOffset;
35124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits BaseOffsetInLayoutClass;
352651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (B.isVirtual()) {
35324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Check if we've visited this virtual base before.
35424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0)))
35524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        continue;
35624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
35724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &LayoutClassLayout =
35824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(LayoutClass);
35924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
36024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
36124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseOffsetInLayoutClass =
36224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        LayoutClassLayout.getVBaseClassOffset(BaseDecl);
36324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    } else {
36424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
36524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      CharUnits Offset = Layout.getBaseClassOffset(BaseDecl);
36624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
36724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseOffset = Base.getBaseOffset() + Offset;
36824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseOffsetInLayoutClass = OffsetInLayoutClass + Offset;
36924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
37024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
37124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    ComputeBaseOffsets(BaseSubobject(BaseDecl, BaseOffset),
372651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                       B.isVirtual(), BaseOffsetInLayoutClass,
37324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                       SubobjectOffsets, SubobjectLayoutClassOffsets,
37424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                       SubobjectCounts);
37524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
37624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
37724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
37824018467ddb13857b764182f7753764d2f32f87dPeter Collingbournevoid FinalOverriders::dump(raw_ostream &Out, BaseSubobject Base,
37924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                           VisitedVirtualBasesSetTy &VisitedVirtualBases) {
38024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *RD = Base.getBase();
38124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
38224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
383651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &B : RD->bases()) {
384651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
38524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
38624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Ignore bases that don't have any virtual member functions.
38724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!BaseDecl->isPolymorphic())
38824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
38924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
39024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits BaseOffset;
391651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (B.isVirtual()) {
392176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (!VisitedVirtualBases.insert(BaseDecl).second) {
39324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // We've visited this base before.
39424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        continue;
39524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
39624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
39724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
39824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    } else {
39924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseOffset = Layout.getBaseClassOffset(BaseDecl) + Base.getBaseOffset();
40024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
40124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
40224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    dump(Out, BaseSubobject(BaseDecl, BaseOffset), VisitedVirtualBases);
40324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
40424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
405651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Out << "Final overriders for (";
406651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  RD->printQualifiedName(Out);
407651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Out << ", ";
40824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Out << Base.getBaseOffset().getQuantity() << ")\n";
40924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
41024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Now dump the overriders for this base subobject.
411651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto *MD : RD->methods()) {
41224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!MD->isVirtual())
41324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
4140e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    MD = MD->getCanonicalDecl();
4150e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
41624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    OverriderInfo Overrider = getOverrider(MD, Base.getBaseOffset());
41724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
418651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Out << "  ";
419651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    MD->printQualifiedName(Out);
420651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Out << " - (";
421651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Overrider.Method->printQualifiedName(Out);
422c65ee8f4fe7d9e48b75a367b8b63d62db0855821Timur Iskhodzhanov    Out << ", " << Overrider.Offset.getQuantity() << ')';
42324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
42424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    BaseOffset Offset;
42524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!Overrider.Method->isPure())
42624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
42724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
42824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!Offset.isEmpty()) {
42924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << " [ret-adj: ";
430651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (Offset.VirtualBase) {
431651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        Offset.VirtualBase->printQualifiedName(Out);
432651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        Out << " vbase, ";
433651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      }
43424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
43524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << Offset.NonVirtualOffset.getQuantity() << " nv]";
43624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
43724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
43824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << "\n";
43924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
44024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
44124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
44224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// VCallOffsetMap - Keeps track of vcall offsets when building a vtable.
44324018467ddb13857b764182f7753764d2f32f87dPeter Collingbournestruct VCallOffsetMap {
44424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
44524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef std::pair<const CXXMethodDecl *, CharUnits> MethodAndOffsetPairTy;
44624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
44724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// Offsets - Keeps track of methods and their offsets.
44824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // FIXME: This should be a real map and not a vector.
44924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  SmallVector<MethodAndOffsetPairTy, 16> Offsets;
45024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
45124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MethodsCanShareVCallOffset - Returns whether two virtual member functions
45224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// can share the same vcall offset.
45324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  static bool MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
45424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                         const CXXMethodDecl *RHS);
45524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
45624018467ddb13857b764182f7753764d2f32f87dPeter Collingbournepublic:
45724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// AddVCallOffset - Adds a vcall offset to the map. Returns true if the
45824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// add was successful, or false if there was already a member function with
45924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// the same signature in the map.
46024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  bool AddVCallOffset(const CXXMethodDecl *MD, CharUnits OffsetOffset);
46124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
46224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// getVCallOffsetOffset - Returns the vcall offset offset (relative to the
46324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// vtable address point) for the given virtual member function.
46424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  CharUnits getVCallOffsetOffset(const CXXMethodDecl *MD);
46524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
46624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // empty - Return whether the offset map is empty or not.
46724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  bool empty() const { return Offsets.empty(); }
46824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne};
46924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
47024018467ddb13857b764182f7753764d2f32f87dPeter Collingbournestatic bool HasSameVirtualSignature(const CXXMethodDecl *LHS,
47124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    const CXXMethodDecl *RHS) {
472260a3e4370a15bc3da9d2d9461b6f179c68dd348John McCall  const FunctionProtoType *LT =
473260a3e4370a15bc3da9d2d9461b6f179c68dd348John McCall    cast<FunctionProtoType>(LHS->getType().getCanonicalType());
474260a3e4370a15bc3da9d2d9461b6f179c68dd348John McCall  const FunctionProtoType *RT =
475260a3e4370a15bc3da9d2d9461b6f179c68dd348John McCall    cast<FunctionProtoType>(RHS->getType().getCanonicalType());
47624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
47724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Fast-path matches in the canonical types.
47824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (LT == RT) return true;
47924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
48024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Force the signatures to match.  We can't rely on the overrides
48124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // list here because there isn't necessarily an inheritance
48224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // relationship between the two methods.
483260a3e4370a15bc3da9d2d9461b6f179c68dd348John McCall  if (LT->getTypeQuals() != RT->getTypeQuals() ||
484651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      LT->getNumParams() != RT->getNumParams())
48524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return false;
486651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (unsigned I = 0, E = LT->getNumParams(); I != E; ++I)
487651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (LT->getParamType(I) != RT->getParamType(I))
48824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      return false;
48924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return true;
49024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
49124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
49224018467ddb13857b764182f7753764d2f32f87dPeter Collingbournebool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
49324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                                const CXXMethodDecl *RHS) {
49424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  assert(LHS->isVirtual() && "LHS must be virtual!");
49524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  assert(RHS->isVirtual() && "LHS must be virtual!");
49624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
49724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // A destructor can share a vcall offset with another destructor.
49824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (isa<CXXDestructorDecl>(LHS))
49924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return isa<CXXDestructorDecl>(RHS);
50024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
50124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // FIXME: We need to check more things here.
50224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
50324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // The methods must have the same name.
50424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  DeclarationName LHSName = LHS->getDeclName();
50524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  DeclarationName RHSName = RHS->getDeclName();
50624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (LHSName != RHSName)
50724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return false;
50824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
50924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // And the same signatures.
51024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return HasSameVirtualSignature(LHS, RHS);
51124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
51224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
51324018467ddb13857b764182f7753764d2f32f87dPeter Collingbournebool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl *MD,
51424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    CharUnits OffsetOffset) {
51524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Check if we can reuse an offset.
51624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  for (unsigned I = 0, E = Offsets.size(); I != E; ++I) {
51724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (MethodsCanShareVCallOffset(Offsets[I].first, MD))
51824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      return false;
51924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
52024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
52124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Add the offset.
52224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset));
52324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return true;
52424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
52524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
52624018467ddb13857b764182f7753764d2f32f87dPeter CollingbourneCharUnits VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) {
52724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Look for an offset.
52824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  for (unsigned I = 0, E = Offsets.size(); I != E; ++I) {
52924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (MethodsCanShareVCallOffset(Offsets[I].first, MD))
53024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      return Offsets[I].second;
53124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
53224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
53324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  llvm_unreachable("Should always find a vcall offset offset!");
53424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
53524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
53624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// VCallAndVBaseOffsetBuilder - Class for building vcall and vbase offsets.
53724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourneclass VCallAndVBaseOffsetBuilder {
53824018467ddb13857b764182f7753764d2f32f87dPeter Collingbournepublic:
53924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
54024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VBaseOffsetOffsetsMapTy;
54124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
54224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourneprivate:
54324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MostDerivedClass - The most derived class for which we're building vcall
54424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// and vbase offsets.
54524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *MostDerivedClass;
54624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
54724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// LayoutClass - The class we're using for layout information. Will be
54824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// different than the most derived class if we're building a construction
54924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// vtable.
55024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *LayoutClass;
55124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
55224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// Context - The ASTContext which we will use for layout information.
55324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ASTContext &Context;
55424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
55524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// Components - vcall and vbase offset components
55624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef SmallVector<VTableComponent, 64> VTableComponentVectorTy;
55724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VTableComponentVectorTy Components;
55824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
55924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// VisitedVirtualBases - Visited virtual bases.
56024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
56124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
56224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// VCallOffsets - Keeps track of vcall offsets.
56324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VCallOffsetMap VCallOffsets;
56424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
56524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
56624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets,
56724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// relative to the address point.
56824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
56924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
57024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// FinalOverriders - The final overriders of the most derived class.
57124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// (Can be null when we're not building a vtable of the most derived class).
57224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const FinalOverriders *Overriders;
57324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
57424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// AddVCallAndVBaseOffsets - Add vcall offsets and vbase offsets for the
57524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// given base subobject.
57624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void AddVCallAndVBaseOffsets(BaseSubobject Base, bool BaseIsVirtual,
57724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                               CharUnits RealBaseOffset);
57824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
57924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// AddVCallOffsets - Add vcall offsets for the given base subobject.
58024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void AddVCallOffsets(BaseSubobject Base, CharUnits VBaseOffset);
58124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
58224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// AddVBaseOffsets - Add vbase offsets for the given class.
58324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void AddVBaseOffsets(const CXXRecordDecl *Base,
58424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                       CharUnits OffsetInLayoutClass);
58524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
58624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// getCurrentOffsetOffset - Get the current vcall or vbase offset offset in
58724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// chars, relative to the vtable address point.
58824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  CharUnits getCurrentOffsetOffset() const;
58924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
59024018467ddb13857b764182f7753764d2f32f87dPeter Collingbournepublic:
59124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VCallAndVBaseOffsetBuilder(const CXXRecordDecl *MostDerivedClass,
59224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                             const CXXRecordDecl *LayoutClass,
59324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                             const FinalOverriders *Overriders,
59424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                             BaseSubobject Base, bool BaseIsVirtual,
59524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                             CharUnits OffsetInLayoutClass)
59624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    : MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass),
59724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Context(MostDerivedClass->getASTContext()), Overriders(Overriders) {
59824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
59924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Add vcall and vbase offsets.
60024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddVCallAndVBaseOffsets(Base, BaseIsVirtual, OffsetInLayoutClass);
60124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
60224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
60324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// Methods for iterating over the components.
60424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef VTableComponentVectorTy::const_reverse_iterator const_iterator;
60524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const_iterator components_begin() const { return Components.rbegin(); }
60624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const_iterator components_end() const { return Components.rend(); }
60724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
60824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const VCallOffsetMap &getVCallOffsets() const { return VCallOffsets; }
60924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const {
61024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return VBaseOffsetOffsets;
61124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
61224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne};
61324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
61424018467ddb13857b764182f7753764d2f32f87dPeter Collingbournevoid
61524018467ddb13857b764182f7753764d2f32f87dPeter CollingbourneVCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base,
61624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                                    bool BaseIsVirtual,
61724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                                    CharUnits RealBaseOffset) {
61824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base.getBase());
61924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
62024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Itanium C++ ABI 2.5.2:
62124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   ..in classes sharing a virtual table with a primary base class, the vcall
62224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   and vbase offsets added by the derived class all come before the vcall
62324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   and vbase offsets required by the base class, so that the latter may be
62424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   laid out as required by the base class without regard to additions from
62524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   the derived class(es).
62624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
62724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // (Since we're emitting the vcall and vbase offsets in reverse order, we'll
62824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // emit them for the primary base first).
62924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
63024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    bool PrimaryBaseIsVirtual = Layout.isPrimaryBaseVirtual();
63124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
63224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits PrimaryBaseOffset;
63324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
63424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Get the base offset of the primary base.
63524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (PrimaryBaseIsVirtual) {
636d4f5198ae07d9a4958d8191bac694ded12173ad9Benjamin Kramer      assert(Layout.getVBaseClassOffset(PrimaryBase).isZero() &&
63724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             "Primary vbase should have a zero offset!");
63824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
63924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &MostDerivedClassLayout =
64024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(MostDerivedClass);
64124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
64224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      PrimaryBaseOffset =
64324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
64424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    } else {
645d4f5198ae07d9a4958d8191bac694ded12173ad9Benjamin Kramer      assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
64624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             "Primary base should have a zero offset!");
64724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
64824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      PrimaryBaseOffset = Base.getBaseOffset();
64924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
65024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
65124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddVCallAndVBaseOffsets(
65224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseSubobject(PrimaryBase,PrimaryBaseOffset),
65324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      PrimaryBaseIsVirtual, RealBaseOffset);
65424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
65524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
65624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  AddVBaseOffsets(Base.getBase(), RealBaseOffset);
65724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
65824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // We only want to add vcall offsets for virtual bases.
65924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (BaseIsVirtual)
66024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddVCallOffsets(Base, RealBaseOffset);
66124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
66224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
66324018467ddb13857b764182f7753764d2f32f87dPeter CollingbourneCharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset() const {
66424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // OffsetIndex is the index of this vcall or vbase offset, relative to the
66524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // vtable address point. (We subtract 3 to account for the information just
66624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // above the address point, the RTTI info, the offset to top, and the
66724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // vcall offset itself).
66824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  int64_t OffsetIndex = -(int64_t)(3 + Components.size());
66924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
67024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  CharUnits PointerWidth =
67124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
67224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  CharUnits OffsetOffset = PointerWidth * OffsetIndex;
67324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return OffsetOffset;
67424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
67524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
67624018467ddb13857b764182f7753764d2f32f87dPeter Collingbournevoid VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
67724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                                 CharUnits VBaseOffset) {
67824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *RD = Base.getBase();
67924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
68024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
68124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
68224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
68324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Handle the primary base first.
68424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // We only want to add vcall offsets if the base is non-virtual; a virtual
68524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // primary base will have its vcall and vbase offsets emitted already.
68624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (PrimaryBase && !Layout.isPrimaryBaseVirtual()) {
68724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Get the base offset of the primary base.
688d4f5198ae07d9a4958d8191bac694ded12173ad9Benjamin Kramer    assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
68924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne           "Primary base should have a zero offset!");
69024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
69124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddVCallOffsets(BaseSubobject(PrimaryBase, Base.getBaseOffset()),
69224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                    VBaseOffset);
69324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
69424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
69524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Add the vcall offsets.
696651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto *MD : RD->methods()) {
69724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!MD->isVirtual())
69824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
6990e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    MD = MD->getCanonicalDecl();
70024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
70124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits OffsetOffset = getCurrentOffsetOffset();
70224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
70324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Don't add a vcall offset if we already have one for this member function
70424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // signature.
70524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
70624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
70724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
70824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits Offset = CharUnits::Zero();
70924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
71024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (Overriders) {
71124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Get the final overrider.
71224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      FinalOverriders::OverriderInfo Overrider =
71324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Overriders->getOverrider(MD, Base.getBaseOffset());
71424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
71524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      /// The vcall offset is the offset from the virtual base to the object
71624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      /// where the function was overridden.
71724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Offset = Overrider.Offset - VBaseOffset;
71824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
71924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
72024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Components.push_back(
72124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VTableComponent::MakeVCallOffset(Offset));
72224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
72324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
72424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // And iterate over all non-virtual bases (ignoring the primary base).
725651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &B : RD->bases()) {
726651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (B.isVirtual())
72724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
72824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
729651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
73024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (BaseDecl == PrimaryBase)
73124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
73224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
73324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Get the base offset of this base.
73424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits BaseOffset = Base.getBaseOffset() +
73524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Layout.getBaseClassOffset(BaseDecl);
73624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
73724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddVCallOffsets(BaseSubobject(BaseDecl, BaseOffset),
73824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                    VBaseOffset);
73924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
74024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
74124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
74224018467ddb13857b764182f7753764d2f32f87dPeter Collingbournevoid
74324018467ddb13857b764182f7753764d2f32f87dPeter CollingbourneVCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
74424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                            CharUnits OffsetInLayoutClass) {
74524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const ASTRecordLayout &LayoutClassLayout =
74624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Context.getASTRecordLayout(LayoutClass);
74724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
74824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Add vbase offsets.
749651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &B : RD->bases()) {
750651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
75124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
75224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check if this is a virtual base that we haven't visited before.
753176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl).second) {
75424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      CharUnits Offset =
75524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        LayoutClassLayout.getVBaseClassOffset(BaseDecl) - OffsetInLayoutClass;
75624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
75724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Add the vbase offset offset.
75824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      assert(!VBaseOffsetOffsets.count(BaseDecl) &&
75924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             "vbase offset offset already exists!");
76024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
76124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      CharUnits VBaseOffsetOffset = getCurrentOffsetOffset();
76224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VBaseOffsetOffsets.insert(
76324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          std::make_pair(BaseDecl, VBaseOffsetOffset));
76424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
76524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Components.push_back(
76624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          VTableComponent::MakeVBaseOffset(Offset));
76724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
76824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
76924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check the base class looking for more vbase offsets.
77024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
77124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
77224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
77324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
774f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov/// ItaniumVTableBuilder - Class for building vtable layout information.
775f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovclass ItaniumVTableBuilder {
77624018467ddb13857b764182f7753764d2f32f87dPeter Collingbournepublic:
77724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// PrimaryBasesSetVectorTy - A set vector of direct and indirect
77824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// primary bases.
77924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::SmallSetVector<const CXXRecordDecl *, 8>
78024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    PrimaryBasesSetVectorTy;
78124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
78224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
78324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VBaseOffsetOffsetsMapTy;
78424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
78524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<BaseSubobject, uint64_t>
78624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddressPointsMapTy;
78724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
7882aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
7892aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
79024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourneprivate:
79124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// VTables - Global vtable information.
792f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov  ItaniumVTableContext &VTables;
79324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
79424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MostDerivedClass - The most derived class for which we're building this
79524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// vtable.
79624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *MostDerivedClass;
79724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
79824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MostDerivedClassOffset - If we're building a construction vtable, this
79924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// holds the offset from the layout class to the most derived class.
80024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CharUnits MostDerivedClassOffset;
80124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
80224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MostDerivedClassIsVirtual - Whether the most derived class is a virtual
80324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// base. (This only makes sense when building a construction vtable).
80424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  bool MostDerivedClassIsVirtual;
80524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
80624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// LayoutClass - The class we're using for layout information. Will be
80724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// different than the most derived class if we're building a construction
80824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// vtable.
80924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *LayoutClass;
81024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
81124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// Context - The ASTContext which we will use for layout information.
81224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ASTContext &Context;
81324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
81424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// FinalOverriders - The final overriders of the most derived class.
81524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const FinalOverriders Overriders;
81624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
81724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// VCallOffsetsForVBases - Keeps track of vcall offsets for the virtual
81824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// bases in this vtable.
81924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
82024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
82124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for
82224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// the most derived class.
82324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
82424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
82524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// Components - The components of the vtable being built.
82624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  SmallVector<VTableComponent, 64> Components;
82724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
82824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// AddressPoints - Address points for the vtable being built.
82924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  AddressPointsMapTy AddressPoints;
83024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
83124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MethodInfo - Contains information about a method in a vtable.
83224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// (Used for computing 'this' pointer adjustment thunks.
83324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  struct MethodInfo {
83424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    /// BaseOffset - The base offset of this method.
83524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CharUnits BaseOffset;
83624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
83724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    /// BaseOffsetInLayoutClass - The base offset in the layout class of this
83824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    /// method.
83924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CharUnits BaseOffsetInLayoutClass;
84024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
84124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    /// VTableIndex - The index in the vtable that this method has.
84224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    /// (For destructors, this is the index of the complete destructor).
84324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const uint64_t VTableIndex;
84424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
84524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    MethodInfo(CharUnits BaseOffset, CharUnits BaseOffsetInLayoutClass,
84624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne               uint64_t VTableIndex)
84724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      : BaseOffset(BaseOffset),
84824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
84924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VTableIndex(VTableIndex) { }
85024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
85124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    MethodInfo()
85224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      : BaseOffset(CharUnits::Zero()),
85324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseOffsetInLayoutClass(CharUnits::Zero()),
85424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VTableIndex(0) { }
85524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  };
85624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
85724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
85824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
85924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MethodInfoMap - The information for all methods in the vtable we're
86024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// currently building.
86124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  MethodInfoMapTy MethodInfoMap;
8622aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
8632aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  /// MethodVTableIndices - Contains the index (relative to the vtable address
8642aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  /// point) where the function pointer for a virtual function is stored.
8652aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  MethodVTableIndicesTy MethodVTableIndices;
8662aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
86724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
86824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
86924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// VTableThunks - The thunks by vtable index in the vtable currently being
87024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// built.
87124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VTableThunksMapTy VTableThunks;
87224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
87324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
87424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
87524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
87624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// Thunks - A map that contains all the thunks needed for all methods in the
87724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// most derived class for which the vtable is currently being built.
87824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ThunksMapTy Thunks;
87924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
88024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// AddThunk - Add a thunk for the given method.
88124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void AddThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk);
88224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
88324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// ComputeThisAdjustments - Compute the 'this' pointer adjustments for the
88424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// part of the vtable we're currently building.
88524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void ComputeThisAdjustments();
88624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
88724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
88824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
88924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// PrimaryVirtualBases - All known virtual bases who are a primary base of
89024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// some other base.
89124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VisitedVirtualBasesSetTy PrimaryVirtualBases;
89224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
89324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// ComputeReturnAdjustment - Compute the return adjustment given a return
89424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// adjustment base offset.
89524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ReturnAdjustment ComputeReturnAdjustment(BaseOffset Offset);
89624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
89724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// ComputeThisAdjustmentBaseOffset - Compute the base offset for adjusting
89824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// the 'this' pointer from the base subobject to the derived subobject.
89924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  BaseOffset ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
90024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                             BaseSubobject Derived) const;
90124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
90224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// ComputeThisAdjustment - Compute the 'this' pointer adjustment for the
90324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// given virtual member function, its offset in the layout class and its
90424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// final overrider.
90524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ThisAdjustment
90624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ComputeThisAdjustment(const CXXMethodDecl *MD,
90724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                        CharUnits BaseOffsetInLayoutClass,
90824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                        FinalOverriders::OverriderInfo Overrider);
90924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
91024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// AddMethod - Add a single virtual member function to the vtable
91124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// components vector.
91224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment);
91324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
91424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// IsOverriderUsed - Returns whether the overrider will ever be used in this
91524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// part of the vtable.
91624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///
91724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// Itanium C++ ABI 2.5.2:
91824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///
91924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   struct A { virtual void f(); };
92024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   struct B : virtual public A { int i; };
92124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   struct C : virtual public A { int j; };
92224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   struct D : public B, public C {};
92324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///
92424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   When B and C are declared, A is a primary base in each case, so although
92524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   vcall offsets are allocated in the A-in-B and A-in-C vtables, no this
92624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   adjustment is required and no thunk is generated. However, inside D
92724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   objects, A is no longer a primary base of C, so if we allowed calls to
92824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   C::f() to use the copy of A's vtable in the C subobject, we would need
92924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   to adjust this from C* to B::A*, which would require a third-party
93024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   thunk. Since we require that a call to C::f() first convert to A*,
93124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   C-in-D's copy of A's vtable is never referenced, so this is not
93224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   necessary.
93324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  bool IsOverriderUsed(const CXXMethodDecl *Overrider,
93424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                       CharUnits BaseOffsetInLayoutClass,
93524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                       const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
93624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                       CharUnits FirstBaseOffsetInLayoutClass) const;
93724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
93824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
93924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// AddMethods - Add the methods of this base subobject and all its
94024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// primary bases to the vtable components vector.
94124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void AddMethods(BaseSubobject Base, CharUnits BaseOffsetInLayoutClass,
94224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                  const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
94324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                  CharUnits FirstBaseOffsetInLayoutClass,
94424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                  PrimaryBasesSetVectorTy &PrimaryBases);
94524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
94624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // LayoutVTable - Layout the vtable for the given base class, including its
94724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // secondary vtables and any vtables for virtual bases.
94824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void LayoutVTable();
94924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
95024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// LayoutPrimaryAndSecondaryVTables - Layout the primary vtable for the
95124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// given base subobject, as well as all its secondary vtables.
95224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///
95324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
95424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// or a direct or indirect base of a virtual base.
95524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///
95624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// \param BaseIsVirtualInLayoutClass - Whether the base subobject is virtual
95724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// in the layout class.
95824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void LayoutPrimaryAndSecondaryVTables(BaseSubobject Base,
95924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                        bool BaseIsMorallyVirtual,
96024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                        bool BaseIsVirtualInLayoutClass,
96124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                        CharUnits OffsetInLayoutClass);
96224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
96324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// LayoutSecondaryVTables - Layout the secondary vtables for the given base
96424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// subobject.
96524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///
96624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
96724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// or a direct or indirect base of a virtual base.
96824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void LayoutSecondaryVTables(BaseSubobject Base, bool BaseIsMorallyVirtual,
96924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                              CharUnits OffsetInLayoutClass);
97024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
97124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this
97224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// class hierarchy.
97324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void DeterminePrimaryVirtualBases(const CXXRecordDecl *RD,
97424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    CharUnits OffsetInLayoutClass,
97524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    VisitedVirtualBasesSetTy &VBases);
97624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
97724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// LayoutVTablesForVirtualBases - Layout vtables for all virtual bases of the
97824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// given base (excluding any primary bases).
97924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void LayoutVTablesForVirtualBases(const CXXRecordDecl *RD,
98024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    VisitedVirtualBasesSetTy &VBases);
98124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
98224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// isBuildingConstructionVTable - Return whether this vtable builder is
98324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// building a construction vtable.
98424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  bool isBuildingConstructorVTable() const {
98524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return MostDerivedClass != LayoutClass;
98624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
98724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
98824018467ddb13857b764182f7753764d2f32f87dPeter Collingbournepublic:
989f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov  ItaniumVTableBuilder(ItaniumVTableContext &VTables,
990f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                       const CXXRecordDecl *MostDerivedClass,
991f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                       CharUnits MostDerivedClassOffset,
992f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                       bool MostDerivedClassIsVirtual,
993f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                       const CXXRecordDecl *LayoutClass)
994f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov      : VTables(VTables), MostDerivedClass(MostDerivedClass),
995f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov        MostDerivedClassOffset(MostDerivedClassOffset),
996f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov        MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
997f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov        LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()),
998f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov        Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) {
9992cb17a06befb61b1434aaa991652fea4338c95d7Timur Iskhodzhanov    assert(!Context.getTargetInfo().getCXXABI().isMicrosoft());
100024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
100124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    LayoutVTable();
100224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
10034e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie    if (Context.getLangOpts().DumpVTableLayouts)
1004152eee9f81f1b4f00e1bce655903fc78cafb1342Reid Kleckner      dumpLayout(llvm::outs());
100524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
100624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
100724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  uint64_t getNumThunks() const {
100824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return Thunks.size();
100924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
101024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
101124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ThunksMapTy::const_iterator thunks_begin() const {
101224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return Thunks.begin();
101324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
101424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
101524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ThunksMapTy::const_iterator thunks_end() const {
101624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return Thunks.end();
101724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
101824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
101924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const {
102024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return VBaseOffsetOffsets;
102124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
102224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
102324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const AddressPointsMapTy &getAddressPoints() const {
102424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return AddressPoints;
102524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
102624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
10272aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  MethodVTableIndicesTy::const_iterator vtable_indices_begin() const {
10282aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    return MethodVTableIndices.begin();
10292aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  }
10302aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
10312aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  MethodVTableIndicesTy::const_iterator vtable_indices_end() const {
10322aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    return MethodVTableIndices.end();
10332aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  }
10342aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
103524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// getNumVTableComponents - Return the number of components in the vtable
103624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// currently built.
103724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  uint64_t getNumVTableComponents() const {
103824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return Components.size();
103924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
104024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
104124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const VTableComponent *vtable_component_begin() const {
104224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return Components.begin();
104324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
104424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
104524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const VTableComponent *vtable_component_end() const {
104624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return Components.end();
104724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
104824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
104924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  AddressPointsMapTy::const_iterator address_points_begin() const {
105024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return AddressPoints.begin();
105124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
105224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
105324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  AddressPointsMapTy::const_iterator address_points_end() const {
105424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return AddressPoints.end();
105524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
105624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
105724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VTableThunksMapTy::const_iterator vtable_thunks_begin() const {
105824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return VTableThunks.begin();
105924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
106024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
106124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VTableThunksMapTy::const_iterator vtable_thunks_end() const {
106224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return VTableThunks.end();
106324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
106424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
106524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// dumpLayout - Dump the vtable layout.
106624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void dumpLayout(raw_ostream&);
106724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne};
106824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1069f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::AddThunk(const CXXMethodDecl *MD,
1070f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                                    const ThunkInfo &Thunk) {
107124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  assert(!isBuildingConstructorVTable() &&
107224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne         "Can't add thunks for construction vtable");
107324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
10746b9240e058bf3451685df73fc8ce181b3046e92bCraig Topper  SmallVectorImpl<ThunkInfo> &ThunksVector = Thunks[MD];
10756b9240e058bf3451685df73fc8ce181b3046e92bCraig Topper
107624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Check if we have this thunk already.
107724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
107824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      ThunksVector.end())
107924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return;
108024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
108124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ThunksVector.push_back(Thunk);
108224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
108324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
108424018467ddb13857b764182f7753764d2f32f87dPeter Collingbournetypedef llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverriddenMethodsSetTy;
108524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1086635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov/// Visit all the methods overridden by the given method recursively,
1087635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov/// in a depth-first pre-order. The Visitor's visitor method returns a bool
1088635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov/// indicating whether to continue the recursion for the given overridden
1089635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov/// method (i.e. returning false stops the iteration).
1090635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovtemplate <class VisitorTy>
1091635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovstatic void
1092635de28950ef84ae26308ff734e778bad1ddde92Timur IskhodzhanovvisitAllOverriddenMethods(const CXXMethodDecl *MD, VisitorTy &Visitor) {
109324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  assert(MD->isVirtual() && "Method is not virtual!");
109424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
109524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
109624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne       E = MD->end_overridden_methods(); I != E; ++I) {
109724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXMethodDecl *OverriddenMD = *I;
1098635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    if (!Visitor.visit(OverriddenMD))
1099635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      continue;
1100635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    visitAllOverriddenMethods(OverriddenMD, Visitor);
110124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
110224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
110324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1104635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovnamespace {
1105635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  struct OverriddenMethodsCollector {
1106635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    OverriddenMethodsSetTy *Methods;
1107635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
1108635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    bool visit(const CXXMethodDecl *MD) {
1109635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      // Don't recurse on this method if we've already collected it.
1110176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return Methods->insert(MD).second;
1111635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
1112635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  };
1113635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
1114635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
1115635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov/// ComputeAllOverriddenMethods - Given a method decl, will return a set of all
1116635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov/// the overridden methods that the function decl overrides.
1117635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovstatic void
1118635de28950ef84ae26308ff734e778bad1ddde92Timur IskhodzhanovComputeAllOverriddenMethods(const CXXMethodDecl *MD,
1119635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                            OverriddenMethodsSetTy& OverriddenMethods) {
1120635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  OverriddenMethodsCollector Collector = { &OverriddenMethods };
1121635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  visitAllOverriddenMethods(MD, Collector);
1122635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
1123635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
1124f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::ComputeThisAdjustments() {
112524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Now go through the method info map and see if any of the methods need
112624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // 'this' pointer adjustments.
112724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(),
112824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne       E = MethodInfoMap.end(); I != E; ++I) {
112924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXMethodDecl *MD = I->first;
113024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const MethodInfo &MethodInfo = I->second;
113124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
113224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Ignore adjustments for unused function pointers.
113324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    uint64_t VTableIndex = MethodInfo.VTableIndex;
113424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (Components[VTableIndex].getKind() ==
113524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        VTableComponent::CK_UnusedFunctionPointer)
113624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
113724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
113824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Get the final overrider for this method.
113924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    FinalOverriders::OverriderInfo Overrider =
114024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Overriders.getOverrider(MD, MethodInfo.BaseOffset);
114124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
114224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check if we need an adjustment at all.
114324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) {
114424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // When a return thunk is needed by a derived class that overrides a
114524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // virtual base, gcc uses a virtual 'this' adjustment as well.
114624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // While the thunk itself might be needed by vtables in subclasses or
114724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // in construction vtables, there doesn't seem to be a reason for using
114824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // the thunk in this vtable. Still, we do so to match gcc.
114924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (VTableThunks.lookup(VTableIndex).Return.isEmpty())
115024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        continue;
115124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
115224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
115324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    ThisAdjustment ThisAdjustment =
115424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
115524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
115624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (ThisAdjustment.isEmpty())
115724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
115824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
115924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Add it.
116024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VTableThunks[VTableIndex].This = ThisAdjustment;
116124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1162a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov    if (isa<CXXDestructorDecl>(MD)) {
116324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Add an adjustment for the deleting destructor as well.
116424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VTableThunks[VTableIndex + 1].This = ThisAdjustment;
116524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
116624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
116724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
116824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// Clear the method info map.
116924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  MethodInfoMap.clear();
117024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
117124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (isBuildingConstructorVTable()) {
117224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // We don't need to store thunk information for construction vtables.
117324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return;
117424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
117524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
117624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  for (VTableThunksMapTy::const_iterator I = VTableThunks.begin(),
117724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne       E = VTableThunks.end(); I != E; ++I) {
117824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const VTableComponent &Component = Components[I->first];
117924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const ThunkInfo &Thunk = I->second;
118024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXMethodDecl *MD;
118124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
118224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    switch (Component.getKind()) {
118324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    default:
118424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      llvm_unreachable("Unexpected vtable component kind!");
118524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_FunctionPointer:
118624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      MD = Component.getFunctionDecl();
118724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
118824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_CompleteDtorPointer:
118924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      MD = Component.getDestructorDecl();
119024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
119124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_DeletingDtorPointer:
119224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // We've already added the thunk when we saw the complete dtor pointer.
119324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
119424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
119524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
119624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (MD->getParent() == MostDerivedClass)
119724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      AddThunk(MD, Thunk);
119824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
119924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
120024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1201f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovReturnAdjustment
1202f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovItaniumVTableBuilder::ComputeReturnAdjustment(BaseOffset Offset) {
120324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ReturnAdjustment Adjustment;
120424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
120524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (!Offset.isEmpty()) {
120624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (Offset.VirtualBase) {
120724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Get the virtual base offset offset.
120824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (Offset.DerivedClass == MostDerivedClass) {
120924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // We can get the offset offset directly from our map.
1210c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov        Adjustment.Virtual.Itanium.VBaseOffsetOffset =
121124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          VBaseOffsetOffsets.lookup(Offset.VirtualBase).getQuantity();
121224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      } else {
1213c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov        Adjustment.Virtual.Itanium.VBaseOffsetOffset =
121424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          VTables.getVirtualBaseOffsetOffset(Offset.DerivedClass,
121524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                             Offset.VirtualBase).getQuantity();
121624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
121724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
121824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
121924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Adjustment.NonVirtual = Offset.NonVirtualOffset.getQuantity();
122024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
122124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
122224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return Adjustment;
122324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
122424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1225f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovBaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
1226f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    BaseSubobject Base, BaseSubobject Derived) const {
122724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *BaseRD = Base.getBase();
122824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *DerivedRD = Derived.getBase();
122924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
123024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  CXXBasePaths Paths(/*FindAmbiguities=*/true,
123124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                     /*RecordPaths=*/true, /*DetectVirtual=*/true);
123224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1233922cec29a9366f70d593d6225aea01dcd3daf8cfBenjamin Kramer  if (!DerivedRD->isDerivedFrom(BaseRD, Paths))
123424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    llvm_unreachable("Class must be derived from the passed in base class!");
123524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
123624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // We have to go through all the paths, and see which one leads us to the
123724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // right base subobject.
123824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  for (CXXBasePaths::const_paths_iterator I = Paths.begin(), E = Paths.end();
123924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne       I != E; ++I) {
124024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, *I);
124124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
124224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset;
124324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
124424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (Offset.VirtualBase) {
124524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // If we have a virtual base class, the non-virtual offset is relative
124624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // to the virtual base class offset.
124724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &LayoutClassLayout =
124824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(LayoutClass);
124924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
125024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      /// Get the virtual base offset, relative to the most derived class
125124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      /// layout.
125224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      OffsetToBaseSubobject +=
125324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        LayoutClassLayout.getVBaseClassOffset(Offset.VirtualBase);
125424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    } else {
125524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Otherwise, the non-virtual offset is relative to the derived class
125624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // offset.
125724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      OffsetToBaseSubobject += Derived.getBaseOffset();
125824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
125924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
126024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check if this path gives us the right base subobject.
126124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (OffsetToBaseSubobject == Base.getBaseOffset()) {
126224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Since we're going from the base class _to_ the derived class, we'll
126324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // invert the non-virtual offset here.
126424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
126524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      return Offset;
126624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
126724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
126824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
126924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return BaseOffset();
127024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
1271f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov
1272f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovThisAdjustment ItaniumVTableBuilder::ComputeThisAdjustment(
1273f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    const CXXMethodDecl *MD, CharUnits BaseOffsetInLayoutClass,
1274f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    FinalOverriders::OverriderInfo Overrider) {
127524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Ignore adjustments for pure virtual member functions.
127624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (Overrider.Method->isPure())
127724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return ThisAdjustment();
127824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
127924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  BaseSubobject OverriddenBaseSubobject(MD->getParent(),
128024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                        BaseOffsetInLayoutClass);
128124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
128224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
128324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                       Overrider.Offset);
128424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
128524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Compute the adjustment offset.
128624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
128724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                                      OverriderBaseSubobject);
128824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (Offset.isEmpty())
128924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return ThisAdjustment();
129024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
129124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ThisAdjustment Adjustment;
129224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
129324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (Offset.VirtualBase) {
129424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Get the vcall offset map for this virtual base.
129524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
129624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
129724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (VCallOffsets.empty()) {
129824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // We don't have vcall offsets for this virtual base, go ahead and
129924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // build them.
130024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass,
13016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                         /*FinalOverriders=*/nullptr,
130224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                         BaseSubobject(Offset.VirtualBase,
130324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                                       CharUnits::Zero()),
130424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                         /*BaseIsVirtual=*/true,
130524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                         /*OffsetInLayoutClass=*/
130624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                             CharUnits::Zero());
130724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
130824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VCallOffsets = Builder.getVCallOffsets();
130924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
131024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
131158b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    Adjustment.Virtual.Itanium.VCallOffsetOffset =
131224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VCallOffsets.getVCallOffsetOffset(MD).getQuantity();
131324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
131424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
131524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Set the non-virtual part of the adjustment.
131624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Adjustment.NonVirtual = Offset.NonVirtualOffset.getQuantity();
131724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
131824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return Adjustment;
131924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
1320f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov
1321f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::AddMethod(const CXXMethodDecl *MD,
1322f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                                     ReturnAdjustment ReturnAdjustment) {
132324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
132424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    assert(ReturnAdjustment.isEmpty() &&
132524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne           "Destructor can't have return adjustment!");
132624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1327a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov    // Add both the complete destructor and the deleting destructor.
1328a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov    Components.push_back(VTableComponent::MakeCompleteDtor(DD));
1329a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov    Components.push_back(VTableComponent::MakeDeletingDtor(DD));
133024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  } else {
133124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Add the return adjustment if necessary.
133224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!ReturnAdjustment.isEmpty())
133324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VTableThunks[Components.size()].Return = ReturnAdjustment;
133424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
133524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Add the function.
133624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Components.push_back(VTableComponent::MakeFunction(MD));
133724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
133824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
133924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
134024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// OverridesIndirectMethodInBase - Return whether the given member function
134124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// overrides any methods in the set of given bases.
134224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// Unlike OverridesMethodInBase, this checks "overriders of overriders".
134324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// For example, if we have:
134424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne///
134524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// struct A { virtual void f(); }
134624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// struct B : A { virtual void f(); }
134724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// struct C : B { virtual void f(); }
134824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne///
134924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// OverridesIndirectMethodInBase will return true if given C::f as the method
135024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// and { A } as the set of bases.
1351f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovstatic bool OverridesIndirectMethodInBases(
1352f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    const CXXMethodDecl *MD,
1353f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    ItaniumVTableBuilder::PrimaryBasesSetVectorTy &Bases) {
135424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (Bases.count(MD->getParent()))
135524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return true;
135624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
135724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
135824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne       E = MD->end_overridden_methods(); I != E; ++I) {
135924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXMethodDecl *OverriddenMD = *I;
136024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
136124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check "indirect overriders".
136224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
136324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      return true;
136424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
136524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
136624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return false;
136724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
136824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1369f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovbool ItaniumVTableBuilder::IsOverriderUsed(
1370f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    const CXXMethodDecl *Overrider, CharUnits BaseOffsetInLayoutClass,
1371f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
1372f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    CharUnits FirstBaseOffsetInLayoutClass) const {
137324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // If the base and the first base in the primary base chain have the same
137424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // offsets, then this overrider will be used.
137524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass)
137624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne   return true;
137724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
137824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // We know now that Base (or a direct or indirect base of it) is a primary
137924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // base in part of the class hierarchy, but not a primary base in the most
138024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // derived class.
138124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
138224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // If the overrider is the first base in the primary base chain, we know
138324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // that the overrider will be used.
138424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (Overrider->getParent() == FirstBaseInPrimaryBaseChain)
138524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return true;
1386f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov
1387f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov  ItaniumVTableBuilder::PrimaryBasesSetVectorTy PrimaryBases;
138824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
138924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *RD = FirstBaseInPrimaryBaseChain;
139024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  PrimaryBases.insert(RD);
139124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
139224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Now traverse the base chain, starting with the first base, until we find
139324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // the base that is no longer a primary base.
139424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  while (true) {
139524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
139624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
139724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
139824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!PrimaryBase)
139924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
140024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
140124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (Layout.isPrimaryBaseVirtual()) {
1402d4f5198ae07d9a4958d8191bac694ded12173ad9Benjamin Kramer      assert(Layout.getVBaseClassOffset(PrimaryBase).isZero() &&
140324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             "Primary base should always be at offset 0!");
140424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
140524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &LayoutClassLayout =
140624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(LayoutClass);
140724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
140824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Now check if this is the primary base that is not a primary base in the
140924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // most derived class.
141024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) !=
141124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          FirstBaseOffsetInLayoutClass) {
141224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // We found it, stop walking the chain.
141324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        break;
141424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
141524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    } else {
1416d4f5198ae07d9a4958d8191bac694ded12173ad9Benjamin Kramer      assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
141724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             "Primary base should always be at offset 0!");
141824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
141924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
142024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!PrimaryBases.insert(PrimaryBase))
142124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      llvm_unreachable("Found a duplicate primary base!");
142224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
142324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    RD = PrimaryBase;
142424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
142524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
142624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // If the final overrider is an override of one of the primary bases,
142724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // then we know that it will be used.
142824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return OverridesIndirectMethodInBases(Overrider, PrimaryBases);
142924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
143024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1431635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovtypedef llvm::SmallSetVector<const CXXRecordDecl *, 8> BasesSetVectorTy;
1432635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
143324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// FindNearestOverriddenMethod - Given a method, returns the overridden method
143424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// from the nearest base. Returns null if no method was found.
1435635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov/// The Bases are expected to be sorted in a base-to-derived order.
1436635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovstatic const CXXMethodDecl *
143724018467ddb13857b764182f7753764d2f32f87dPeter CollingbourneFindNearestOverriddenMethod(const CXXMethodDecl *MD,
1438635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                            BasesSetVectorTy &Bases) {
143924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  OverriddenMethodsSetTy OverriddenMethods;
144024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ComputeAllOverriddenMethods(MD, OverriddenMethods);
144124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
144224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  for (int I = Bases.size(), E = 0; I != E; --I) {
144324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXRecordDecl *PrimaryBase = Bases[I - 1];
144424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1445635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // Now check the overridden methods.
144624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    for (OverriddenMethodsSetTy::const_iterator I = OverriddenMethods.begin(),
144724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne         E = OverriddenMethods.end(); I != E; ++I) {
144824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const CXXMethodDecl *OverriddenMD = *I;
144924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
145024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // We found our overridden method.
145124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (OverriddenMD->getParent() == PrimaryBase)
145224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        return OverriddenMD;
145324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
145424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
14556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
14566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return nullptr;
1457f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov}
145824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1459f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::AddMethods(
1460f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    BaseSubobject Base, CharUnits BaseOffsetInLayoutClass,
1461f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
1462f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    CharUnits FirstBaseOffsetInLayoutClass,
1463f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    PrimaryBasesSetVectorTy &PrimaryBases) {
14642aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  // Itanium C++ ABI 2.5.2:
14652aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  //   The order of the virtual function pointers in a virtual table is the
14662aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  //   order of declaration of the corresponding member functions in the class.
14672aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  //
14682aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  //   There is an entry for any virtual function declared in a class,
14692aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  //   whether it is a new function or overrides a base class function,
14702aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  //   unless it overrides a function from the primary base, and conversion
14712aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  //   between their return types does not require an adjustment.
14722aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
147324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *RD = Base.getBase();
147424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
147524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
147624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
147724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits PrimaryBaseOffset;
147824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits PrimaryBaseOffsetInLayoutClass;
147924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (Layout.isPrimaryBaseVirtual()) {
1480d4f5198ae07d9a4958d8191bac694ded12173ad9Benjamin Kramer      assert(Layout.getVBaseClassOffset(PrimaryBase).isZero() &&
148124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             "Primary vbase should have a zero offset!");
148224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
148324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &MostDerivedClassLayout =
148424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(MostDerivedClass);
148524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
148624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      PrimaryBaseOffset =
148724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
148824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
148924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &LayoutClassLayout =
149024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(LayoutClass);
149124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
149224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      PrimaryBaseOffsetInLayoutClass =
149324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        LayoutClassLayout.getVBaseClassOffset(PrimaryBase);
149424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    } else {
1495d4f5198ae07d9a4958d8191bac694ded12173ad9Benjamin Kramer      assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
149624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             "Primary base should have a zero offset!");
149724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
149824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      PrimaryBaseOffset = Base.getBaseOffset();
149924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass;
150024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
150124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
150224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddMethods(BaseSubobject(PrimaryBase, PrimaryBaseOffset),
150324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne               PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
150424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne               FirstBaseOffsetInLayoutClass, PrimaryBases);
150524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
150624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!PrimaryBases.insert(PrimaryBase))
150724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      llvm_unreachable("Found a duplicate primary base!");
150824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
150924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
15106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  const CXXDestructorDecl *ImplicitVirtualDtor = nullptr;
15112aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
15122aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  typedef llvm::SmallVector<const CXXMethodDecl *, 8> NewVirtualFunctionsTy;
15132aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  NewVirtualFunctionsTy NewVirtualFunctions;
15142aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
151524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Now go through all virtual member functions and add them.
1516651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto *MD : RD->methods()) {
151724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!MD->isVirtual())
151824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
15190e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    MD = MD->getCanonicalDecl();
152024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
152124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Get the final overrider.
152224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    FinalOverriders::OverriderInfo Overrider =
152324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Overriders.getOverrider(MD, Base.getBaseOffset());
152424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
152524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check if this virtual member function overrides a method in a primary
152624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // base. If this is the case, and the return type doesn't require adjustment
152724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // then we can just use the member function from the primary base.
152824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (const CXXMethodDecl *OverriddenMD =
152924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          FindNearestOverriddenMethod(MD, PrimaryBases)) {
153024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (ComputeReturnAdjustmentBaseOffset(Context, MD,
153124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                            OverriddenMD).isEmpty()) {
153224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // Replace the method info of the overridden method with our own
153324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // method.
153424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        assert(MethodInfoMap.count(OverriddenMD) &&
153524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne               "Did not find the overridden method!");
153624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
153724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
153824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass,
153924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                              OverriddenMethodInfo.VTableIndex);
154024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
154124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        assert(!MethodInfoMap.count(MD) &&
154224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne               "Should not have method info for this method yet!");
154324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
154424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
154524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        MethodInfoMap.erase(OverriddenMD);
154624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
154724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // If the overridden method exists in a virtual base class or a direct
154824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // or indirect base class of a virtual base class, we need to emit a
154924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // thunk if we ever have a class hierarchy where the base class is not
155024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // a primary base in the complete object.
155124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        if (!isBuildingConstructorVTable() && OverriddenMD != MD) {
155224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          // Compute the this adjustment.
155324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          ThisAdjustment ThisAdjustment =
155424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
155524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                  Overrider);
155624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
155758b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov          if (ThisAdjustment.Virtual.Itanium.VCallOffsetOffset &&
155824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne              Overrider.Method->getParent() == MostDerivedClass) {
155924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
156024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            // There's no return adjustment from OverriddenMD and MD,
156124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            // but that doesn't mean there isn't one between MD and
156224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            // the final overrider.
156324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            BaseOffset ReturnAdjustmentOffset =
156424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne              ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
156524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            ReturnAdjustment ReturnAdjustment =
156624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne              ComputeReturnAdjustment(ReturnAdjustmentOffset);
156724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
156824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            // This is a virtual thunk for the most derived class, add it.
156924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            AddThunk(Overrider.Method,
157024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                     ThunkInfo(ThisAdjustment, ReturnAdjustment));
157124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          }
157224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        }
157324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
157424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        continue;
157524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
157624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
157724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
15782aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
15792aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      if (MD->isImplicit()) {
15802aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov        // Itanium C++ ABI 2.5.2:
15812aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov        //   If a class has an implicitly-defined virtual destructor,
15822aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov        //   its entries come after the declared virtual function pointers.
15832aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
15842aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov        assert(!ImplicitVirtualDtor &&
15852aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov               "Did already see an implicit virtual dtor!");
15862aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov        ImplicitVirtualDtor = DD;
15872aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov        continue;
15882aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      }
15892aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    }
15902aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
15912aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    NewVirtualFunctions.push_back(MD);
15922aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  }
15932aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
15942aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  if (ImplicitVirtualDtor)
15952aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    NewVirtualFunctions.push_back(ImplicitVirtualDtor);
15962aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
15972aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  for (NewVirtualFunctionsTy::const_iterator I = NewVirtualFunctions.begin(),
15982aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov       E = NewVirtualFunctions.end(); I != E; ++I) {
15992aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    const CXXMethodDecl *MD = *I;
16002aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
16012aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    // Get the final overrider.
16022aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    FinalOverriders::OverriderInfo Overrider =
16032aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      Overriders.getOverrider(MD, Base.getBaseOffset());
16042aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
160524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Insert the method info for this method.
160624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass,
160724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                          Components.size());
160824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
160924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    assert(!MethodInfoMap.count(MD) &&
161024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne           "Should not have method info for this method yet!");
161124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
161224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
161324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check if this overrider is going to be used.
161424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXMethodDecl *OverriderMD = Overrider.Method;
161524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass,
161624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                         FirstBaseInPrimaryBaseChain,
161724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                         FirstBaseOffsetInLayoutClass)) {
161824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Components.push_back(VTableComponent::MakeUnusedFunction(OverriderMD));
161924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
162024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
16212aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
162224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check if this overrider needs a return adjustment.
162324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // We don't want to do this for pure virtual member functions.
162424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    BaseOffset ReturnAdjustmentOffset;
162524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!OverriderMD->isPure()) {
162624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      ReturnAdjustmentOffset =
162724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
162824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
162924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
163024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    ReturnAdjustment ReturnAdjustment =
163124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      ComputeReturnAdjustment(ReturnAdjustmentOffset);
163224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
163324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddMethod(Overrider.Method, ReturnAdjustment);
163424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
163524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
163624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1637f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::LayoutVTable() {
163824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  LayoutPrimaryAndSecondaryVTables(BaseSubobject(MostDerivedClass,
163924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                                 CharUnits::Zero()),
164024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                   /*BaseIsMorallyVirtual=*/false,
164124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                   MostDerivedClassIsVirtual,
164224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                   MostDerivedClassOffset);
164324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
164424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VisitedVirtualBasesSetTy VBases;
164524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
164624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Determine the primary virtual bases.
164724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
164824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                               VBases);
164924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VBases.clear();
165024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
165124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
165224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
165324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // -fapple-kext adds an extra entry at end of vtbl.
16544e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  bool IsAppleKext = Context.getLangOpts().AppleKext;
165524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (IsAppleKext)
165624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Components.push_back(VTableComponent::MakeVCallOffset(CharUnits::Zero()));
165724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
1658f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov
1659f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
1660f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    BaseSubobject Base, bool BaseIsMorallyVirtual,
1661f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    bool BaseIsVirtualInLayoutClass, CharUnits OffsetInLayoutClass) {
166224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!");
166324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
166424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Add vcall and vbase offsets for this vtable.
166524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders,
166624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                     Base, BaseIsVirtualInLayoutClass,
166724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                     OffsetInLayoutClass);
166824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Components.append(Builder.components_begin(), Builder.components_end());
166924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
167024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Check if we need to add these vcall offsets.
167124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) {
167224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Base.getBase()];
167324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
167424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (VCallOffsets.empty())
167524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VCallOffsets = Builder.getVCallOffsets();
167624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
167724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
167824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // If we're laying out the most derived class we want to keep track of the
167924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // virtual base class offset offsets.
168024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (Base.getBase() == MostDerivedClass)
168124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
168224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1683a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov  // Add the offset to top.
1684a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov  CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
1685a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov  Components.push_back(VTableComponent::MakeOffsetToTop(OffsetToTop));
1686649c7316aa29181df7270732722fe5d07ab3c7adTimur Iskhodzhanov
1687a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov  // Next, add the RTTI.
1688a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov  Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
1689649c7316aa29181df7270732722fe5d07ab3c7adTimur Iskhodzhanov
169024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  uint64_t AddressPoint = Components.size();
169124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
169224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Now go through all virtual member functions and add them.
169324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  PrimaryBasesSetVectorTy PrimaryBases;
169424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  AddMethods(Base, OffsetInLayoutClass,
169524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             Base.getBase(), OffsetInLayoutClass,
169624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             PrimaryBases);
169724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
16982aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  const CXXRecordDecl *RD = Base.getBase();
16992aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  if (RD == MostDerivedClass) {
17002aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    assert(MethodVTableIndices.empty());
17012aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(),
17022aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov         E = MethodInfoMap.end(); I != E; ++I) {
17032aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      const CXXMethodDecl *MD = I->first;
17042aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      const MethodInfo &MI = I->second;
17052aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1706a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov        MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
1707a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov            = MI.VTableIndex - AddressPoint;
1708a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov        MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
1709a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov            = MI.VTableIndex + 1 - AddressPoint;
17102aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      } else {
17112aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov        MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
17122aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      }
17132aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    }
17142aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  }
17152aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
171624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Compute 'this' pointer adjustments.
171724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ComputeThisAdjustments();
171824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
171924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Add all address points.
172024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  while (true) {
172124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddressPoints.insert(std::make_pair(
172224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseSubobject(RD, OffsetInLayoutClass),
172324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      AddressPoint));
172424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
172524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
172624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
172724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
172824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!PrimaryBase)
172924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
173024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
173124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (Layout.isPrimaryBaseVirtual()) {
173224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Check if this virtual primary base is a primary base in the layout
173324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // class. If it's not, we don't want to add it.
173424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &LayoutClassLayout =
173524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(LayoutClass);
173624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
173724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) !=
173824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          OffsetInLayoutClass) {
173924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // We don't want to add this class (or any of its primary bases).
174024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        break;
174124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
174224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
174324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
174424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    RD = PrimaryBase;
174524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
174624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
174724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Layout secondary vtables.
174824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  LayoutSecondaryVTables(Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
174924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
175024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1751f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid
1752f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovItaniumVTableBuilder::LayoutSecondaryVTables(BaseSubobject Base,
1753f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                                             bool BaseIsMorallyVirtual,
1754f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                                             CharUnits OffsetInLayoutClass) {
175524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Itanium C++ ABI 2.5.2:
175624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   Following the primary virtual table of a derived class are secondary
175724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   virtual tables for each of its proper base classes, except any primary
175824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   base(s) with which it shares its primary virtual table.
175924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
176024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *RD = Base.getBase();
176124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
176224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
176324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1764651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &B : RD->bases()) {
176524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Ignore virtual bases, we'll emit them later.
1766651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (B.isVirtual())
176724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
176824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1769651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
177024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
177124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Ignore bases that don't have a vtable.
177224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!BaseDecl->isDynamicClass())
177324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
177424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
177524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (isBuildingConstructorVTable()) {
177624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Itanium C++ ABI 2.6.4:
177724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      //   Some of the base class subobjects may not need construction virtual
177824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      //   tables, which will therefore not be present in the construction
177924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      //   virtual table group, even though the subobject virtual tables are
178024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      //   present in the main virtual table group for the complete object.
178124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (!BaseIsMorallyVirtual && !BaseDecl->getNumVBases())
178224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        continue;
178324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
178424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
178524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Get the base offset of this base.
178624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits RelativeBaseOffset = Layout.getBaseClassOffset(BaseDecl);
178724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits BaseOffset = Base.getBaseOffset() + RelativeBaseOffset;
178824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
178924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits BaseOffsetInLayoutClass =
179024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      OffsetInLayoutClass + RelativeBaseOffset;
179124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
179224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Don't emit a secondary vtable for a primary base. We might however want
179324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // to emit secondary vtables for other bases of this base.
179424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (BaseDecl == PrimaryBase) {
179524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      LayoutSecondaryVTables(BaseSubobject(BaseDecl, BaseOffset),
179624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                             BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
179724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
179824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
179924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
180024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Layout the primary vtable (and any secondary vtables) for this base.
180124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    LayoutPrimaryAndSecondaryVTables(
180224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseSubobject(BaseDecl, BaseOffset),
180324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseIsMorallyVirtual,
180424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      /*BaseIsVirtualInLayoutClass=*/false,
180524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseOffsetInLayoutClass);
180624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
180724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
180824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1809f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
1810f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    const CXXRecordDecl *RD, CharUnits OffsetInLayoutClass,
1811f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    VisitedVirtualBasesSetTy &VBases) {
181224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
181324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
181424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Check if this base has a primary base.
181524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
181624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
181724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check if it's virtual.
181824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (Layout.isPrimaryBaseVirtual()) {
181924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      bool IsPrimaryVirtualBase = true;
182024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
182124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (isBuildingConstructorVTable()) {
182224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // Check if the base is actually a primary base in the class we use for
182324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // layout.
182424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        const ASTRecordLayout &LayoutClassLayout =
182524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Context.getASTRecordLayout(LayoutClass);
182624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
182724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        CharUnits PrimaryBaseOffsetInLayoutClass =
182824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          LayoutClassLayout.getVBaseClassOffset(PrimaryBase);
182924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
183024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // We know that the base is not a primary base in the layout class if
183124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // the base offsets are different.
183224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass)
183324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          IsPrimaryVirtualBase = false;
183424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
183524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
183624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (IsPrimaryVirtualBase)
183724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        PrimaryVirtualBases.insert(PrimaryBase);
183824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
183924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
184024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
184124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Traverse bases, looking for more primary virtual bases.
1842651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &B : RD->bases()) {
1843651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
184424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
184524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits BaseOffsetInLayoutClass;
184624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1847651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (B.isVirtual()) {
1848176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (!VBases.insert(BaseDecl).second)
184924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        continue;
185024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
185124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &LayoutClassLayout =
185224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(LayoutClass);
185324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
185424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseOffsetInLayoutClass =
185524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        LayoutClassLayout.getVBaseClassOffset(BaseDecl);
185624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    } else {
185724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseOffsetInLayoutClass =
185824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        OffsetInLayoutClass + Layout.getBaseClassOffset(BaseDecl);
185924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
186024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
186124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases);
186224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
186324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
186424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1865f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
1866f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases) {
186724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Itanium C++ ABI 2.5.2:
186824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   Then come the virtual base virtual tables, also in inheritance graph
186924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   order, and again excluding primary bases (which share virtual tables with
187024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   the classes for which they are primary).
1871651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &B : RD->bases()) {
1872651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
187324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
187424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check if this base needs a vtable. (If it's virtual, not a primary base
187524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // of some other class, and we haven't visited it before).
1876176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (B.isVirtual() && BaseDecl->isDynamicClass() &&
1877176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        !PrimaryVirtualBases.count(BaseDecl) &&
1878176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        VBases.insert(BaseDecl).second) {
187924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &MostDerivedClassLayout =
188024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(MostDerivedClass);
188124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      CharUnits BaseOffset =
188224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
188324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
188424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &LayoutClassLayout =
188524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(LayoutClass);
188624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      CharUnits BaseOffsetInLayoutClass =
188724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        LayoutClassLayout.getVBaseClassOffset(BaseDecl);
188824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
188924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      LayoutPrimaryAndSecondaryVTables(
189024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        BaseSubobject(BaseDecl, BaseOffset),
189124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        /*BaseIsMorallyVirtual=*/true,
189224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        /*BaseIsVirtualInLayoutClass=*/true,
189324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        BaseOffsetInLayoutClass);
189424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
189524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
189624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // We only need to check the base for virtual base vtables if it actually
189724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // has virtual bases.
189824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (BaseDecl->getNumVBases())
189924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      LayoutVTablesForVirtualBases(BaseDecl, VBases);
190024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
190124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
190224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
190324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// dumpLayout - Dump the vtable layout.
1904f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
190515a0de95f5b364cfb96bacc644f491215bd92098Timur Iskhodzhanov  // FIXME: write more tests that actually use the dumpLayout output to prevent
1906f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov  // ItaniumVTableBuilder regressions.
190724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
190824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (isBuildingConstructorVTable()) {
190924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << "Construction vtable for ('";
1910651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    MostDerivedClass->printQualifiedName(Out);
1911651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Out << "', ";
191224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << MostDerivedClassOffset.getQuantity() << ") in '";
1913651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    LayoutClass->printQualifiedName(Out);
191424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  } else {
191524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << "Vtable for '";
1916651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    MostDerivedClass->printQualifiedName(Out);
191724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
191824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Out << "' (" << Components.size() << " entries).\n";
191924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
192024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Iterate through the address points and insert them into a new map where
192124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // they are keyed by the index and not the base object.
192224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Since an address point can be shared by multiple subobjects, we use an
192324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // STL multimap.
192424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
192524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  for (AddressPointsMapTy::const_iterator I = AddressPoints.begin(),
192624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne       E = AddressPoints.end(); I != E; ++I) {
192724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const BaseSubobject& Base = I->first;
192824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    uint64_t Index = I->second;
192924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
193024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddressPointsByIndex.insert(std::make_pair(Index, Base));
193124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
193224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
193324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  for (unsigned I = 0, E = Components.size(); I != E; ++I) {
193424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    uint64_t Index = I;
193524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
193624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << llvm::format("%4d | ", I);
193724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
193824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const VTableComponent &Component = Components[I];
193924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
194024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Dump the component.
194124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    switch (Component.getKind()) {
194224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
194324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_VCallOffset:
194424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << "vcall_offset ("
194524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          << Component.getVCallOffset().getQuantity()
194624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          << ")";
194724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
194824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
194924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_VBaseOffset:
195024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << "vbase_offset ("
195124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          << Component.getVBaseOffset().getQuantity()
195224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          << ")";
195324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
195424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
195524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_OffsetToTop:
195624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << "offset_to_top ("
195724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          << Component.getOffsetToTop().getQuantity()
195824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          << ")";
195924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
196024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
196124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_RTTI:
1962651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Component.getRTTIDecl()->printQualifiedName(Out);
1963651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Out << " RTTI";
196424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
196524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
196624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_FunctionPointer: {
196724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const CXXMethodDecl *MD = Component.getFunctionDecl();
196824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
196924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      std::string Str =
197024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
197124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    MD);
197224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << Str;
197324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (MD->isPure())
197424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << " [pure]";
197524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1976d954ab47c681b8afc94bc3accbee708a05e6768eDavid Blaikie      if (MD->isDeleted())
1977d954ab47c681b8afc94bc3accbee708a05e6768eDavid Blaikie        Out << " [deleted]";
1978d954ab47c681b8afc94bc3accbee708a05e6768eDavid Blaikie
197924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      ThunkInfo Thunk = VTableThunks.lookup(I);
198024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (!Thunk.isEmpty()) {
198124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // If this function pointer has a return adjustment, dump it.
198224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        if (!Thunk.Return.isEmpty()) {
198324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << "\n       [return adjustment: ";
198424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << Thunk.Return.NonVirtual << " non-virtual";
198524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1986c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov          if (Thunk.Return.Virtual.Itanium.VBaseOffsetOffset) {
1987c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov            Out << ", " << Thunk.Return.Virtual.Itanium.VBaseOffsetOffset;
198824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            Out << " vbase offset offset";
198924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          }
199024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
199124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << ']';
199224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        }
199324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
199424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // If this function pointer has a 'this' pointer adjustment, dump it.
199524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        if (!Thunk.This.isEmpty()) {
199624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << "\n       [this adjustment: ";
199724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << Thunk.This.NonVirtual << " non-virtual";
199824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
199958b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov          if (Thunk.This.Virtual.Itanium.VCallOffsetOffset) {
200058b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov            Out << ", " << Thunk.This.Virtual.Itanium.VCallOffsetOffset;
200124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            Out << " vcall offset offset";
200224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          }
200324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
200424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << ']';
200524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        }
200624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
200724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
200824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
200924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
201024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
201124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_CompleteDtorPointer:
201224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_DeletingDtorPointer: {
201324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      bool IsComplete =
201424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Component.getKind() == VTableComponent::CK_CompleteDtorPointer;
201524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
201624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const CXXDestructorDecl *DD = Component.getDestructorDecl();
201724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2018651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      DD->printQualifiedName(Out);
201924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (IsComplete)
202024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << "() [complete]";
202124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      else
202224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << "() [deleting]";
202324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
202424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (DD->isPure())
202524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << " [pure]";
202624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
202724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      ThunkInfo Thunk = VTableThunks.lookup(I);
202824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (!Thunk.isEmpty()) {
202924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // If this destructor has a 'this' pointer adjustment, dump it.
203024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        if (!Thunk.This.isEmpty()) {
203124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << "\n       [this adjustment: ";
203224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << Thunk.This.NonVirtual << " non-virtual";
203324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
203458b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov          if (Thunk.This.Virtual.Itanium.VCallOffsetOffset) {
203558b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov            Out << ", " << Thunk.This.Virtual.Itanium.VCallOffsetOffset;
203624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            Out << " vcall offset offset";
203724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          }
203824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
203924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << ']';
204024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        }
204124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
204224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
204324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
204424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
204524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
204624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_UnusedFunctionPointer: {
204724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const CXXMethodDecl *MD = Component.getUnusedFunctionDecl();
204824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
204924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      std::string Str =
205024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
205124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    MD);
205224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << "[unused] " << Str;
205324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (MD->isPure())
205424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << " [pure]";
205524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
205624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
205724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
205824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
205924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << '\n';
206024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
206124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Dump the next address point.
206224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    uint64_t NextIndex = Index + 1;
206324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (AddressPointsByIndex.count(NextIndex)) {
206424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (AddressPointsByIndex.count(NextIndex) == 1) {
206524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        const BaseSubobject &Base =
206624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          AddressPointsByIndex.find(NextIndex)->second;
206724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2068651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        Out << "       -- (";
2069651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        Base.getBase()->printQualifiedName(Out);
207024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << ", " << Base.getBaseOffset().getQuantity();
207124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << ") vtable address --\n";
207224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      } else {
207324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        CharUnits BaseOffset =
207424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
207524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
207624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // We store the class names in a set to get a stable order.
207724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        std::set<std::string> ClassNames;
207824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        for (std::multimap<uint64_t, BaseSubobject>::const_iterator I =
207924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             AddressPointsByIndex.lower_bound(NextIndex), E =
208024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             AddressPointsByIndex.upper_bound(NextIndex); I != E; ++I) {
208124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          assert(I->second.getBaseOffset() == BaseOffset &&
208224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                 "Invalid base offset!");
208324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          const CXXRecordDecl *RD = I->second.getBase();
208424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          ClassNames.insert(RD->getQualifiedNameAsString());
208524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        }
208624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
208724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        for (std::set<std::string>::const_iterator I = ClassNames.begin(),
208824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             E = ClassNames.end(); I != E; ++I) {
208924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << "       -- (" << *I;
209024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << ", " << BaseOffset.getQuantity() << ") vtable address --\n";
209124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        }
209224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
209324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
209424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
209524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
209624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Out << '\n';
209724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
209824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (isBuildingConstructorVTable())
209924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return;
210024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
210124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (MostDerivedClass->getNumVBases()) {
210224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // We store the virtual base class names and their offsets in a map to get
210324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // a stable order.
210424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
210524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    std::map<std::string, CharUnits> ClassNamesAndOffsets;
210624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    for (VBaseOffsetOffsetsMapTy::const_iterator I = VBaseOffsetOffsets.begin(),
210724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne         E = VBaseOffsetOffsets.end(); I != E; ++I) {
210824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      std::string ClassName = I->first->getQualifiedNameAsString();
210924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      CharUnits OffsetOffset = I->second;
211024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      ClassNamesAndOffsets.insert(
211124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          std::make_pair(ClassName, OffsetOffset));
211224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
211324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
211424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << "Virtual base offset offsets for '";
2115651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    MostDerivedClass->printQualifiedName(Out);
2116651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Out << "' (";
211724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << ClassNamesAndOffsets.size();
211824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << (ClassNamesAndOffsets.size() == 1 ? " entry" : " entries") << ").\n";
211924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
212024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    for (std::map<std::string, CharUnits>::const_iterator I =
212124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne         ClassNamesAndOffsets.begin(), E = ClassNamesAndOffsets.end();
212224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne         I != E; ++I)
212324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << "   " << I->first << " | " << I->second.getQuantity() << '\n';
212424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
212524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << "\n";
212624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
212724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
212824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (!Thunks.empty()) {
212924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // We store the method names in a map to get a stable order.
213024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
213124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
213224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    for (ThunksMapTy::const_iterator I = Thunks.begin(), E = Thunks.end();
213324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne         I != E; ++I) {
213424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const CXXMethodDecl *MD = I->first;
213524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      std::string MethodName =
213624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
213724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    MD);
213824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
213924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
214024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
214124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
214224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    for (std::map<std::string, const CXXMethodDecl *>::const_iterator I =
214324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne         MethodNamesAndDecls.begin(), E = MethodNamesAndDecls.end();
214424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne         I != E; ++I) {
214524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const std::string &MethodName = I->first;
214624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const CXXMethodDecl *MD = I->second;
214724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
214824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      ThunkInfoVectorTy ThunksVector = Thunks[MD];
21492cb17a06befb61b1434aaa991652fea4338c95d7Timur Iskhodzhanov      std::sort(ThunksVector.begin(), ThunksVector.end(),
2150651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                [](const ThunkInfo &LHS, const ThunkInfo &RHS) {
21516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        assert(LHS.Method == nullptr && RHS.Method == nullptr);
2152651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return);
2153651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      });
215424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
215524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size();
215624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n";
215724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
215824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      for (unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
215924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        const ThunkInfo &Thunk = ThunksVector[I];
216024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
216124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << llvm::format("%4d | ", I);
216224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
216324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // If this function pointer has a return pointer adjustment, dump it.
216424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        if (!Thunk.Return.isEmpty()) {
216515a0de95f5b364cfb96bacc644f491215bd92098Timur Iskhodzhanov          Out << "return adjustment: " << Thunk.Return.NonVirtual;
216624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << " non-virtual";
2167c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov          if (Thunk.Return.Virtual.Itanium.VBaseOffsetOffset) {
2168c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov            Out << ", " << Thunk.Return.Virtual.Itanium.VBaseOffsetOffset;
216924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            Out << " vbase offset offset";
217024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          }
217124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
217224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          if (!Thunk.This.isEmpty())
217324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            Out << "\n       ";
217424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        }
217524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
217624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // If this function pointer has a 'this' pointer adjustment, dump it.
217724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        if (!Thunk.This.isEmpty()) {
217824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << "this adjustment: ";
217924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << Thunk.This.NonVirtual << " non-virtual";
218024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
218158b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov          if (Thunk.This.Virtual.Itanium.VCallOffsetOffset) {
218258b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov            Out << ", " << Thunk.This.Virtual.Itanium.VCallOffsetOffset;
218324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            Out << " vcall offset offset";
218424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          }
218524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        }
218624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
218724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << '\n';
218824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
218924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
219024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << '\n';
219124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
219224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
219324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
219424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Compute the vtable indices for all the member functions.
219524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Store them in a map keyed by the index so we'll get a sorted table.
219624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  std::map<uint64_t, std::string> IndicesMap;
219724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2198651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto *MD : MostDerivedClass->methods()) {
219924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // We only want virtual member functions.
220024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!MD->isVirtual())
220124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
22020e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    MD = MD->getCanonicalDecl();
220324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
220424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    std::string MethodName =
220524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
220624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                  MD);
220724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
220824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2209a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov      GlobalDecl GD(DD, Dtor_Complete);
2210a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov      assert(MethodVTableIndices.count(GD));
2211a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov      uint64_t VTableIndex = MethodVTableIndices[GD];
2212a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov      IndicesMap[VTableIndex] = MethodName + " [complete]";
2213a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov      IndicesMap[VTableIndex + 1] = MethodName + " [deleting]";
221424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    } else {
22152aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      assert(MethodVTableIndices.count(MD));
22162aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      IndicesMap[MethodVTableIndices[MD]] = MethodName;
221724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
221824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
221924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
222024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Print the vtable indices for all the member functions.
222124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (!IndicesMap.empty()) {
222224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << "VTable indices for '";
2223651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    MostDerivedClass->printQualifiedName(Out);
222424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << "' (" << IndicesMap.size() << " entries).\n";
222524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
222624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    for (std::map<uint64_t, std::string>::const_iterator I = IndicesMap.begin(),
222724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne         E = IndicesMap.end(); I != E; ++I) {
222824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      uint64_t VTableIndex = I->first;
222924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const std::string &MethodName = I->second;
223024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
22312aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      Out << llvm::format("%4" PRIu64 " | ", VTableIndex) << MethodName
223279a55010ed5afa88939e74186494ecfadefbfa43Benjamin Kramer          << '\n';
223324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
223424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
223524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
223624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Out << '\n';
223724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
223824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
223924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
224024018467ddb13857b764182f7753764d2f32f87dPeter CollingbourneVTableLayout::VTableLayout(uint64_t NumVTableComponents,
224124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                           const VTableComponent *VTableComponents,
224224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                           uint64_t NumVTableThunks,
224324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                           const VTableThunkTy *VTableThunks,
2244649c7316aa29181df7270732722fe5d07ab3c7adTimur Iskhodzhanov                           const AddressPointsMapTy &AddressPoints,
2245649c7316aa29181df7270732722fe5d07ab3c7adTimur Iskhodzhanov                           bool IsMicrosoftABI)
224624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  : NumVTableComponents(NumVTableComponents),
224724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VTableComponents(new VTableComponent[NumVTableComponents]),
224824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    NumVTableThunks(NumVTableThunks),
224924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VTableThunks(new VTableThunkTy[NumVTableThunks]),
2250649c7316aa29181df7270732722fe5d07ab3c7adTimur Iskhodzhanov    AddressPoints(AddressPoints),
2251649c7316aa29181df7270732722fe5d07ab3c7adTimur Iskhodzhanov    IsMicrosoftABI(IsMicrosoftABI) {
225224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  std::copy(VTableComponents, VTableComponents+NumVTableComponents,
22538fb9fb66d415ee40447277f649ecdb12b4964385Benjamin Kramer            this->VTableComponents.get());
22548fb9fb66d415ee40447277f649ecdb12b4964385Benjamin Kramer  std::copy(VTableThunks, VTableThunks+NumVTableThunks,
22558fb9fb66d415ee40447277f649ecdb12b4964385Benjamin Kramer            this->VTableThunks.get());
22562cb17a06befb61b1434aaa991652fea4338c95d7Timur Iskhodzhanov  std::sort(this->VTableThunks.get(),
22572cb17a06befb61b1434aaa991652fea4338c95d7Timur Iskhodzhanov            this->VTableThunks.get() + NumVTableThunks,
2258651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            [](const VTableLayout::VTableThunkTy &LHS,
2259651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines               const VTableLayout::VTableThunkTy &RHS) {
2260651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
2261651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines           "Different thunks should have unique indices!");
2262651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return LHS.first < RHS.first;
2263651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  });
226424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
226524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
22668fb9fb66d415ee40447277f649ecdb12b4964385Benjamin KramerVTableLayout::~VTableLayout() { }
226724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2268f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovItaniumVTableContext::ItaniumVTableContext(ASTContext &Context)
2269651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    : VTableContextBase(/*MS=*/false) {}
2270649c7316aa29181df7270732722fe5d07ab3c7adTimur Iskhodzhanov
2271f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovItaniumVTableContext::~ItaniumVTableContext() {
227224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  llvm::DeleteContainerSeconds(VTableLayouts);
227324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
227424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2275f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovuint64_t ItaniumVTableContext::getMethodVTableIndex(GlobalDecl GD) {
227624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
227724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (I != MethodVTableIndices.end())
227824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return I->second;
227924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
228024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
228124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2282635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  computeVTableRelatedInformation(RD);
228324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
228424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  I = MethodVTableIndices.find(GD);
228524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  assert(I != MethodVTableIndices.end() && "Did not find index!");
228624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return I->second;
228724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
228824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2289f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovCharUnits
2290f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovItaniumVTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
2291f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                                                 const CXXRecordDecl *VBase) {
229224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ClassPairTy ClassPair(RD, VBase);
229324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
229424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VirtualBaseClassOffsetOffsetsMapTy::iterator I =
229524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VirtualBaseClassOffsetOffsets.find(ClassPair);
229624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (I != VirtualBaseClassOffsetOffsets.end())
229724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return I->second;
22986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
22996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  VCallAndVBaseOffsetBuilder Builder(RD, RD, /*FinalOverriders=*/nullptr,
230024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                     BaseSubobject(RD, CharUnits::Zero()),
230124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                     /*BaseIsVirtual=*/false,
230224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                     /*OffsetInLayoutClass=*/CharUnits::Zero());
230324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
230424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  for (VCallAndVBaseOffsetBuilder::VBaseOffsetOffsetsMapTy::const_iterator I =
230524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne       Builder.getVBaseOffsetOffsets().begin(),
230624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne       E = Builder.getVBaseOffsetOffsets().end(); I != E; ++I) {
230724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Insert all types.
230824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    ClassPairTy ClassPair(RD, I->first);
230924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
231024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VirtualBaseClassOffsetOffsets.insert(
231124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        std::make_pair(ClassPair, I->second));
231224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
231324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
231424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  I = VirtualBaseClassOffsetOffsets.find(ClassPair);
231524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  assert(I != VirtualBaseClassOffsetOffsets.end() && "Did not find index!");
231624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
231724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return I->second;
231824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
231924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2320f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovstatic VTableLayout *CreateVTableLayout(const ItaniumVTableBuilder &Builder) {
232124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  SmallVector<VTableLayout::VTableThunkTy, 1>
232224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
232324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
232424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return new VTableLayout(Builder.getNumVTableComponents(),
232524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                          Builder.vtable_component_begin(),
232624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                          VTableThunks.size(),
232724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                          VTableThunks.data(),
2328649c7316aa29181df7270732722fe5d07ab3c7adTimur Iskhodzhanov                          Builder.getAddressPoints(),
2329a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov                          /*IsMicrosoftABI=*/false);
233024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
233124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2332f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid
2333f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovItaniumVTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD) {
233424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const VTableLayout *&Entry = VTableLayouts[RD];
233524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
233624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Check if we've computed this information before.
233724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (Entry)
233824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return;
233924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2340f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov  ItaniumVTableBuilder Builder(*this, RD, CharUnits::Zero(),
2341f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                               /*MostDerivedClassIsVirtual=*/0, RD);
234224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Entry = CreateVTableLayout(Builder);
234324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
23442aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  MethodVTableIndices.insert(Builder.vtable_indices_begin(),
23452aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov                             Builder.vtable_indices_end());
23462aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
234724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Add the known thunks.
234824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
234924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
235024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // If we don't have the vbase information for this class, insert it.
235124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // getVirtualBaseOffsetOffset will compute it separately without computing
235224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // the rest of the vtable related information.
235324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (!RD->getNumVBases())
235424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return;
235524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2356432d488305492bd998dbcd200ed500389c7602f5Timur Iskhodzhanov  const CXXRecordDecl *VBase =
2357432d488305492bd998dbcd200ed500389c7602f5Timur Iskhodzhanov    RD->vbases_begin()->getType()->getAsCXXRecordDecl();
235824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
235924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
236024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return;
2361f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov
2362f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov  for (ItaniumVTableBuilder::VBaseOffsetOffsetsMapTy::const_iterator
2363f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov           I = Builder.getVBaseOffsetOffsets().begin(),
2364f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov           E = Builder.getVBaseOffsetOffsets().end();
2365f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov       I != E; ++I) {
236624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Insert all types.
236724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    ClassPairTy ClassPair(RD, I->first);
236824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
236924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I->second));
237024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
237124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
237224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2373f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovVTableLayout *ItaniumVTableContext::createConstructionVTableLayout(
2374f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset,
2375f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass) {
2376f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov  ItaniumVTableBuilder Builder(*this, MostDerivedClass, MostDerivedClassOffset,
2377f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                               MostDerivedClassIsVirtual, LayoutClass);
237824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return CreateVTableLayout(Builder);
237924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
2380635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2381635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovnamespace {
2382635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2383635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov// Vtables in the Microsoft ABI are different from the Itanium ABI.
2384635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//
2385635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov// The main differences are:
2386635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//  1. Separate vftable and vbtable.
2387635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//
2388635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//  2. Each subobject with a vfptr gets its own vftable rather than an address
2389635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     point in a single vtable shared between all the subobjects.
2390635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     Each vftable is represented by a separate section and virtual calls
2391635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     must be done using the vftable which has a slot for the function to be
2392635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     called.
2393635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//
2394635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//  3. Virtual method definitions expect their 'this' parameter to point to the
2395635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     first vfptr whose table provides a compatible overridden method.  In many
2396635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     cases, this permits the original vf-table entry to directly call
2397635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     the method instead of passing through a thunk.
2398176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     See example before VFTableBuilder::ComputeThisOffset below.
2399635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//
2400635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     A compatible overridden method is one which does not have a non-trivial
2401635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     covariant-return adjustment.
2402635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//
2403635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     The first vfptr is the one with the lowest offset in the complete-object
2404635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     layout of the defining class, and the method definition will subtract
2405635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     that constant offset from the parameter value to get the real 'this'
2406635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     value.  Therefore, if the offset isn't really constant (e.g. if a virtual
2407635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     function defined in a virtual base is overridden in a more derived
2408635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     virtual base and these bases have a reverse order in the complete
2409635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     object), the vf-table may require a this-adjustment thunk.
2410635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//
2411635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//  4. vftables do not contain new entries for overrides that merely require
2412635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     this-adjustment.  Together with #3, this keeps vf-tables smaller and
2413635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     eliminates the need for this-adjustment thunks in many cases, at the cost
2414635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     of often requiring redundant work to adjust the "this" pointer.
2415635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//
2416635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//  5. Instead of VTT and constructor vtables, vbtables and vtordisps are used.
2417635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     Vtordisps are emitted into the class layout if a class has
2418635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//      a) a user-defined ctor/dtor
2419635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     and
2420635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//      b) a method overriding a method in a virtual base.
2421176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2422176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  To get a better understanding of this code,
2423176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  you might want to see examples in test/CodeGenCXX/microsoft-abi-vtables-*.cpp
2424635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2425635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovclass VFTableBuilder {
2426635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovpublic:
24275f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov  typedef MicrosoftVTableContext::MethodVFTableLocation MethodVFTableLocation;
2428635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2429635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
2430635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    MethodVFTableLocationsTy;
2431635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2432651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator>
2433651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    method_locations_range;
2434651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
2435635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovprivate:
24365f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov  /// VTables - Global vtable information.
24375f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov  MicrosoftVTableContext &VTables;
24385f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov
2439635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// Context - The ASTContext which we will use for layout information.
2440635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  ASTContext &Context;
2441635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2442635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// MostDerivedClass - The most derived class for which we're building this
2443635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// vtable.
2444635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const CXXRecordDecl *MostDerivedClass;
2445635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2446635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const ASTRecordLayout &MostDerivedClassLayout;
2447635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2448651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const VPtrInfo &WhichVFPtr;
2449635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2450635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// FinalOverriders - The final overriders of the most derived class.
2451635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const FinalOverriders Overriders;
2452635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2453635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// Components - The components of the vftable being built.
2454635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  SmallVector<VTableComponent, 64> Components;
2455635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2456635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  MethodVFTableLocationsTy MethodVFTableLocations;
2457635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2458c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// \brief Does this class have an RTTI component?
2459c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool HasRTTIComponent;
2460c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2461635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// MethodInfo - Contains information about a method in a vtable.
2462635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// (Used for computing 'this' pointer adjustment thunks.
2463635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  struct MethodInfo {
2464635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    /// VBTableIndex - The nonzero index in the vbtable that
2465635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    /// this method's base has, or zero.
2466635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    const uint64_t VBTableIndex;
2467635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2468635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    /// VFTableIndex - The index in the vftable that this method has.
2469635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    const uint64_t VFTableIndex;
2470635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2471635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    /// Shadowed - Indicates if this vftable slot is shadowed by
2472635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    /// a slot for a covariant-return override. If so, it shouldn't be printed
2473635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    /// or used for vcalls in the most derived class.
2474635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    bool Shadowed;
2475635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2476176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    /// UsesExtraSlot - Indicates if this vftable slot was created because
2477176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    /// any of the overridden slots required a return adjusting thunk.
2478176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    bool UsesExtraSlot;
2479176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
2480176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex,
2481176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines               bool UsesExtraSlot = false)
2482e39c0f32fd9e6c6de68b50a1b20bca58759ba8d5Timur Iskhodzhanov        : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
2483176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          Shadowed(false), UsesExtraSlot(UsesExtraSlot) {}
2484635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2485176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    MethodInfo()
2486176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        : VBTableIndex(0), VFTableIndex(0), Shadowed(false),
2487176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          UsesExtraSlot(false) {}
2488635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  };
2489635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2490635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
2491635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2492635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// MethodInfoMap - The information for all methods in the vftable we're
2493635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// currently building.
2494635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  MethodInfoMapTy MethodInfoMap;
2495635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2496635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
2497635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2498635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// VTableThunks - The thunks by vftable index in the vftable currently being
2499635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// built.
2500635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  VTableThunksMapTy VTableThunks;
2501635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2502635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
2503635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
2504635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2505635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// Thunks - A map that contains all the thunks needed for all methods in the
2506635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// most derived class for which the vftable is currently being built.
2507635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  ThunksMapTy Thunks;
2508635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2509635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// AddThunk - Add a thunk for the given method.
2510635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  void AddThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk) {
2511635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    SmallVector<ThunkInfo, 1> &ThunksVector = Thunks[MD];
2512635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2513635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // Check if we have this thunk already.
2514635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
2515635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        ThunksVector.end())
2516635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      return;
2517635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2518635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    ThunksVector.push_back(Thunk);
2519635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2520635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2521635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// ComputeThisOffset - Returns the 'this' argument offset for the given
2522651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// method, relative to the beginning of the MostDerivedClass.
2523651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
2524635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
252558b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
252658b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov                                   CharUnits ThisOffset, ThisAdjustment &TA);
252758b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov
2528635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// AddMethod - Add a single virtual member function to the vftable
2529635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// components vector.
25302cb17a06befb61b1434aaa991652fea4338c95d7Timur Iskhodzhanov  void AddMethod(const CXXMethodDecl *MD, ThunkInfo TI) {
2531651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!TI.isEmpty()) {
2532651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      VTableThunks[Components.size()] = TI;
2533651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      AddThunk(MD, TI);
2534651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
2535635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
25362cb17a06befb61b1434aaa991652fea4338c95d7Timur Iskhodzhanov      assert(TI.Return.isEmpty() &&
2537635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov             "Destructor can't have return adjustment!");
2538635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Components.push_back(VTableComponent::MakeDeletingDtor(DD));
2539635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    } else {
2540635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Components.push_back(VTableComponent::MakeFunction(MD));
2541635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
2542635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2543635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2544635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// AddMethods - Add the methods of this base subobject and the relevant
2545635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// subbases to the vftable we're currently laying out.
2546635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  void AddMethods(BaseSubobject Base, unsigned BaseDepth,
2547635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                  const CXXRecordDecl *LastVBase,
2548635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                  BasesSetVectorTy &VisitedBases);
2549635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2550635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  void LayoutVFTable() {
2551176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // RTTI data goes before all other entries.
2552176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (HasRTTIComponent)
2553176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
2554635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2555635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    BasesSetVectorTy VisitedBases;
25566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    AddMethods(BaseSubobject(MostDerivedClass, CharUnits::Zero()), 0, nullptr,
2557635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov               VisitedBases);
2558176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    assert((HasRTTIComponent ? Components.size() - 1 : Components.size()) &&
2559176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines           "vftable can't be empty");
2560635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2561635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    assert(MethodVFTableLocations.empty());
2562635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(),
2563635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov         E = MethodInfoMap.end(); I != E; ++I) {
2564635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      const CXXMethodDecl *MD = I->first;
2565635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      const MethodInfo &MI = I->second;
2566635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      // Skip the methods that the MostDerivedClass didn't override
2567635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      // and the entries shadowed by return adjusting thunks.
2568635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (MD->getParent() != MostDerivedClass || MI.Shadowed)
2569635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        continue;
2570651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      MethodVFTableLocation Loc(MI.VBTableIndex, WhichVFPtr.getVBaseWithVPtr(),
2571651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                WhichVFPtr.NonVirtualOffset, MI.VFTableIndex);
2572635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2573635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        MethodVFTableLocations[GlobalDecl(DD, Dtor_Deleting)] = Loc;
2574635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      } else {
2575635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        MethodVFTableLocations[MD] = Loc;
2576635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      }
2577635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
2578635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2579635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2580635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovpublic:
25815f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov  VFTableBuilder(MicrosoftVTableContext &VTables,
2582651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                 const CXXRecordDecl *MostDerivedClass, const VPtrInfo *Which)
25835f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov      : VTables(VTables),
25845f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov        Context(MostDerivedClass->getASTContext()),
2585635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        MostDerivedClass(MostDerivedClass),
2586635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)),
2587651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        WhichVFPtr(*Which),
2588635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) {
2589c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Only include the RTTI component if we know that we will provide a
2590c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // definition of the vftable.
2591c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    HasRTTIComponent = Context.getLangOpts().RTTIData &&
25923ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                       !MostDerivedClass->hasAttr<DLLImportAttr>() &&
25933ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                       MostDerivedClass->getTemplateSpecializationKind() !=
25943ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                           TSK_ExplicitInstantiationDeclaration;
2595c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2596635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    LayoutVFTable();
2597635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2598635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    if (Context.getLangOpts().DumpVTableLayouts)
2599152eee9f81f1b4f00e1bce655903fc78cafb1342Reid Kleckner      dumpLayout(llvm::outs());
2600635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2601635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2602635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  uint64_t getNumThunks() const { return Thunks.size(); }
2603635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2604635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  ThunksMapTy::const_iterator thunks_begin() const { return Thunks.begin(); }
2605635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2606635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  ThunksMapTy::const_iterator thunks_end() const { return Thunks.end(); }
2607635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2608651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  method_locations_range vtable_locations() const {
2609651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return method_locations_range(MethodVFTableLocations.begin(),
2610651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                  MethodVFTableLocations.end());
2611635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2612635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2613635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  uint64_t getNumVTableComponents() const { return Components.size(); }
2614635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2615635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const VTableComponent *vtable_component_begin() const {
2616635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    return Components.begin();
2617635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2618635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2619635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const VTableComponent *vtable_component_end() const {
2620635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    return Components.end();
2621635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2622635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2623635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  VTableThunksMapTy::const_iterator vtable_thunks_begin() const {
2624635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    return VTableThunks.begin();
2625635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2626635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2627635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  VTableThunksMapTy::const_iterator vtable_thunks_end() const {
2628635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    return VTableThunks.end();
2629635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2630635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2631635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  void dumpLayout(raw_ostream &);
2632635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov};
2633635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2634635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov/// InitialOverriddenDefinitionCollector - Finds the set of least derived bases
2635635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov/// that define the given method.
2636635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovstruct InitialOverriddenDefinitionCollector {
2637635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  BasesSetVectorTy Bases;
2638635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  OverriddenMethodsSetTy VisitedOverriddenMethods;
2639635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2640635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  bool visit(const CXXMethodDecl *OverriddenMD) {
2641635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    if (OverriddenMD->size_overridden_methods() == 0)
2642635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Bases.insert(OverriddenMD->getParent());
2643635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // Don't recurse on this method if we've already collected it.
2644176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return VisitedOverriddenMethods.insert(OverriddenMD).second;
2645635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2646635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov};
2647635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
26483ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar} // end namespace
26493ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
2650635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovstatic bool BaseInSet(const CXXBaseSpecifier *Specifier,
2651635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                      CXXBasePath &Path, void *BasesSet) {
2652635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  BasesSetVectorTy *Bases = (BasesSetVectorTy *)BasesSet;
2653635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  return Bases->count(Specifier->getType()->getAsCXXRecordDecl());
2654635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
2655635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2656176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Let's study one class hierarchy as an example:
2657176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct A {
2658176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     virtual void f();
2659176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     int x;
2660176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   };
2661176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2662176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct B : virtual A {
2663176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     virtual void f();
2664176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   };
2665176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2666176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Record layouts:
2667176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct A:
2668176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   0 |   (A vftable pointer)
2669176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   4 |   int x
2670176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2671176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct B:
2672176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   0 |   (B vbtable pointer)
2673176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   4 |   struct A (virtual base)
2674176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   4 |     (A vftable pointer)
2675176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   8 |     int x
2676176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2677176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Let's assume we have a pointer to the A part of an object of dynamic type B:
2678176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   B b;
2679176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   A *a = (A*)&b;
2680176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   a->f();
2681176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2682176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// In this hierarchy, f() belongs to the vftable of A, so B::f() expects
2683176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// "this" parameter to point at the A subobject, which is B+4.
2684176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// In the B::f() prologue, it adjusts "this" back to B by subtracting 4,
26850e2c34f92f00628d48968dfea096d36381f494cbStephen Hines// performed as a *static* adjustment.
2686176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2687176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Interesting thing happens when we alter the relative placement of A and B
2688176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// subobjects in a class:
2689176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct C : virtual B { };
2690176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2691176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   C c;
2692176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   A *a = (A*)&c;
2693176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   a->f();
2694176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2695176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Respective record layout is:
2696176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   0 |   (C vbtable pointer)
2697176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   4 |   struct A (virtual base)
2698176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   4 |     (A vftable pointer)
2699176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   8 |     int x
2700176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  12 |   struct B (virtual base)
2701176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  12 |     (B vbtable pointer)
2702176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2703176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// The final overrider of f() in class C is still B::f(), so B+4 should be
2704176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// passed as "this" to that code.  However, "a" points at B-8, so the respective
2705176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// vftable entry should hold a thunk that adds 12 to the "this" argument before
2706176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// performing a tail call to B::f().
2707176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2708176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// With this example in mind, we can now calculate the 'this' argument offset
2709176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// for the given method, relative to the beginning of the MostDerivedClass.
2710635de28950ef84ae26308ff734e778bad1ddde92Timur IskhodzhanovCharUnits
2711651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesVFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
2712635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  InitialOverriddenDefinitionCollector Collector;
2713651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  visitAllOverriddenMethods(Overrider.Method, Collector);
2714651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
2715651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // If there are no overrides then 'this' is located
2716651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // in the base that defines the method.
2717651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (Collector.Bases.size() == 0)
2718651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return Overrider.Offset;
2719635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2720635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  CXXBasePaths Paths;
2721651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Overrider.Method->getParent()->lookupInBases(BaseInSet, &Collector.Bases,
2722651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                               Paths);
2723635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2724635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // This will hold the smallest this offset among overridees of MD.
2725635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // This implies that an offset of a non-virtual base will dominate an offset
2726635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // of a virtual base to potentially reduce the number of thunks required
2727635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // in the derived classes that inherit this method.
2728635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  CharUnits Ret;
2729635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  bool First = true;
2730635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
27316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  const ASTRecordLayout &OverriderRDLayout =
27326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      Context.getASTRecordLayout(Overrider.Method->getParent());
2733635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  for (CXXBasePaths::paths_iterator I = Paths.begin(), E = Paths.end();
2734635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov       I != E; ++I) {
2735635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    const CXXBasePath &Path = (*I);
2736651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    CharUnits ThisOffset = Overrider.Offset;
273758b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    CharUnits LastVBaseOffset;
2738635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2739635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // For each path from the overrider to the parents of the overridden methods,
2740635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // traverse the path, calculating the this offset in the most derived class.
2741635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    for (int J = 0, F = Path.size(); J != F; ++J) {
2742635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      const CXXBasePathElement &Element = Path[J];
2743635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      QualType CurTy = Element.Base->getType();
2744635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      const CXXRecordDecl *PrevRD = Element.Class,
2745635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                          *CurRD = CurTy->getAsCXXRecordDecl();
2746635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      const ASTRecordLayout &Layout = Context.getASTRecordLayout(PrevRD);
2747635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2748635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (Element.Base->isVirtual()) {
27496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // The interesting things begin when you have virtual inheritance.
27506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // The final overrider will use a static adjustment equal to the offset
27516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // of the vbase in the final overrider class.
27526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // For example, if the final overrider is in a vbase B of the most
27536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // derived class and it overrides a method of the B's own vbase A,
27546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // it uses A* as "this".  In its prologue, it can cast A* to B* with
27556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // a static offset.  This offset is used regardless of the actual
27566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // offset of A from B in the most derived class, requiring an
27576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // this-adjusting thunk in the vftable if A and B are laid out
27586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // differently in the most derived class.
27596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        LastVBaseOffset = ThisOffset =
27606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines            Overrider.Offset + OverriderRDLayout.getVBaseClassOffset(CurRD);
2761635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      } else {
2762635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        ThisOffset += Layout.getBaseClassOffset(CurRD);
2763635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      }
2764635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
2765635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2766651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (isa<CXXDestructorDecl>(Overrider.Method)) {
276758b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      if (LastVBaseOffset.isZero()) {
276858b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov        // If a "Base" class has at least one non-virtual base with a virtual
276958b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov        // destructor, the "Base" virtual destructor will take the address
277058b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov        // of the "Base" subobject as the "this" argument.
2771651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        ThisOffset = Overrider.Offset;
277258b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      } else {
277358b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov        // A virtual destructor of a virtual base takes the address of the
277458b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov        // virtual base subobject as the "this" argument.
2775651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        ThisOffset = LastVBaseOffset;
277658b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      }
277758b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    }
277882552742a1002cf1408d6f371efc9cc6a9f2d7ccTimur Iskhodzhanov
2779635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    if (Ret > ThisOffset || First) {
2780635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      First = false;
2781635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Ret = ThisOffset;
2782635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
2783635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2784635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2785635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  assert(!First && "Method not found in the given subobject?");
2786635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  return Ret;
2787635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
2788635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2789176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Things are getting even more complex when the "this" adjustment has to
2790176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// use a dynamic offset instead of a static one, or even two dynamic offsets.
2791176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// This is sometimes required when a virtual call happens in the middle of
2792176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// a non-most-derived class construction or destruction.
2793176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2794176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Let's take a look at the following example:
2795176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct A {
2796176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     virtual void f();
2797176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   };
2798176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2799176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   void foo(A *a) { a->f(); }  // Knows nothing about siblings of A.
2800176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2801176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct B : virtual A {
2802176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     virtual void f();
2803176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     B() {
2804176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//       foo(this);
2805176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     }
2806176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   };
2807176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2808176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct C : virtual B {
2809176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     virtual void f();
2810176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   };
2811176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2812176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Record layouts for these classes are:
2813176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct A
2814176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   0 |   (A vftable pointer)
2815176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2816176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct B
2817176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   0 |   (B vbtable pointer)
2818176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   4 |   (vtordisp for vbase A)
2819176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   8 |   struct A (virtual base)
2820176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   8 |     (A vftable pointer)
2821176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2822176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct C
2823176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   0 |   (C vbtable pointer)
2824176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   4 |   (vtordisp for vbase A)
2825176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   8 |   struct A (virtual base)  // A precedes B!
2826176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   8 |     (A vftable pointer)
2827176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  12 |   struct B (virtual base)
2828176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  12 |     (B vbtable pointer)
2829176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2830176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// When one creates an object of type C, the C constructor:
2831176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// - initializes all the vbptrs, then
2832176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// - calls the A subobject constructor
2833176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   (initializes A's vfptr with an address of A vftable), then
2834176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// - calls the B subobject constructor
2835176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   (initializes A's vfptr with an address of B vftable and vtordisp for A),
2836176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   that in turn calls foo(), then
2837176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// - initializes A's vfptr with an address of C vftable and zeroes out the
2838176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   vtordisp
2839176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   FIXME: if a structor knows it belongs to MDC, why doesn't it use a vftable
2840176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   without vtordisp thunks?
2841176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   FIXME: how are vtordisp handled in the presence of nooverride/final?
2842176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2843176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// When foo() is called, an object with a layout of class C has a vftable
2844176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// referencing B::f() that assumes a B layout, so the "this" adjustments are
2845176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// incorrect, unless an extra adjustment is done.  This adjustment is called
2846176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// "vtordisp adjustment".  Vtordisp basically holds the difference between the
2847176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// actual location of a vbase in the layout class and the location assumed by
2848176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// the vftable of the class being constructed/destructed.  Vtordisp is only
2849176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// needed if "this" escapes a
2850176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// structor (or we can't prove otherwise).
2851176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// [i.e. vtordisp is a dynamic adjustment for a static adjustment, which is an
2852176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// estimation of a dynamic adjustment]
2853176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2854176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// foo() gets a pointer to the A vbase and doesn't know anything about B or C,
2855176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// so it just passes that pointer as "this" in a virtual call.
2856176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// If there was no vtordisp, that would just dispatch to B::f().
2857176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// However, B::f() assumes B+8 is passed as "this",
2858176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// yet the pointer foo() passes along is B-4 (i.e. C+8).
2859176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// An extra adjustment is needed, so we emit a thunk into the B vftable.
2860176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// This vtordisp thunk subtracts the value of vtordisp
2861176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// from the "this" argument (-12) before making a tailcall to B::f().
2862176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2863176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Let's consider an even more complex example:
2864176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct D : virtual B, virtual C {
2865176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     D() {
2866176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//       foo(this);
2867176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     }
2868176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   };
2869176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2870176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct D
2871176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   0 |   (D vbtable pointer)
2872176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   4 |   (vtordisp for vbase A)
2873176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   8 |   struct A (virtual base)  // A precedes both B and C!
2874176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   8 |     (A vftable pointer)
2875176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  12 |   struct B (virtual base)  // B precedes C!
2876176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  12 |     (B vbtable pointer)
2877176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  16 |   struct C (virtual base)
2878176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  16 |     (C vbtable pointer)
2879176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2880176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// When D::D() calls foo(), we find ourselves in a thunk that should tailcall
2881176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// to C::f(), which assumes C+8 as its "this" parameter.  This time, foo()
2882176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// passes along A, which is C-8.  The A vtordisp holds
2883176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   "D.vbptr[index_of_A] - offset_of_A_in_D"
2884176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// and we statically know offset_of_A_in_D, so can get a pointer to D.
2885176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// When we know it, we can make an extra vbtable lookup to locate the C vbase
2886176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// and one extra static adjustment to calculate the expected value of C+8.
288758b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanovvoid VFTableBuilder::CalculateVtordispAdjustment(
288858b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    FinalOverriders::OverriderInfo Overrider, CharUnits ThisOffset,
288958b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    ThisAdjustment &TA) {
289058b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  const ASTRecordLayout::VBaseOffsetsMapTy &VBaseMap =
289158b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      MostDerivedClassLayout.getVBaseOffsetsMap();
289258b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2893651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      VBaseMap.find(WhichVFPtr.getVBaseWithVPtr());
289458b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  assert(VBaseMapEntry != VBaseMap.end());
289558b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov
28966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // If there's no vtordisp or the final overrider is defined in the same vbase
28976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // as the initial declaration, we don't need any vtordisp adjustment.
28986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (!VBaseMapEntry->second.hasVtorDisp() ||
28996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      Overrider.VirtualBase == WhichVFPtr.getVBaseWithVPtr())
290058b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    return;
290158b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov
29026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // OK, now we know we need to use a vtordisp thunk.
290358b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  // The implicit vtordisp field is located right before the vbase.
2904176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
290558b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  TA.Virtual.Microsoft.VtordispOffset =
2906176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      (OffsetOfVBaseWithVFPtr - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4;
290758b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov
29086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // A simple vtordisp thunk will suffice if the final overrider is defined
29096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // in either the most derived class or its non-virtual base.
29106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (Overrider.Method->getParent() == MostDerivedClass ||
29116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      !Overrider.VirtualBase)
291258b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    return;
291358b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov
291458b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  // Otherwise, we need to do use the dynamic offset of the final overrider
291558b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  // in order to get "this" adjustment right.
291658b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  TA.Virtual.Microsoft.VBPtrOffset =
2917176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      (OffsetOfVBaseWithVFPtr + WhichVFPtr.NonVirtualOffset -
291858b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov       MostDerivedClassLayout.getVBPtrOffset()).getQuantity();
291958b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  TA.Virtual.Microsoft.VBOffsetOffset =
292058b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      Context.getTypeSizeInChars(Context.IntTy).getQuantity() *
29216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      VTables.getVBTableIndex(MostDerivedClass, Overrider.VirtualBase);
292258b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov
292358b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  TA.NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
292458b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov}
292558b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov
2926cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanovstatic void GroupNewVirtualOverloads(
2927cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov    const CXXRecordDecl *RD,
2928cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov    SmallVector<const CXXMethodDecl *, 10> &VirtualMethods) {
2929cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  // Put the virtual methods into VirtualMethods in the proper order:
2930cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  // 1) Group overloads by declaration name. New groups are added to the
2931cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  //    vftable in the order of their first declarations in this class
2932651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  //    (including overrides and non-virtual methods).
2933cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  // 2) In each group, new overloads appear in the reverse order of declaration.
2934cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  typedef SmallVector<const CXXMethodDecl *, 1> MethodGroup;
2935cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  SmallVector<MethodGroup, 10> Groups;
2936cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
2937cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  VisitedGroupIndicesTy VisitedGroupIndices;
2938651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto *MD : RD->methods()) {
29390e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    MD = MD->getCanonicalDecl();
2940cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov    VisitedGroupIndicesTy::iterator J;
2941cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov    bool Inserted;
2942651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    std::tie(J, Inserted) = VisitedGroupIndices.insert(
2943cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov        std::make_pair(MD->getDeclName(), Groups.size()));
2944cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov    if (Inserted)
2945651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Groups.push_back(MethodGroup());
2946651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (MD->isVirtual())
2947cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov      Groups[J->second].push_back(MD);
2948cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  }
2949cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov
2950cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  for (unsigned I = 0, E = Groups.size(); I != E; ++I)
2951cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov    VirtualMethods.append(Groups[I].rbegin(), Groups[I].rend());
2952cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov}
2953cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov
2954651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool isDirectVBase(const CXXRecordDecl *Base, const CXXRecordDecl *RD) {
2955651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &B : RD->bases()) {
2956651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() == Base)
2957651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return true;
2958651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
2959651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return false;
2960651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
2961651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
2962635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovvoid VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
2963635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                                const CXXRecordDecl *LastVBase,
2964635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                                BasesSetVectorTy &VisitedBases) {
2965635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const CXXRecordDecl *RD = Base.getBase();
2966635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  if (!RD->isPolymorphic())
2967635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    return;
2968635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2969635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
2970635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2971635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // See if this class expands a vftable of the base we look at, which is either
2972635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // the one defined by the vfptr base path or the primary base of the current class.
29736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  const CXXRecordDecl *NextBase = nullptr, *NextLastVBase = LastVBase;
2974635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  CharUnits NextBaseOffset;
2975651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (BaseDepth < WhichVFPtr.PathToBaseWithVPtr.size()) {
2976651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    NextBase = WhichVFPtr.PathToBaseWithVPtr[BaseDepth];
2977651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (isDirectVBase(NextBase, RD)) {
2978635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      NextLastVBase = NextBase;
2979635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(NextBase);
2980635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    } else {
2981635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      NextBaseOffset =
2982635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          Base.getBaseOffset() + Layout.getBaseClassOffset(NextBase);
2983635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
2984635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  } else if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
2985635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    assert(!Layout.isPrimaryBaseVirtual() &&
2986635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov           "No primary virtual bases in this ABI");
2987635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    NextBase = PrimaryBase;
2988635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    NextBaseOffset = Base.getBaseOffset();
2989635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2990635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2991635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  if (NextBase) {
2992635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    AddMethods(BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
2993635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov               NextLastVBase, VisitedBases);
2994635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    if (!VisitedBases.insert(NextBase))
2995635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      llvm_unreachable("Found a duplicate primary base!");
2996635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2997635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2998cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  SmallVector<const CXXMethodDecl*, 10> VirtualMethods;
2999cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  // Put virtual methods in the proper order.
3000cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  GroupNewVirtualOverloads(RD, VirtualMethods);
3001cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov
3002635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // Now go through all virtual member functions and add them to the current
3003635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // vftable. This is done by
3004635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  //  - replacing overridden methods in their existing slots, as long as they
3005635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  //    don't require return adjustment; calculating This adjustment if needed.
3006635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  //  - adding new slots for methods of the current base not present in any
3007635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  //    sub-bases;
3008635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  //  - adding new slots for methods that require Return adjustment.
3009635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // We keep track of the methods visited in the sub-bases in MethodInfoMap.
3010cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  for (unsigned I = 0, E = VirtualMethods.size(); I != E; ++I) {
3011cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov    const CXXMethodDecl *MD = VirtualMethods[I];
3012635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3013176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    FinalOverriders::OverriderInfo FinalOverrider =
3014635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Overriders.getOverrider(MD, Base.getBaseOffset());
3015176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
3016651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXMethodDecl *OverriddenMD =
3017651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        FindNearestOverriddenMethod(MD, VisitedBases);
3018635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3019651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ThisAdjustment ThisAdjustmentOffset;
3020176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    bool ReturnAdjustingThunk = false, ForceReturnAdjustmentMangling = false;
3021176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
3022651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ThisAdjustmentOffset.NonVirtual =
3023651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        (ThisOffset - WhichVFPtr.FullOffsetInMDC).getQuantity();
3024176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if ((OverriddenMD || FinalOverriderMD != MD) &&
3025651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        WhichVFPtr.getVBaseWithVPtr())
3026176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
3027176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                  ThisAdjustmentOffset);
3028651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3029651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (OverriddenMD) {
3030651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // If MD overrides anything in this vftable, we need to update the entries.
3031635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      MethodInfoMapTy::iterator OverriddenMDIterator =
3032635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          MethodInfoMap.find(OverriddenMD);
3033635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3034635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      // If the overridden method went to a different vftable, skip it.
3035635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (OverriddenMDIterator == MethodInfoMap.end())
3036635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        continue;
3037635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3038635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
3039635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3040176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // Let's check if the overrider requires any return adjustments.
3041176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // We must create a new slot if the MD's return type is not trivially
3042176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // convertible to the OverriddenMD's one.
3043176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // Once a chain of method overrides adds a return adjusting vftable slot,
3044176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // all subsequent overrides will also use an extra method slot.
3045176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
3046176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                  Context, MD, OverriddenMD).isEmpty() ||
3047176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                             OverriddenMethodInfo.UsesExtraSlot;
3048176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
3049176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (!ReturnAdjustingThunk) {
3050635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        // No return adjustment needed - just replace the overridden method info
3051635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        // with the current info.
3052635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        MethodInfo MI(OverriddenMethodInfo.VBTableIndex,
3053635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                      OverriddenMethodInfo.VFTableIndex);
3054635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        MethodInfoMap.erase(OverriddenMDIterator);
3055635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3056635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        assert(!MethodInfoMap.count(MD) &&
3057635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov               "Should not have method info for this method yet!");
3058635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        MethodInfoMap.insert(std::make_pair(MD, MI));
3059635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        continue;
3060635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      }
3061651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3062651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // In case we need a return adjustment, we'll add a new slot for
3063651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // the overrider. Mark the overriden method as shadowed by the new slot.
3064651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      OverriddenMethodInfo.Shadowed = true;
3065651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3066651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // Force a special name mangling for a return-adjusting thunk
3067651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // unless the method is the final overrider without this adjustment.
3068176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      ForceReturnAdjustmentMangling =
3069176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          !(MD == FinalOverriderMD && ThisAdjustmentOffset.isEmpty());
3070651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    } else if (Base.getBaseOffset() != WhichVFPtr.FullOffsetInMDC ||
3071635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov               MD->size_overridden_methods()) {
3072635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      // Skip methods that don't belong to the vftable of the current class,
3073635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      // e.g. each method that wasn't seen in any of the visited sub-bases
3074635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      // but overrides multiple methods of other sub-bases.
3075635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      continue;
3076635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3077635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3078635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // If we got here, MD is a method not seen in any of the sub-bases or
3079635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // it requires return adjustment. Insert the method info for this method.
3080635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    unsigned VBIndex =
30815f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov        LastVBase ? VTables.getVBTableIndex(MostDerivedClass, LastVBase) : 0;
3082c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    MethodInfo MI(VBIndex,
3083176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                  HasRTTIComponent ? Components.size() - 1 : Components.size(),
3084176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                  ReturnAdjustingThunk);
3085635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3086635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    assert(!MethodInfoMap.count(MD) &&
3087635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov           "Should not have method info for this method yet!");
3088635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    MethodInfoMap.insert(std::make_pair(MD, MI));
3089635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3090635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // Check if this overrider needs a return adjustment.
3091635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // We don't want to do this for pure virtual member functions.
3092635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    BaseOffset ReturnAdjustmentOffset;
3093635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    ReturnAdjustment ReturnAdjustment;
3094176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (!FinalOverriderMD->isPure()) {
3095635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      ReturnAdjustmentOffset =
3096176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          ComputeReturnAdjustmentBaseOffset(Context, FinalOverriderMD, MD);
3097635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3098635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    if (!ReturnAdjustmentOffset.isEmpty()) {
3099176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      ForceReturnAdjustmentMangling = true;
3100635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      ReturnAdjustment.NonVirtual =
3101635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          ReturnAdjustmentOffset.NonVirtualOffset.getQuantity();
3102635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (ReturnAdjustmentOffset.VirtualBase) {
3103c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov        const ASTRecordLayout &DerivedLayout =
3104c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov            Context.getASTRecordLayout(ReturnAdjustmentOffset.DerivedClass);
3105c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov        ReturnAdjustment.Virtual.Microsoft.VBPtrOffset =
3106c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov            DerivedLayout.getVBPtrOffset().getQuantity();
3107c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov        ReturnAdjustment.Virtual.Microsoft.VBIndex =
31085f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov            VTables.getVBTableIndex(ReturnAdjustmentOffset.DerivedClass,
31095f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov                                    ReturnAdjustmentOffset.VirtualBase);
3110635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      }
3111635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3112635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3113176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    AddMethod(FinalOverriderMD,
3114176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines              ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment,
3115176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                        ForceReturnAdjustmentMangling ? MD : nullptr));
3116635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
3117635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3118635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3119651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void PrintBasePath(const VPtrInfo::BasePath &Path, raw_ostream &Out) {
3120651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (VPtrInfo::BasePath::const_reverse_iterator I = Path.rbegin(),
3121635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov       E = Path.rend(); I != E; ++I) {
3122651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Out << "'";
3123651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    (*I)->printQualifiedName(Out);
3124651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Out << "' in ";
3125635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
3126635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3127635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3128c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanovstatic void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out,
3129c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov                                         bool ContinueFirstLine) {
3130c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov  const ReturnAdjustment &R = TI.Return;
3131c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov  bool Multiline = false;
3132651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const char *LinePrefix = "\n       ";
3133651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (!R.isEmpty() || TI.Method) {
3134c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov    if (!ContinueFirstLine)
3135c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov      Out << LinePrefix;
3136651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Out << "[return adjustment (to type '"
3137651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        << TI.Method->getReturnType().getCanonicalType().getAsString()
3138651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        << "'): ";
3139c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov    if (R.Virtual.Microsoft.VBPtrOffset)
3140c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov      Out << "vbptr at offset " << R.Virtual.Microsoft.VBPtrOffset << ", ";
3141c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov    if (R.Virtual.Microsoft.VBIndex)
3142c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov      Out << "vbase #" << R.Virtual.Microsoft.VBIndex << ", ";
3143c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov    Out << R.NonVirtual << " non-virtual]";
3144c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov    Multiline = true;
3145c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov  }
3146c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov
3147c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov  const ThisAdjustment &T = TI.This;
3148c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov  if (!T.isEmpty()) {
3149c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov    if (Multiline || !ContinueFirstLine)
3150c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov      Out << LinePrefix;
3151c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov    Out << "[this adjustment: ";
315258b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    if (!TI.This.Virtual.isEmpty()) {
315358b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      assert(T.Virtual.Microsoft.VtordispOffset < 0);
315458b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      Out << "vtordisp at " << T.Virtual.Microsoft.VtordispOffset << ", ";
315558b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      if (T.Virtual.Microsoft.VBPtrOffset) {
315658b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov        Out << "vbptr at " << T.Virtual.Microsoft.VBPtrOffset
3157651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            << " to the left,";
315858b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov        assert(T.Virtual.Microsoft.VBOffsetOffset > 0);
315958b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov        Out << LinePrefix << " vboffset at "
316058b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov            << T.Virtual.Microsoft.VBOffsetOffset << " in the vbtable, ";
316158b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      }
316258b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    }
3163c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov    Out << T.NonVirtual << " non-virtual]";
3164c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov  }
3165c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov}
3166c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov
3167635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovvoid VFTableBuilder::dumpLayout(raw_ostream &Out) {
3168635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  Out << "VFTable for ";
3169651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  PrintBasePath(WhichVFPtr.PathToBaseWithVPtr, Out);
3170651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Out << "'";
3171651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  MostDerivedClass->printQualifiedName(Out);
3172651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Out << "' (" << Components.size()
3173651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      << (Components.size() == 1 ? " entry" : " entries") << ").\n";
3174635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3175635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  for (unsigned I = 0, E = Components.size(); I != E; ++I) {
3176635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    Out << llvm::format("%4d | ", I);
3177635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3178635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    const VTableComponent &Component = Components[I];
3179635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3180635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // Dump the component.
3181635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    switch (Component.getKind()) {
3182635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    case VTableComponent::CK_RTTI:
3183651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Component.getRTTIDecl()->printQualifiedName(Out);
3184651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Out << " RTTI";
3185635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      break;
3186635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3187635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    case VTableComponent::CK_FunctionPointer: {
3188635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      const CXXMethodDecl *MD = Component.getFunctionDecl();
3189635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3190651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // FIXME: Figure out how to print the real thunk type, since they can
3191651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // differ in the return type.
3192635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      std::string Str = PredefinedExpr::ComputeName(
3193635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          PredefinedExpr::PrettyFunctionNoVirtual, MD);
3194635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Out << Str;
3195635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (MD->isPure())
3196635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Out << " [pure]";
3197635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3198176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (MD->isDeleted())
3199635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Out << " [deleted]";
3200635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3201635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      ThunkInfo Thunk = VTableThunks.lookup(I);
3202c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov      if (!Thunk.isEmpty())
3203c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov        dumpMicrosoftThunkAdjustment(Thunk, Out, /*ContinueFirstLine=*/false);
3204635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3205635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      break;
3206635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3207635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3208635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    case VTableComponent::CK_DeletingDtorPointer: {
3209635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      const CXXDestructorDecl *DD = Component.getDestructorDecl();
3210635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3211651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      DD->printQualifiedName(Out);
3212635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Out << "() [scalar deleting]";
3213635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3214635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (DD->isPure())
3215635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Out << " [pure]";
3216635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3217635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      ThunkInfo Thunk = VTableThunks.lookup(I);
3218635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (!Thunk.isEmpty()) {
3219635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        assert(Thunk.Return.isEmpty() &&
3220635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov               "No return adjustment needed for destructors!");
3221c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov        dumpMicrosoftThunkAdjustment(Thunk, Out, /*ContinueFirstLine=*/false);
3222635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      }
3223635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3224635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      break;
3225635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3226635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3227635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    default:
3228635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      DiagnosticsEngine &Diags = Context.getDiagnostics();
3229635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      unsigned DiagID = Diags.getCustomDiagID(
3230635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          DiagnosticsEngine::Error,
3231635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          "Unexpected vftable component type %0 for component number %1");
3232635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Diags.Report(MostDerivedClass->getLocation(), DiagID)
3233635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          << I << Component.getKind();
3234635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3235635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3236635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    Out << '\n';
3237635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
3238635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3239635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  Out << '\n';
3240635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3241635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  if (!Thunks.empty()) {
3242635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // We store the method names in a map to get a stable order.
3243635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3244635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3245635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    for (ThunksMapTy::const_iterator I = Thunks.begin(), E = Thunks.end();
3246635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov         I != E; ++I) {
3247635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      const CXXMethodDecl *MD = I->first;
3248635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      std::string MethodName = PredefinedExpr::ComputeName(
3249635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          PredefinedExpr::PrettyFunctionNoVirtual, MD);
3250635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3251635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3252635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3253635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3254635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    for (std::map<std::string, const CXXMethodDecl *>::const_iterator
3255635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov             I = MethodNamesAndDecls.begin(),
3256635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov             E = MethodNamesAndDecls.end();
3257635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov         I != E; ++I) {
3258635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      const std::string &MethodName = I->first;
3259635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      const CXXMethodDecl *MD = I->second;
3260635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3261635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      ThunkInfoVectorTy ThunksVector = Thunks[MD];
32622cb17a06befb61b1434aaa991652fea4338c95d7Timur Iskhodzhanov      std::stable_sort(ThunksVector.begin(), ThunksVector.end(),
3263651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                       [](const ThunkInfo &LHS, const ThunkInfo &RHS) {
3264651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        // Keep different thunks with the same adjustments in the order they
3265651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        // were put into the vector.
3266651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return);
3267651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      });
3268635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3269635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size();
3270635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n";
3271635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3272635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      for (unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
3273635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        const ThunkInfo &Thunk = ThunksVector[I];
3274635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3275635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Out << llvm::format("%4d | ", I);
3276c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov        dumpMicrosoftThunkAdjustment(Thunk, Out, /*ContinueFirstLine=*/true);
3277635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Out << '\n';
3278635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      }
3279635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3280635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Out << '\n';
3281635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3282635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
3283651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3284651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Out.flush();
3285635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3286635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3287651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool setsIntersect(const llvm::SmallPtrSet<const CXXRecordDecl *, 4> &A,
3288176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                          ArrayRef<const CXXRecordDecl *> B) {
3289c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (ArrayRef<const CXXRecordDecl *>::iterator I = B.begin(), E = B.end();
3290651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines       I != E; ++I) {
3291651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (A.count(*I))
3292651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return true;
3293635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
3294651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return false;
3295651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
3296635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3297651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool rebucketPaths(VPtrInfoVector &Paths);
3298635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3299651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// Produces MSVC-compatible vbtable data.  The symbols produced by this
3300651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// algorithm match those produced by MSVC 2012 and newer, which is different
3301651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// from MSVC 2010.
3302651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines///
3303651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// MSVC 2012 appears to minimize the vbtable names using the following
3304651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// algorithm.  First, walk the class hierarchy in the usual order, depth first,
3305651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// left to right, to find all of the subobjects which contain a vbptr field.
3306651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// Visiting each class node yields a list of inheritance paths to vbptrs.  Each
3307651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// record with a vbptr creates an initially empty path.
3308651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines///
3309651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// To combine paths from child nodes, the paths are compared to check for
3310651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// ambiguity.  Paths are "ambiguous" if multiple paths have the same set of
3311651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// components in the same order.  Each group of ambiguous paths is extended by
3312651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// appending the class of the base from which it came.  If the current class
3313651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// node produced an ambiguous path, its path is extended with the current class.
3314651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// After extending paths, MSVC again checks for ambiguity, and extends any
3315651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// ambiguous path which wasn't already extended.  Because each node yields an
3316651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// unambiguous set of paths, MSVC doesn't need to extend any path more than once
3317651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// to produce an unambiguous set of paths.
3318651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines///
3319651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// TODO: Presumably vftables use the same algorithm.
3320651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid MicrosoftVTableContext::computeVTablePaths(bool ForVBTables,
3321651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                                const CXXRecordDecl *RD,
3322651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                                VPtrInfoVector &Paths) {
3323651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  assert(Paths.empty());
3324651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3325635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3326651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Base case: this subobject has its own vptr.
3327651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (ForVBTables ? Layout.hasOwnVBPtr() : Layout.hasOwnVFPtr())
3328651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Paths.push_back(new VPtrInfo(RD));
3329635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3330651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Recursive case: get all the vbtables from our bases and remove anything
3331651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // that shares a virtual base.
3332651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
3333651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &B : RD->bases()) {
3334651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
3335651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (B.isVirtual() && VBasesSeen.count(Base))
3336651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      continue;
3337635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3338651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!Base->isDynamicClass())
3339651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      continue;
3340651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3341651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const VPtrInfoVector &BasePaths =
3342651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        ForVBTables ? enumerateVBTables(Base) : getVFPtrOffsets(Base);
3343a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov
33446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    for (VPtrInfo *BaseInfo : BasePaths) {
3345651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // Don't include the path if it goes through a virtual base that we've
3346651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // already included.
3347651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (setsIntersect(VBasesSeen, BaseInfo->ContainingVBases))
3348651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        continue;
3349a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov
3350651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // Copy the path and adjust it as necessary.
3351651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      VPtrInfo *P = new VPtrInfo(*BaseInfo);
3352651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3353651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // We mangle Base into the path if the path would've been ambiguous and it
3354651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // wasn't already extended with Base.
3355651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (P->MangledPath.empty() || P->MangledPath.back() != Base)
3356651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        P->NextBaseToMangle = Base;
3357651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
33586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      // Keep track of which vtable the derived class is going to extend with
33596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      // new methods or bases.  We append to either the vftable of our primary
33606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      // base, or the first non-virtual base that has a vbtable.
33616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (P->ReusingBase == Base &&
33626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          Base == (ForVBTables ? Layout.getBaseSharingVBPtr()
3363651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                               : Layout.getPrimaryBase()))
3364651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        P->ReusingBase = RD;
33656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
33666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      // Keep track of the full adjustment from the MDC to this vtable.  The
33676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      // adjustment is captured by an optional vbase and a non-virtual offset.
3368651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (B.isVirtual())
3369651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        P->ContainingVBases.push_back(Base);
3370651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      else if (P->ContainingVBases.empty())
3371651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        P->NonVirtualOffset += Layout.getBaseClassOffset(Base);
3372651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3373651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // Update the full offset in the MDC.
3374651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      P->FullOffsetInMDC = P->NonVirtualOffset;
3375651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (const CXXRecordDecl *VB = P->getVBaseWithVPtr())
3376651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        P->FullOffsetInMDC += Layout.getVBaseClassOffset(VB);
3377651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3378651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Paths.push_back(P);
3379a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov    }
3380651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3381651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (B.isVirtual())
3382651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      VBasesSeen.insert(Base);
3383651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3384651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // After visiting any direct base, we've transitively visited all of its
3385651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // morally virtual bases.
3386651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (const auto &VB : Base->vbases())
3387651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3388a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov  }
3389a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov
3390651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Sort the paths into buckets, and if any of them are ambiguous, extend all
3391651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // paths in ambiguous buckets.
3392651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool Changed = true;
3393651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  while (Changed)
3394651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Changed = rebucketPaths(Paths);
3395651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
3396a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov
3397651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool extendPath(VPtrInfo *P) {
3398651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (P->NextBaseToMangle) {
3399651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    P->MangledPath.push_back(P->NextBaseToMangle);
34006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    P->NextBaseToMangle = nullptr;// Prevent the path from being extended twice.
3401651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return true;
3402a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov  }
3403651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return false;
3404a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov}
3405a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov
3406651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool rebucketPaths(VPtrInfoVector &Paths) {
3407651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // What we're essentially doing here is bucketing together ambiguous paths.
3408651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Any bucket with more than one path in it gets extended by NextBase, which
3409651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // is usually the direct base of the inherited the vbptr.  This code uses a
3410651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // sorted vector to implement a multiset to form the buckets.  Note that the
3411651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // ordering is based on pointers, but it doesn't change our output order.  The
3412651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // current algorithm is designed to match MSVC 2012's names.
3413651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  VPtrInfoVector PathsSorted(Paths);
3414651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::sort(PathsSorted.begin(), PathsSorted.end(),
3415651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            [](const VPtrInfo *LHS, const VPtrInfo *RHS) {
3416651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return LHS->MangledPath < RHS->MangledPath;
3417651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  });
3418651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool Changed = false;
3419651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (size_t I = 0, E = PathsSorted.size(); I != E;) {
3420651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // Scan forward to find the end of the bucket.
3421651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    size_t BucketStart = I;
3422651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    do {
3423651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      ++I;
3424651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    } while (I != E && PathsSorted[BucketStart]->MangledPath ==
3425651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                           PathsSorted[I]->MangledPath);
3426651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3427651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // If this bucket has multiple paths, extend them all.
3428651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (I - BucketStart > 1) {
3429651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      for (size_t II = BucketStart; II != I; ++II)
3430651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        Changed |= extendPath(PathsSorted[II]);
3431651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      assert(Changed && "no paths were extended to fix ambiguity");
3432651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
3433a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov  }
3434651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return Changed;
3435651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
3436651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3437651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesMicrosoftVTableContext::~MicrosoftVTableContext() {
34386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (auto &P : VFPtrLocations)
34396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    llvm::DeleteContainerPointers(*P.second);
3440651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::DeleteContainerSeconds(VFPtrLocations);
3441651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::DeleteContainerSeconds(VFTableLayouts);
3442651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::DeleteContainerSeconds(VBaseInfo);
3443635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3444635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3445176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstatic bool
3446176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesfindPathForVPtr(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout,
3447176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                const CXXRecordDecl *RD, CharUnits Offset,
3448176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                llvm::SmallPtrSetImpl<const CXXRecordDecl *> &VBasesSeen,
3449176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                VPtrInfo::BasePath &FullPath, VPtrInfo *Info) {
3450176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (RD == Info->BaseWithVPtr && Offset == Info->FullOffsetInMDC) {
3451176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    Info->PathToBaseWithVPtr = FullPath;
3452176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return true;
3453176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
3454176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
3455176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3456176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
3457176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // Recurse with non-virtual bases first.
3458176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // FIXME: Does this need to be in layout order? Virtual bases will be in base
3459176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // specifier order, which isn't necessarily layout order.
3460176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  SmallVector<CXXBaseSpecifier, 4> Bases(RD->bases_begin(), RD->bases_end());
3461176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::stable_partition(Bases.begin(), Bases.end(),
3462176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                        [](CXXBaseSpecifier bs) { return !bs.isVirtual(); });
3463176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
3464176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  for (const auto &B : Bases) {
3465176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
3466176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    CharUnits NewOffset;
3467176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (!B.isVirtual())
3468176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      NewOffset = Offset + Layout.getBaseClassOffset(Base);
3469176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    else {
3470176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (!VBasesSeen.insert(Base).second)
3471176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return false;
3472176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      NewOffset = MostDerivedLayout.getVBaseClassOffset(Base);
3473176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
3474176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    FullPath.push_back(Base);
3475176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (findPathForVPtr(Context, MostDerivedLayout, Base, NewOffset, VBasesSeen,
3476176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                        FullPath, Info))
3477176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return true;
3478176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    FullPath.pop_back();
3479176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
3480176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return false;
3481176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
3482176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
3483176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstatic void computeFullPathsForVFTables(ASTContext &Context,
3484176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                        const CXXRecordDecl *RD,
3485176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                        VPtrInfoVector &Paths) {
3486176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
3487176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  const ASTRecordLayout &MostDerivedLayout = Context.getASTRecordLayout(RD);
3488176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  VPtrInfo::BasePath FullPath;
3489176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  for (VPtrInfo *Info : Paths) {
3490176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    findPathForVPtr(Context, MostDerivedLayout, RD, CharUnits::Zero(),
3491176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                    VBasesSeen, FullPath, Info);
3492176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    VBasesSeen.clear();
3493176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    FullPath.clear();
3494176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
3495176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
3496176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
34975f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanovvoid MicrosoftVTableContext::computeVTableRelatedInformation(
3498635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    const CXXRecordDecl *RD) {
3499635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  assert(RD->isDynamicClass());
3500635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3501635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // Check if we've computed this information before.
3502635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  if (VFPtrLocations.count(RD))
3503635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    return;
3504635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3505635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const VTableLayout::AddressPointsMapTy EmptyAddressPointsMap;
3506635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3507651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  VPtrInfoVector *VFPtrs = new VPtrInfoVector();
3508651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  computeVTablePaths(/*ForVBTables=*/false, RD, *VFPtrs);
3509176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  computeFullPathsForVFTables(Context, RD, *VFPtrs);
3510651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  VFPtrLocations[RD] = VFPtrs;
3511635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3512635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  MethodVFTableLocationsTy NewMethodLocations;
3513651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (VPtrInfoVector::iterator I = VFPtrs->begin(), E = VFPtrs->end();
3514635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov       I != E; ++I) {
35155f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov    VFTableBuilder Builder(*this, RD, *I);
3516635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3517651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    VFTableIdTy id(RD, (*I)->FullOffsetInMDC);
3518635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    assert(VFTableLayouts.count(id) == 0);
3519635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks(
3520635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
3521635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    VFTableLayouts[id] = new VTableLayout(
3522635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Builder.getNumVTableComponents(), Builder.vtable_component_begin(),
3523635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        VTableThunks.size(), VTableThunks.data(), EmptyAddressPointsMap, true);
3524635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
3525651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3526651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (const auto &Loc : Builder.vtable_locations()) {
3527651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      GlobalDecl GD = Loc.first;
3528651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      MethodVFTableLocation NewLoc = Loc.second;
3529651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      auto M = NewMethodLocations.find(GD);
3530651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (M == NewMethodLocations.end() || NewLoc < M->second)
3531651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        NewMethodLocations[GD] = NewLoc;
3532651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
3533635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
3534635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3535635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  MethodVFTableLocations.insert(NewMethodLocations.begin(),
3536635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                                NewMethodLocations.end());
3537635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  if (Context.getLangOpts().DumpVTableLayouts)
3538152eee9f81f1b4f00e1bce655903fc78cafb1342Reid Kleckner    dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3539635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3540635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
35415f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanovvoid MicrosoftVTableContext::dumpMethodLocations(
3542635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    const CXXRecordDecl *RD, const MethodVFTableLocationsTy &NewMethods,
3543635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    raw_ostream &Out) {
3544635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // Compute the vtable indices for all the member functions.
3545635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // Store them in a map keyed by the location so we'll get a sorted table.
3546635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  std::map<MethodVFTableLocation, std::string> IndicesMap;
3547635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  bool HasNonzeroOffset = false;
3548635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3549635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  for (MethodVFTableLocationsTy::const_iterator I = NewMethods.begin(),
3550635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov       E = NewMethods.end(); I != E; ++I) {
3551635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    const CXXMethodDecl *MD = cast<const CXXMethodDecl>(I->first.getDecl());
3552635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    assert(MD->isVirtual());
3553635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3554635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    std::string MethodName = PredefinedExpr::ComputeName(
3555635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        PredefinedExpr::PrettyFunctionNoVirtual, MD);
3556635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3557635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    if (isa<CXXDestructorDecl>(MD)) {
3558635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      IndicesMap[I->second] = MethodName + " [scalar deleting]";
3559635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    } else {
3560635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      IndicesMap[I->second] = MethodName;
3561635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3562635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
356340aa366f994f7b2c103e94f903a34226b4b8f06bTimur Iskhodzhanov    if (!I->second.VFPtrOffset.isZero() || I->second.VBTableIndex != 0)
3564635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      HasNonzeroOffset = true;
3565635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
3566635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3567635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // Print the vtable indices for all the member functions.
3568635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  if (!IndicesMap.empty()) {
3569635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    Out << "VFTable indices for ";
3570651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Out << "'";
3571651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    RD->printQualifiedName(Out);
3572651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Out << "' (" << IndicesMap.size()
3573651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        << (IndicesMap.size() == 1 ? " entry" : " entries") << ").\n";
3574635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3575635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    CharUnits LastVFPtrOffset = CharUnits::fromQuantity(-1);
3576635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    uint64_t LastVBIndex = 0;
3577635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    for (std::map<MethodVFTableLocation, std::string>::const_iterator
3578635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov             I = IndicesMap.begin(),
3579635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov             E = IndicesMap.end();
3580635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov         I != E; ++I) {
358140aa366f994f7b2c103e94f903a34226b4b8f06bTimur Iskhodzhanov      CharUnits VFPtrOffset = I->first.VFPtrOffset;
3582635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      uint64_t VBIndex = I->first.VBTableIndex;
3583635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (HasNonzeroOffset &&
3584635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3585635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3586635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Out << " -- accessible via ";
3587635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        if (VBIndex)
3588635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          Out << "vbtable index " << VBIndex << ", ";
3589635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Out << "vfptr at offset " << VFPtrOffset.getQuantity() << " --\n";
3590635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        LastVFPtrOffset = VFPtrOffset;
3591635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        LastVBIndex = VBIndex;
3592635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      }
3593635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3594635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      uint64_t VTableIndex = I->first.Index;
3595635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      const std::string &MethodName = I->second;
3596635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Out << llvm::format("%4" PRIu64 " | ", VTableIndex) << MethodName << '\n';
3597635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3598635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    Out << '\n';
3599635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
3600651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3601651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Out.flush();
3602635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3603635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3604651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesconst VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation(
36055f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov    const CXXRecordDecl *RD) {
3606651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  VirtualBaseInfo *VBI;
36075f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov
3608651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  {
3609651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // Get or create a VBI for RD.  Don't hold a reference to the DenseMap cell,
3610651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // as it may be modified and rehashed under us.
3611651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    VirtualBaseInfo *&Entry = VBaseInfo[RD];
3612651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (Entry)
3613651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return Entry;
3614651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Entry = VBI = new VirtualBaseInfo();
3615651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
3616651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3617651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  computeVTablePaths(/*ForVBTables=*/true, RD, VBI->VBPtrPaths);
36185f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov
36196acb04f755cfc73d05772457d70aeb5adfaf6d8fTimur Iskhodzhanov  // First, see if the Derived class shared the vbptr with a non-virtual base.
3620651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
36216acb04f755cfc73d05772457d70aeb5adfaf6d8fTimur Iskhodzhanov  if (const CXXRecordDecl *VBPtrBase = Layout.getBaseSharingVBPtr()) {
3622651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // If the Derived class shares the vbptr with a non-virtual base, the shared
3623651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // virtual bases come first so that the layout is the same.
3624651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const VirtualBaseInfo *BaseInfo =
3625651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        computeVBTableRelatedInformation(VBPtrBase);
3626651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    VBI->VBTableIndices.insert(BaseInfo->VBTableIndices.begin(),
3627651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                               BaseInfo->VBTableIndices.end());
36285f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov  }
36295f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov
36305f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov  // New vbases are added to the end of the vbtable.
36315f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov  // Skip the self entry and vbases visited in the non-virtual base, if any.
3632651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  unsigned VBTableIndex = 1 + VBI->VBTableIndices.size();
3633651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &VB : RD->vbases()) {
3634651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3635651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!VBI->VBTableIndices.count(CurVBase))
3636651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      VBI->VBTableIndices[CurVBase] = VBTableIndex++;
36375f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov  }
3638651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3639651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return VBI;
3640651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
3641651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3642651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesunsigned MicrosoftVTableContext::getVBTableIndex(const CXXRecordDecl *Derived,
3643651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                                 const CXXRecordDecl *VBase) {
3644651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const VirtualBaseInfo *VBInfo = computeVBTableRelatedInformation(Derived);
3645651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  assert(VBInfo->VBTableIndices.count(VBase));
3646651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return VBInfo->VBTableIndices.find(VBase)->second;
3647651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
3648651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3649651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesconst VPtrInfoVector &
3650651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesMicrosoftVTableContext::enumerateVBTables(const CXXRecordDecl *RD) {
3651651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return computeVBTableRelatedInformation(RD)->VBPtrPaths;
36525f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov}
36535f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov
3654651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesconst VPtrInfoVector &
36555f0db587078b5af32fc9ac41fe4276b80918fd8dTimur IskhodzhanovMicrosoftVTableContext::getVFPtrOffsets(const CXXRecordDecl *RD) {
3656635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  computeVTableRelatedInformation(RD);
3657635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3658635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  assert(VFPtrLocations.count(RD) && "Couldn't find vfptr locations");
3659651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return *VFPtrLocations[RD];
3660635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3661635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3662635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovconst VTableLayout &
36635f0db587078b5af32fc9ac41fe4276b80918fd8dTimur IskhodzhanovMicrosoftVTableContext::getVFTableLayout(const CXXRecordDecl *RD,
36645f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov                                         CharUnits VFPtrOffset) {
3665635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  computeVTableRelatedInformation(RD);
3666635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3667635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  VFTableIdTy id(RD, VFPtrOffset);
3668635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  assert(VFTableLayouts.count(id) && "Couldn't find a VFTable at this offset");
3669635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  return *VFTableLayouts[id];
3670635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3671635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
36725f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanovconst MicrosoftVTableContext::MethodVFTableLocation &
36735f0db587078b5af32fc9ac41fe4276b80918fd8dTimur IskhodzhanovMicrosoftVTableContext::getMethodVFTableLocation(GlobalDecl GD) {
3674635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  assert(cast<CXXMethodDecl>(GD.getDecl())->isVirtual() &&
3675635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov         "Only use this method for virtual methods or dtors");
3676635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  if (isa<CXXDestructorDecl>(GD.getDecl()))
3677635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    assert(GD.getDtorType() == Dtor_Deleting);
3678635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3679635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  MethodVFTableLocationsTy::iterator I = MethodVFTableLocations.find(GD);
3680635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  if (I != MethodVFTableLocations.end())
3681635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    return I->second;
3682635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3683635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
3684635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3685635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  computeVTableRelatedInformation(RD);
3686635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3687635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  I = MethodVFTableLocations.find(GD);
3688635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  assert(I != MethodVFTableLocations.end() && "Did not find index!");
3689635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  return I->second;
3690635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3691