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"
16b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar#include "clang/AST/ASTDiagnostic.h"
1724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include "clang/AST/CXXInheritance.h"
1824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include "clang/AST/RecordLayout.h"
1924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include "clang/Basic/TargetInfo.h"
20b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar#include "llvm/ADT/SetOperations.h"
21651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/ADT/SmallPtrSet.h"
2224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include "llvm/Support/Format.h"
23a93d0f280693b8418bc88cf7a8c93325f7fcf4c6Benjamin Kramer#include "llvm/Support/raw_ostream.h"
2424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include <algorithm>
2524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include <cstdio>
2624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourneusing namespace clang;
2824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#define DUMP_OVERRIDERS 0
3024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
3124018467ddb13857b764182f7753764d2f32f87dPeter Collingbournenamespace {
3224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
3324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// BaseOffset - Represents an offset from a derived class to a direct or
3424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// indirect base class.
3524018467ddb13857b764182f7753764d2f32f87dPeter Collingbournestruct BaseOffset {
3624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// DerivedClass - The derived class.
3724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *DerivedClass;
3824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
3924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// VirtualBase - If the path from the derived class to the base class
402fca8027fdfa09e99d1066f4694ca437b43ab6d4Timur Iskhodzhanov  /// involves virtual base classes, this holds the declaration of the last
412fca8027fdfa09e99d1066f4694ca437b43ab6d4Timur Iskhodzhanov  /// virtual base in this path (i.e. closest to the base class).
4224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *VirtualBase;
4324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
4424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// NonVirtualOffset - The offset from the derived class to the base class.
4524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// (Or the offset from the virtual base class to the base class, if the
4624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// path from the derived class to the base class involves a virtual base
4724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// class.
4824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  CharUnits NonVirtualOffset;
496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  BaseOffset() : DerivedClass(nullptr), VirtualBase(nullptr),
516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                 NonVirtualOffset(CharUnits::Zero()) { }
5224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  BaseOffset(const CXXRecordDecl *DerivedClass,
5324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             const CXXRecordDecl *VirtualBase, CharUnits NonVirtualOffset)
5424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    : DerivedClass(DerivedClass), VirtualBase(VirtualBase),
5524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    NonVirtualOffset(NonVirtualOffset) { }
5624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
5724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  bool isEmpty() const { return NonVirtualOffset.isZero() && !VirtualBase; }
5824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne};
5924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
6024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// FinalOverriders - Contains the final overrider member functions for all
6124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// member functions in the base subobjects of a class.
6224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourneclass FinalOverriders {
6324018467ddb13857b764182f7753764d2f32f87dPeter Collingbournepublic:
6424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// OverriderInfo - Information about a final overrider.
6524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  struct OverriderInfo {
6624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    /// Method - The method decl of the overrider.
6724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXMethodDecl *Method;
6824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
69176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    /// VirtualBase - The virtual base class subobject of this overrider.
706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    /// Note that this records the closest derived virtual base class subobject.
716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const CXXRecordDecl *VirtualBase;
726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
73635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    /// Offset - the base offset of the overrider's parent in the layout class.
7424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits Offset;
756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    OverriderInfo() : Method(nullptr), VirtualBase(nullptr),
776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                      Offset(CharUnits::Zero()) { }
7824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  };
7924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
8024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourneprivate:
8124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MostDerivedClass - The most derived class for which the final overriders
8224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// are stored.
8324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *MostDerivedClass;
8424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
8524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MostDerivedClassOffset - If we're building final overriders for a
8624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// construction vtable, this holds the offset from the layout class to the
8724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// most derived class.
8824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CharUnits MostDerivedClassOffset;
8924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
9024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// LayoutClass - The class we're using for layout information. Will be
9124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// different than the most derived class if the final overriders are for a
9224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// construction vtable.
9324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *LayoutClass;
9424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
9524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ASTContext &Context;
9624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
9724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MostDerivedClassLayout - the AST record layout of the most derived class.
9824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const ASTRecordLayout &MostDerivedClassLayout;
9924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
10024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MethodBaseOffsetPairTy - Uniquely identifies a member function
10124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// in a base subobject.
10224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef std::pair<const CXXMethodDecl *, CharUnits> MethodBaseOffsetPairTy;
10324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
10424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<MethodBaseOffsetPairTy,
10524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                         OverriderInfo> OverridersMapTy;
10624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
10724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// OverridersMap - The final overriders for all virtual member functions of
10824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// all the base subobjects of the most derived class.
10924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  OverridersMapTy OverridersMap;
11024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
11124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// SubobjectsToOffsetsMapTy - A mapping from a base subobject (represented
11224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// as a record decl and a subobject number) and its offsets in the most
11324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// derived class as well as the layout class.
11424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<std::pair<const CXXRecordDecl *, unsigned>,
11524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                         CharUnits> SubobjectOffsetMapTy;
11624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
11724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCountMapTy;
11824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
11924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// ComputeBaseOffsets - Compute the offsets for all base subobjects of the
12024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// given base.
12124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
12224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                          CharUnits OffsetInLayoutClass,
12324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                          SubobjectOffsetMapTy &SubobjectOffsets,
12424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                          SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
12524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                          SubobjectCountMapTy &SubobjectCounts);
12624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
12724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
12824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
12924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// dump - dump the final overriders for a base subobject, and all its direct
13024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// and indirect base subobjects.
13124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void dump(raw_ostream &Out, BaseSubobject Base,
13224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            VisitedVirtualBasesSetTy& VisitedVirtualBases);
13324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
13424018467ddb13857b764182f7753764d2f32f87dPeter Collingbournepublic:
13524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  FinalOverriders(const CXXRecordDecl *MostDerivedClass,
13624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                  CharUnits MostDerivedClassOffset,
13724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                  const CXXRecordDecl *LayoutClass);
13824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
13924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// getOverrider - Get the final overrider for the given method declaration in
14024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// the subobject with the given base offset.
14124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  OverriderInfo getOverrider(const CXXMethodDecl *MD,
14224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                             CharUnits BaseOffset) const {
14324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    assert(OverridersMap.count(std::make_pair(MD, BaseOffset)) &&
14424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne           "Did not find overrider!");
14524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
14624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return OverridersMap.lookup(std::make_pair(MD, BaseOffset));
14724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
14824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
14924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// dump - dump the final overriders.
15024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void dump() {
15124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VisitedVirtualBasesSetTy VisitedVirtualBases;
15224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    dump(llvm::errs(), BaseSubobject(MostDerivedClass, CharUnits::Zero()),
15324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne         VisitedVirtualBases);
15424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
15524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
15624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne};
15724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
15824018467ddb13857b764182f7753764d2f32f87dPeter CollingbourneFinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass,
15924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                 CharUnits MostDerivedClassOffset,
16024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                 const CXXRecordDecl *LayoutClass)
16124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  : MostDerivedClass(MostDerivedClass),
16224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass),
16324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Context(MostDerivedClass->getASTContext()),
16424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)) {
16524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
16624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Compute base offsets.
16724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  SubobjectOffsetMapTy SubobjectOffsets;
16824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  SubobjectOffsetMapTy SubobjectLayoutClassOffsets;
16924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  SubobjectCountMapTy SubobjectCounts;
17024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ComputeBaseOffsets(BaseSubobject(MostDerivedClass, CharUnits::Zero()),
17124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                     /*IsVirtual=*/false,
17224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                     MostDerivedClassOffset,
17324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                     SubobjectOffsets, SubobjectLayoutClassOffsets,
17424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                     SubobjectCounts);
17524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
176bed28ac1d1463adca3ecf24fca5c30646fa9dbb2Sylvestre Ledru  // Get the final overriders.
17724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  CXXFinalOverriderMap FinalOverriders;
17824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  MostDerivedClass->getFinalOverriders(FinalOverriders);
17924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
18087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const auto &Overrider : FinalOverriders) {
18187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    const CXXMethodDecl *MD = Overrider.first;
18287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    const OverridingMethods &Methods = Overrider.second;
18387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
18487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    for (const auto &M : Methods) {
18587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      unsigned SubobjectNumber = M.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
19387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      assert(M.second.size() == 1 && "Final overrider is not unique!");
19487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const UniqueVirtualMethod &Method = M.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
219b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainarstatic BaseOffset ComputeBaseOffset(const 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
258b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainarstatic BaseOffset ComputeBaseOffset(const 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.
48387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  if (LT->getTypeQuals() != RT->getTypeQuals())
48424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return false;
48587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  return LT->getParamTypes() == RT->getParamTypes();
48624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
48724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
48824018467ddb13857b764182f7753764d2f32f87dPeter Collingbournebool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
48924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                                const CXXMethodDecl *RHS) {
49024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  assert(LHS->isVirtual() && "LHS must be virtual!");
49124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  assert(RHS->isVirtual() && "LHS must be virtual!");
49224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
49324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // A destructor can share a vcall offset with another destructor.
49424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (isa<CXXDestructorDecl>(LHS))
49524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return isa<CXXDestructorDecl>(RHS);
49624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
49724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // FIXME: We need to check more things here.
49824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
49924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // The methods must have the same name.
50024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  DeclarationName LHSName = LHS->getDeclName();
50124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  DeclarationName RHSName = RHS->getDeclName();
50224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (LHSName != RHSName)
50324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return false;
50424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
50524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // And the same signatures.
50624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return HasSameVirtualSignature(LHS, RHS);
50724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
50824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
50924018467ddb13857b764182f7753764d2f32f87dPeter Collingbournebool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl *MD,
51024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    CharUnits OffsetOffset) {
51124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Check if we can reuse an offset.
51287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const auto &OffsetPair : Offsets) {
51387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
51424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      return false;
51524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
51624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
51724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Add the offset.
51824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset));
51924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return true;
52024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
52124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
52224018467ddb13857b764182f7753764d2f32f87dPeter CollingbourneCharUnits VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) {
52324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Look for an offset.
52487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const auto &OffsetPair : Offsets) {
52587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
52687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      return OffsetPair.second;
52724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
52824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
52924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  llvm_unreachable("Should always find a vcall offset offset!");
53024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
53124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
53224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// VCallAndVBaseOffsetBuilder - Class for building vcall and vbase offsets.
53324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourneclass VCallAndVBaseOffsetBuilder {
53424018467ddb13857b764182f7753764d2f32f87dPeter Collingbournepublic:
53524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
53624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VBaseOffsetOffsetsMapTy;
53724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
53824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourneprivate:
53924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MostDerivedClass - The most derived class for which we're building vcall
54024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// and vbase offsets.
54124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *MostDerivedClass;
54224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
54324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// LayoutClass - The class we're using for layout information. Will be
54424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// different than the most derived class if we're building a construction
54524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// vtable.
54624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *LayoutClass;
54724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
54824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// Context - The ASTContext which we will use for layout information.
54924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ASTContext &Context;
55024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
55124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// Components - vcall and vbase offset components
55224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef SmallVector<VTableComponent, 64> VTableComponentVectorTy;
55324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VTableComponentVectorTy Components;
55424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
55524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// VisitedVirtualBases - Visited virtual bases.
55624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
55724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
55824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// VCallOffsets - Keeps track of vcall offsets.
55924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VCallOffsetMap VCallOffsets;
56024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
56124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
56224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets,
56324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// relative to the address point.
56424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
56524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
56624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// FinalOverriders - The final overriders of the most derived class.
56724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// (Can be null when we're not building a vtable of the most derived class).
56824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const FinalOverriders *Overriders;
56924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
57024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// AddVCallAndVBaseOffsets - Add vcall offsets and vbase offsets for the
57124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// given base subobject.
57224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void AddVCallAndVBaseOffsets(BaseSubobject Base, bool BaseIsVirtual,
57324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                               CharUnits RealBaseOffset);
57424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
57524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// AddVCallOffsets - Add vcall offsets for the given base subobject.
57624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void AddVCallOffsets(BaseSubobject Base, CharUnits VBaseOffset);
57724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
57824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// AddVBaseOffsets - Add vbase offsets for the given class.
57924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void AddVBaseOffsets(const CXXRecordDecl *Base,
58024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                       CharUnits OffsetInLayoutClass);
58124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
58224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// getCurrentOffsetOffset - Get the current vcall or vbase offset offset in
58324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// chars, relative to the vtable address point.
58424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  CharUnits getCurrentOffsetOffset() const;
58524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
58624018467ddb13857b764182f7753764d2f32f87dPeter Collingbournepublic:
58724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VCallAndVBaseOffsetBuilder(const CXXRecordDecl *MostDerivedClass,
58824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                             const CXXRecordDecl *LayoutClass,
58924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                             const FinalOverriders *Overriders,
59024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                             BaseSubobject Base, bool BaseIsVirtual,
59124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                             CharUnits OffsetInLayoutClass)
59224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    : MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass),
59324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Context(MostDerivedClass->getASTContext()), Overriders(Overriders) {
59424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
59524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Add vcall and vbase offsets.
59624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddVCallAndVBaseOffsets(Base, BaseIsVirtual, OffsetInLayoutClass);
59724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
59824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
59924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// Methods for iterating over the components.
60024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef VTableComponentVectorTy::const_reverse_iterator const_iterator;
60124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const_iterator components_begin() const { return Components.rbegin(); }
60224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const_iterator components_end() const { return Components.rend(); }
60324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
60424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const VCallOffsetMap &getVCallOffsets() const { return VCallOffsets; }
60524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const {
60624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return VBaseOffsetOffsets;
60724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
60824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne};
60924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
61024018467ddb13857b764182f7753764d2f32f87dPeter Collingbournevoid
61124018467ddb13857b764182f7753764d2f32f87dPeter CollingbourneVCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base,
61224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                                    bool BaseIsVirtual,
61324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                                    CharUnits RealBaseOffset) {
61424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base.getBase());
61524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
61624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Itanium C++ ABI 2.5.2:
61724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   ..in classes sharing a virtual table with a primary base class, the vcall
61824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   and vbase offsets added by the derived class all come before the vcall
61924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   and vbase offsets required by the base class, so that the latter may be
62024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   laid out as required by the base class without regard to additions from
62124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   the derived class(es).
62224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
62324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // (Since we're emitting the vcall and vbase offsets in reverse order, we'll
62424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // emit them for the primary base first).
62524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
62624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    bool PrimaryBaseIsVirtual = Layout.isPrimaryBaseVirtual();
62724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
62824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits PrimaryBaseOffset;
62924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
63024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Get the base offset of the primary base.
63124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (PrimaryBaseIsVirtual) {
632d4f5198ae07d9a4958d8191bac694ded12173ad9Benjamin Kramer      assert(Layout.getVBaseClassOffset(PrimaryBase).isZero() &&
63324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             "Primary vbase should have a zero offset!");
63424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
63524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &MostDerivedClassLayout =
63624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(MostDerivedClass);
63724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
63824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      PrimaryBaseOffset =
63924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
64024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    } else {
641d4f5198ae07d9a4958d8191bac694ded12173ad9Benjamin Kramer      assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
64224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             "Primary base should have a zero offset!");
64324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
64424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      PrimaryBaseOffset = Base.getBaseOffset();
64524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
64624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
64724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddVCallAndVBaseOffsets(
64824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseSubobject(PrimaryBase,PrimaryBaseOffset),
64924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      PrimaryBaseIsVirtual, RealBaseOffset);
65024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
65124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
65224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  AddVBaseOffsets(Base.getBase(), RealBaseOffset);
65324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
65424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // We only want to add vcall offsets for virtual bases.
65524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (BaseIsVirtual)
65624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddVCallOffsets(Base, RealBaseOffset);
65724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
65824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
65924018467ddb13857b764182f7753764d2f32f87dPeter CollingbourneCharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset() const {
66024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // OffsetIndex is the index of this vcall or vbase offset, relative to the
66124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // vtable address point. (We subtract 3 to account for the information just
66224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // above the address point, the RTTI info, the offset to top, and the
66324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // vcall offset itself).
66424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  int64_t OffsetIndex = -(int64_t)(3 + Components.size());
66524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
66624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  CharUnits PointerWidth =
66724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
66824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  CharUnits OffsetOffset = PointerWidth * OffsetIndex;
66924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return OffsetOffset;
67024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
67124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
67224018467ddb13857b764182f7753764d2f32f87dPeter Collingbournevoid VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
67324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                                 CharUnits VBaseOffset) {
67424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *RD = Base.getBase();
67524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
67624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
67724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
67824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
67924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Handle the primary base first.
68024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // We only want to add vcall offsets if the base is non-virtual; a virtual
68124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // primary base will have its vcall and vbase offsets emitted already.
68224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (PrimaryBase && !Layout.isPrimaryBaseVirtual()) {
68324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Get the base offset of the primary base.
684d4f5198ae07d9a4958d8191bac694ded12173ad9Benjamin Kramer    assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
68524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne           "Primary base should have a zero offset!");
68624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
68724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddVCallOffsets(BaseSubobject(PrimaryBase, Base.getBaseOffset()),
68824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                    VBaseOffset);
68924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
69024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
69124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Add the vcall offsets.
692651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto *MD : RD->methods()) {
69324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!MD->isVirtual())
69424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
6950e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    MD = MD->getCanonicalDecl();
69624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
69724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits OffsetOffset = getCurrentOffsetOffset();
69824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
69924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Don't add a vcall offset if we already have one for this member function
70024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // signature.
70124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
70224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
70324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
70424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits Offset = CharUnits::Zero();
70524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
70624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (Overriders) {
70724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Get the final overrider.
70824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      FinalOverriders::OverriderInfo Overrider =
70924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Overriders->getOverrider(MD, Base.getBaseOffset());
71024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
71124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      /// The vcall offset is the offset from the virtual base to the object
71224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      /// where the function was overridden.
71324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Offset = Overrider.Offset - VBaseOffset;
71424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
71524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
71624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Components.push_back(
71724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VTableComponent::MakeVCallOffset(Offset));
71824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
71924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
72024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // And iterate over all non-virtual bases (ignoring the primary base).
721651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &B : RD->bases()) {
722651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (B.isVirtual())
72324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
72424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
725651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
72624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (BaseDecl == PrimaryBase)
72724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
72824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
72924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Get the base offset of this base.
73024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits BaseOffset = Base.getBaseOffset() +
73124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Layout.getBaseClassOffset(BaseDecl);
73224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
73324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddVCallOffsets(BaseSubobject(BaseDecl, BaseOffset),
73424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                    VBaseOffset);
73524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
73624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
73724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
73824018467ddb13857b764182f7753764d2f32f87dPeter Collingbournevoid
73924018467ddb13857b764182f7753764d2f32f87dPeter CollingbourneVCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
74024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                            CharUnits OffsetInLayoutClass) {
74124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const ASTRecordLayout &LayoutClassLayout =
74224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Context.getASTRecordLayout(LayoutClass);
74324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
74424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Add vbase offsets.
745651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &B : RD->bases()) {
746651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
74724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
74824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check if this is a virtual base that we haven't visited before.
749176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl).second) {
75024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      CharUnits Offset =
75124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        LayoutClassLayout.getVBaseClassOffset(BaseDecl) - OffsetInLayoutClass;
75224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
75324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Add the vbase offset offset.
75424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      assert(!VBaseOffsetOffsets.count(BaseDecl) &&
75524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             "vbase offset offset already exists!");
75624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
75724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      CharUnits VBaseOffsetOffset = getCurrentOffsetOffset();
75824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VBaseOffsetOffsets.insert(
75924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          std::make_pair(BaseDecl, VBaseOffsetOffset));
76024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
76124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Components.push_back(
76224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          VTableComponent::MakeVBaseOffset(Offset));
76324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
76424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
76524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check the base class looking for more vbase offsets.
76624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
76724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
76824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
76924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
770f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov/// ItaniumVTableBuilder - Class for building vtable layout information.
771f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovclass ItaniumVTableBuilder {
77224018467ddb13857b764182f7753764d2f32f87dPeter Collingbournepublic:
77324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// PrimaryBasesSetVectorTy - A set vector of direct and indirect
77424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// primary bases.
77524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::SmallSetVector<const CXXRecordDecl *, 8>
77624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    PrimaryBasesSetVectorTy;
77724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
77824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
77924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VBaseOffsetOffsetsMapTy;
78024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
78124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<BaseSubobject, uint64_t>
78224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddressPointsMapTy;
78324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
7842aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
7852aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
78624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourneprivate:
78724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// VTables - Global vtable information.
788f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov  ItaniumVTableContext &VTables;
78924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
79024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MostDerivedClass - The most derived class for which we're building this
79124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// vtable.
79224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *MostDerivedClass;
79324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
79424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MostDerivedClassOffset - If we're building a construction vtable, this
79524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// holds the offset from the layout class to the most derived class.
79624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CharUnits MostDerivedClassOffset;
79724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
79824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MostDerivedClassIsVirtual - Whether the most derived class is a virtual
79924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// base. (This only makes sense when building a construction vtable).
80024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  bool MostDerivedClassIsVirtual;
80124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
80224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// LayoutClass - The class we're using for layout information. Will be
80324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// different than the most derived class if we're building a construction
80424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// vtable.
80524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *LayoutClass;
80624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
80724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// Context - The ASTContext which we will use for layout information.
80824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ASTContext &Context;
80924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
81024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// FinalOverriders - The final overriders of the most derived class.
81124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const FinalOverriders Overriders;
81224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
81324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// VCallOffsetsForVBases - Keeps track of vcall offsets for the virtual
81424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// bases in this vtable.
81524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
81624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
81724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for
81824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// the most derived class.
81924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
82024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
82124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// Components - The components of the vtable being built.
82224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  SmallVector<VTableComponent, 64> Components;
82324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
82424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// AddressPoints - Address points for the vtable being built.
82524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  AddressPointsMapTy AddressPoints;
82624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
82724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MethodInfo - Contains information about a method in a vtable.
82824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// (Used for computing 'this' pointer adjustment thunks.
82924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  struct MethodInfo {
83024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    /// BaseOffset - The base offset of this method.
83124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CharUnits BaseOffset;
83224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
83324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    /// BaseOffsetInLayoutClass - The base offset in the layout class of this
83424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    /// method.
83524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CharUnits BaseOffsetInLayoutClass;
83624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
83724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    /// VTableIndex - The index in the vtable that this method has.
83824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    /// (For destructors, this is the index of the complete destructor).
83924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const uint64_t VTableIndex;
84024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
84124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    MethodInfo(CharUnits BaseOffset, CharUnits BaseOffsetInLayoutClass,
84224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne               uint64_t VTableIndex)
84324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      : BaseOffset(BaseOffset),
84424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
84524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VTableIndex(VTableIndex) { }
84624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
84724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    MethodInfo()
84824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      : BaseOffset(CharUnits::Zero()),
84924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseOffsetInLayoutClass(CharUnits::Zero()),
85024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VTableIndex(0) { }
85124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  };
85224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
85324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
85424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
85524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// MethodInfoMap - The information for all methods in the vtable we're
85624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// currently building.
85724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  MethodInfoMapTy MethodInfoMap;
8582aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
8592aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  /// MethodVTableIndices - Contains the index (relative to the vtable address
8602aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  /// point) where the function pointer for a virtual function is stored.
8612aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  MethodVTableIndicesTy MethodVTableIndices;
8622aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
86324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
86424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
86524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// VTableThunks - The thunks by vtable index in the vtable currently being
86624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// built.
86724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VTableThunksMapTy VTableThunks;
86824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
86924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
87024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
87124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
87224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// Thunks - A map that contains all the thunks needed for all methods in the
87324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// most derived class for which the vtable is currently being built.
87424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ThunksMapTy Thunks;
87524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
87624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// AddThunk - Add a thunk for the given method.
87724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void AddThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk);
87824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
87924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// ComputeThisAdjustments - Compute the 'this' pointer adjustments for the
88024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// part of the vtable we're currently building.
88124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void ComputeThisAdjustments();
88224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
88324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
88424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
88524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// PrimaryVirtualBases - All known virtual bases who are a primary base of
88624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// some other base.
88724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VisitedVirtualBasesSetTy PrimaryVirtualBases;
88824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
88924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// ComputeReturnAdjustment - Compute the return adjustment given a return
89024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// adjustment base offset.
89124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ReturnAdjustment ComputeReturnAdjustment(BaseOffset Offset);
89224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
89324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// ComputeThisAdjustmentBaseOffset - Compute the base offset for adjusting
89424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// the 'this' pointer from the base subobject to the derived subobject.
89524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  BaseOffset ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
89624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                             BaseSubobject Derived) const;
89724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
89824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// ComputeThisAdjustment - Compute the 'this' pointer adjustment for the
89924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// given virtual member function, its offset in the layout class and its
90024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// final overrider.
90124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ThisAdjustment
90224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ComputeThisAdjustment(const CXXMethodDecl *MD,
90324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                        CharUnits BaseOffsetInLayoutClass,
90424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                        FinalOverriders::OverriderInfo Overrider);
90524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
90624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// AddMethod - Add a single virtual member function to the vtable
90724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// components vector.
90824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment);
90924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
91024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// IsOverriderUsed - Returns whether the overrider will ever be used in this
91124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// part of the vtable.
91224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///
91324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// Itanium C++ ABI 2.5.2:
91424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///
91524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   struct A { virtual void f(); };
91624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   struct B : virtual public A { int i; };
91724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   struct C : virtual public A { int j; };
91824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   struct D : public B, public C {};
91924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///
92024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   When B and C are declared, A is a primary base in each case, so although
92124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   vcall offsets are allocated in the A-in-B and A-in-C vtables, no this
92224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   adjustment is required and no thunk is generated. However, inside D
92324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   objects, A is no longer a primary base of C, so if we allowed calls to
92424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   C::f() to use the copy of A's vtable in the C subobject, we would need
92524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   to adjust this from C* to B::A*, which would require a third-party
92624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   thunk. Since we require that a call to C::f() first convert to A*,
92724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   C-in-D's copy of A's vtable is never referenced, so this is not
92824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///   necessary.
92924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  bool IsOverriderUsed(const CXXMethodDecl *Overrider,
93024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                       CharUnits BaseOffsetInLayoutClass,
93124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                       const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
93224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                       CharUnits FirstBaseOffsetInLayoutClass) const;
93324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
93424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
93524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// AddMethods - Add the methods of this base subobject and all its
93624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// primary bases to the vtable components vector.
93724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void AddMethods(BaseSubobject Base, CharUnits BaseOffsetInLayoutClass,
93824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                  const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
93924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                  CharUnits FirstBaseOffsetInLayoutClass,
94024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                  PrimaryBasesSetVectorTy &PrimaryBases);
94124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
94224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // LayoutVTable - Layout the vtable for the given base class, including its
94324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // secondary vtables and any vtables for virtual bases.
94424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void LayoutVTable();
94524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
94624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// LayoutPrimaryAndSecondaryVTables - Layout the primary vtable for the
94724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// given base subobject, as well as all its secondary vtables.
94824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///
94924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
95024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// or a direct or indirect base of a virtual base.
95124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///
95224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// \param BaseIsVirtualInLayoutClass - Whether the base subobject is virtual
95324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// in the layout class.
95424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void LayoutPrimaryAndSecondaryVTables(BaseSubobject Base,
95524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                        bool BaseIsMorallyVirtual,
95624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                        bool BaseIsVirtualInLayoutClass,
95724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                        CharUnits OffsetInLayoutClass);
95824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
95924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// LayoutSecondaryVTables - Layout the secondary vtables for the given base
96024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// subobject.
96124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ///
96224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
96324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// or a direct or indirect base of a virtual base.
96424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void LayoutSecondaryVTables(BaseSubobject Base, bool BaseIsMorallyVirtual,
96524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                              CharUnits OffsetInLayoutClass);
96624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
96724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this
96824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// class hierarchy.
96924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void DeterminePrimaryVirtualBases(const CXXRecordDecl *RD,
97024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    CharUnits OffsetInLayoutClass,
97124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    VisitedVirtualBasesSetTy &VBases);
97224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
97324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// LayoutVTablesForVirtualBases - Layout vtables for all virtual bases of the
97424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// given base (excluding any primary bases).
97524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void LayoutVTablesForVirtualBases(const CXXRecordDecl *RD,
97624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    VisitedVirtualBasesSetTy &VBases);
97724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
97824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// isBuildingConstructionVTable - Return whether this vtable builder is
97924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// building a construction vtable.
98024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  bool isBuildingConstructorVTable() const {
98124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return MostDerivedClass != LayoutClass;
98224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
98324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
98424018467ddb13857b764182f7753764d2f32f87dPeter Collingbournepublic:
985f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov  ItaniumVTableBuilder(ItaniumVTableContext &VTables,
986f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                       const CXXRecordDecl *MostDerivedClass,
987f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                       CharUnits MostDerivedClassOffset,
988f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                       bool MostDerivedClassIsVirtual,
989f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                       const CXXRecordDecl *LayoutClass)
990f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov      : VTables(VTables), MostDerivedClass(MostDerivedClass),
991f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov        MostDerivedClassOffset(MostDerivedClassOffset),
992f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov        MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
993f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov        LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()),
994f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov        Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) {
9952cb17a06befb61b1434aaa991652fea4338c95d7Timur Iskhodzhanov    assert(!Context.getTargetInfo().getCXXABI().isMicrosoft());
99624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
99724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    LayoutVTable();
99824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
9994e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie    if (Context.getLangOpts().DumpVTableLayouts)
1000152eee9f81f1b4f00e1bce655903fc78cafb1342Reid Kleckner      dumpLayout(llvm::outs());
100124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
100224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
100324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  uint64_t getNumThunks() const {
100424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return Thunks.size();
100524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
100624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
100724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ThunksMapTy::const_iterator thunks_begin() const {
100824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return Thunks.begin();
100924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
101024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
101124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ThunksMapTy::const_iterator thunks_end() const {
101224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return Thunks.end();
101324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
101424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
101524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const {
101624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return VBaseOffsetOffsets;
101724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
101824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
101924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const AddressPointsMapTy &getAddressPoints() const {
102024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return AddressPoints;
102124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
102224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
10232aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  MethodVTableIndicesTy::const_iterator vtable_indices_begin() const {
10242aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    return MethodVTableIndices.begin();
10252aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  }
10262aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
10272aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  MethodVTableIndicesTy::const_iterator vtable_indices_end() const {
10282aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    return MethodVTableIndices.end();
10292aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  }
10302aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
103124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// getNumVTableComponents - Return the number of components in the vtable
103224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// currently built.
103324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  uint64_t getNumVTableComponents() const {
103424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return Components.size();
103524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
103624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
103724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const VTableComponent *vtable_component_begin() const {
103824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return Components.begin();
103924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
104024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
104124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const VTableComponent *vtable_component_end() const {
104224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return Components.end();
104324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
104424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
104524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  AddressPointsMapTy::const_iterator address_points_begin() const {
104624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return AddressPoints.begin();
104724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
104824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
104924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  AddressPointsMapTy::const_iterator address_points_end() const {
105024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return AddressPoints.end();
105124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
105224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
105324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VTableThunksMapTy::const_iterator vtable_thunks_begin() const {
105424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return VTableThunks.begin();
105524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
105624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
105724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VTableThunksMapTy::const_iterator vtable_thunks_end() const {
105824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return VTableThunks.end();
105924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
106024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
106124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// dumpLayout - Dump the vtable layout.
106224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void dumpLayout(raw_ostream&);
106324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne};
106424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1065f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::AddThunk(const CXXMethodDecl *MD,
1066f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                                    const ThunkInfo &Thunk) {
106724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  assert(!isBuildingConstructorVTable() &&
106824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne         "Can't add thunks for construction vtable");
106924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
10706b9240e058bf3451685df73fc8ce181b3046e92bCraig Topper  SmallVectorImpl<ThunkInfo> &ThunksVector = Thunks[MD];
10716b9240e058bf3451685df73fc8ce181b3046e92bCraig Topper
107224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Check if we have this thunk already.
107324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
107424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      ThunksVector.end())
107524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return;
107624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
107724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ThunksVector.push_back(Thunk);
107824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
107924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
108024018467ddb13857b764182f7753764d2f32f87dPeter Collingbournetypedef llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverriddenMethodsSetTy;
108124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1082635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov/// Visit all the methods overridden by the given method recursively,
1083635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov/// in a depth-first pre-order. The Visitor's visitor method returns a bool
1084635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov/// indicating whether to continue the recursion for the given overridden
1085635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov/// method (i.e. returning false stops the iteration).
1086635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovtemplate <class VisitorTy>
1087635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovstatic void
1088635de28950ef84ae26308ff734e778bad1ddde92Timur IskhodzhanovvisitAllOverriddenMethods(const CXXMethodDecl *MD, VisitorTy &Visitor) {
108924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  assert(MD->isVirtual() && "Method is not virtual!");
109024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
109124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
109224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne       E = MD->end_overridden_methods(); I != E; ++I) {
109324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXMethodDecl *OverriddenMD = *I;
109487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    if (!Visitor(OverriddenMD))
1095635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      continue;
1096635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    visitAllOverriddenMethods(OverriddenMD, Visitor);
109724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
109824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
109924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1100635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov/// ComputeAllOverriddenMethods - Given a method decl, will return a set of all
1101635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov/// the overridden methods that the function decl overrides.
1102635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovstatic void
1103635de28950ef84ae26308ff734e778bad1ddde92Timur IskhodzhanovComputeAllOverriddenMethods(const CXXMethodDecl *MD,
1104635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                            OverriddenMethodsSetTy& OverriddenMethods) {
110587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  auto OverriddenMethodsCollector = [&](const CXXMethodDecl *MD) {
110687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    // Don't recurse on this method if we've already collected it.
110787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    return OverriddenMethods.insert(MD).second;
110887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  };
110987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  visitAllOverriddenMethods(MD, OverriddenMethodsCollector);
1110635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
1111635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
1112f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::ComputeThisAdjustments() {
111324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Now go through the method info map and see if any of the methods need
111424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // 'this' pointer adjustments.
111587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const auto &MI : MethodInfoMap) {
111687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    const CXXMethodDecl *MD = MI.first;
111787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    const MethodInfo &MethodInfo = MI.second;
111824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
111924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Ignore adjustments for unused function pointers.
112024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    uint64_t VTableIndex = MethodInfo.VTableIndex;
112124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (Components[VTableIndex].getKind() ==
112224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        VTableComponent::CK_UnusedFunctionPointer)
112324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
112424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
112524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Get the final overrider for this method.
112624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    FinalOverriders::OverriderInfo Overrider =
112724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Overriders.getOverrider(MD, MethodInfo.BaseOffset);
112824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
112924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check if we need an adjustment at all.
113024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) {
113124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // When a return thunk is needed by a derived class that overrides a
113224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // virtual base, gcc uses a virtual 'this' adjustment as well.
113324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // While the thunk itself might be needed by vtables in subclasses or
113424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // in construction vtables, there doesn't seem to be a reason for using
113524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // the thunk in this vtable. Still, we do so to match gcc.
113624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (VTableThunks.lookup(VTableIndex).Return.isEmpty())
113724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        continue;
113824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
113924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
114024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    ThisAdjustment ThisAdjustment =
114124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
114224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
114324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (ThisAdjustment.isEmpty())
114424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
114524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
114624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Add it.
114724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VTableThunks[VTableIndex].This = ThisAdjustment;
114824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1149a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov    if (isa<CXXDestructorDecl>(MD)) {
115024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Add an adjustment for the deleting destructor as well.
115124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VTableThunks[VTableIndex + 1].This = ThisAdjustment;
115224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
115324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
115424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
115524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  /// Clear the method info map.
115624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  MethodInfoMap.clear();
115724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
115824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (isBuildingConstructorVTable()) {
115924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // We don't need to store thunk information for construction vtables.
116024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return;
116124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
116224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
116387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const auto &TI : VTableThunks) {
116487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    const VTableComponent &Component = Components[TI.first];
116587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    const ThunkInfo &Thunk = TI.second;
116624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXMethodDecl *MD;
116724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
116824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    switch (Component.getKind()) {
116924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    default:
117024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      llvm_unreachable("Unexpected vtable component kind!");
117124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_FunctionPointer:
117224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      MD = Component.getFunctionDecl();
117324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
117424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_CompleteDtorPointer:
117524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      MD = Component.getDestructorDecl();
117624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
117724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_DeletingDtorPointer:
117824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // We've already added the thunk when we saw the complete dtor pointer.
117924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
118024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
118124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
118224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (MD->getParent() == MostDerivedClass)
118324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      AddThunk(MD, Thunk);
118424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
118524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
118624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1187f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovReturnAdjustment
1188f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovItaniumVTableBuilder::ComputeReturnAdjustment(BaseOffset Offset) {
118924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ReturnAdjustment Adjustment;
119024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
119124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (!Offset.isEmpty()) {
119224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (Offset.VirtualBase) {
119324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Get the virtual base offset offset.
119424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (Offset.DerivedClass == MostDerivedClass) {
119524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // We can get the offset offset directly from our map.
1196c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov        Adjustment.Virtual.Itanium.VBaseOffsetOffset =
119724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          VBaseOffsetOffsets.lookup(Offset.VirtualBase).getQuantity();
119824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      } else {
1199c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov        Adjustment.Virtual.Itanium.VBaseOffsetOffset =
120024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          VTables.getVirtualBaseOffsetOffset(Offset.DerivedClass,
120124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                             Offset.VirtualBase).getQuantity();
120224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
120324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
120424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
120524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Adjustment.NonVirtual = Offset.NonVirtualOffset.getQuantity();
120624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
120724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
120824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return Adjustment;
120924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
121024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1211f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovBaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
1212f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    BaseSubobject Base, BaseSubobject Derived) const {
121324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *BaseRD = Base.getBase();
121424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *DerivedRD = Derived.getBase();
121524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
121624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  CXXBasePaths Paths(/*FindAmbiguities=*/true,
121724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                     /*RecordPaths=*/true, /*DetectVirtual=*/true);
121824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1219922cec29a9366f70d593d6225aea01dcd3daf8cfBenjamin Kramer  if (!DerivedRD->isDerivedFrom(BaseRD, Paths))
122024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    llvm_unreachable("Class must be derived from the passed in base class!");
122124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
122224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // We have to go through all the paths, and see which one leads us to the
122324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // right base subobject.
122487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const CXXBasePath &Path : Paths) {
122587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, Path);
122687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
122724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset;
122824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
122924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (Offset.VirtualBase) {
123024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // If we have a virtual base class, the non-virtual offset is relative
123124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // to the virtual base class offset.
123224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &LayoutClassLayout =
123324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(LayoutClass);
123424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
123524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      /// Get the virtual base offset, relative to the most derived class
123624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      /// layout.
123724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      OffsetToBaseSubobject +=
123824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        LayoutClassLayout.getVBaseClassOffset(Offset.VirtualBase);
123924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    } else {
124024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Otherwise, the non-virtual offset is relative to the derived class
124124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // offset.
124224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      OffsetToBaseSubobject += Derived.getBaseOffset();
124324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
124424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
124524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check if this path gives us the right base subobject.
124624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (OffsetToBaseSubobject == Base.getBaseOffset()) {
124724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Since we're going from the base class _to_ the derived class, we'll
124824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // invert the non-virtual offset here.
124924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
125024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      return Offset;
125124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
125224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
125324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
125424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return BaseOffset();
125524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
1256f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov
1257f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovThisAdjustment ItaniumVTableBuilder::ComputeThisAdjustment(
1258f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    const CXXMethodDecl *MD, CharUnits BaseOffsetInLayoutClass,
1259f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    FinalOverriders::OverriderInfo Overrider) {
126024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Ignore adjustments for pure virtual member functions.
126124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (Overrider.Method->isPure())
126224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return ThisAdjustment();
126324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
126424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  BaseSubobject OverriddenBaseSubobject(MD->getParent(),
126524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                        BaseOffsetInLayoutClass);
126624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
126724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
126824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                       Overrider.Offset);
126924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
127024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Compute the adjustment offset.
127124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
127224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                                      OverriderBaseSubobject);
127324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (Offset.isEmpty())
127424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return ThisAdjustment();
127524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
127624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ThisAdjustment Adjustment;
127724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
127824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (Offset.VirtualBase) {
127924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Get the vcall offset map for this virtual base.
128024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
128124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
128224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (VCallOffsets.empty()) {
128324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // We don't have vcall offsets for this virtual base, go ahead and
128424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // build them.
128524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass,
12866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                         /*FinalOverriders=*/nullptr,
128724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                         BaseSubobject(Offset.VirtualBase,
128824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                                       CharUnits::Zero()),
128924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                         /*BaseIsVirtual=*/true,
129024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                         /*OffsetInLayoutClass=*/
129124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                             CharUnits::Zero());
129224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
129324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VCallOffsets = Builder.getVCallOffsets();
129424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
129524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
129658b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    Adjustment.Virtual.Itanium.VCallOffsetOffset =
129724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VCallOffsets.getVCallOffsetOffset(MD).getQuantity();
129824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
129924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
130024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Set the non-virtual part of the adjustment.
130124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Adjustment.NonVirtual = Offset.NonVirtualOffset.getQuantity();
130224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
130324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return Adjustment;
130424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
1305f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov
1306f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::AddMethod(const CXXMethodDecl *MD,
1307f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                                     ReturnAdjustment ReturnAdjustment) {
130824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
130924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    assert(ReturnAdjustment.isEmpty() &&
131024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne           "Destructor can't have return adjustment!");
131124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1312a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov    // Add both the complete destructor and the deleting destructor.
1313a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov    Components.push_back(VTableComponent::MakeCompleteDtor(DD));
1314a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov    Components.push_back(VTableComponent::MakeDeletingDtor(DD));
131524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  } else {
131624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Add the return adjustment if necessary.
131724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!ReturnAdjustment.isEmpty())
131824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VTableThunks[Components.size()].Return = ReturnAdjustment;
131924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
132024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Add the function.
132124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Components.push_back(VTableComponent::MakeFunction(MD));
132224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
132324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
132424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
132524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// OverridesIndirectMethodInBase - Return whether the given member function
132624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// overrides any methods in the set of given bases.
132724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// Unlike OverridesMethodInBase, this checks "overriders of overriders".
132824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// For example, if we have:
132924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne///
133024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// struct A { virtual void f(); }
133124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// struct B : A { virtual void f(); }
133224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// struct C : B { virtual void f(); }
133324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne///
133424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// OverridesIndirectMethodInBase will return true if given C::f as the method
133524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// and { A } as the set of bases.
1336f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovstatic bool OverridesIndirectMethodInBases(
1337f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    const CXXMethodDecl *MD,
1338f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    ItaniumVTableBuilder::PrimaryBasesSetVectorTy &Bases) {
133924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (Bases.count(MD->getParent()))
134024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return true;
134124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
134224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
134324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne       E = MD->end_overridden_methods(); I != E; ++I) {
134424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXMethodDecl *OverriddenMD = *I;
134524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
134624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check "indirect overriders".
134724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
134824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      return true;
134924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
135024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
135124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return false;
135224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
135324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1354f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovbool ItaniumVTableBuilder::IsOverriderUsed(
1355f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    const CXXMethodDecl *Overrider, CharUnits BaseOffsetInLayoutClass,
1356f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
1357f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    CharUnits FirstBaseOffsetInLayoutClass) const {
135824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // If the base and the first base in the primary base chain have the same
135924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // offsets, then this overrider will be used.
136024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass)
136124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne   return true;
136224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
136324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // We know now that Base (or a direct or indirect base of it) is a primary
136424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // base in part of the class hierarchy, but not a primary base in the most
136524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // derived class.
136624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
136724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // If the overrider is the first base in the primary base chain, we know
136824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // that the overrider will be used.
136924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (Overrider->getParent() == FirstBaseInPrimaryBaseChain)
137024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return true;
1371f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov
1372f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov  ItaniumVTableBuilder::PrimaryBasesSetVectorTy PrimaryBases;
137324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
137424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *RD = FirstBaseInPrimaryBaseChain;
137524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  PrimaryBases.insert(RD);
137624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
137724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Now traverse the base chain, starting with the first base, until we find
137824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // the base that is no longer a primary base.
137924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  while (true) {
138024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
138124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
138224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
138324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!PrimaryBase)
138424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
138524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
138624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (Layout.isPrimaryBaseVirtual()) {
1387d4f5198ae07d9a4958d8191bac694ded12173ad9Benjamin Kramer      assert(Layout.getVBaseClassOffset(PrimaryBase).isZero() &&
138824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             "Primary base should always be at offset 0!");
138924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
139024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &LayoutClassLayout =
139124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(LayoutClass);
139224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
139324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Now check if this is the primary base that is not a primary base in the
139424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // most derived class.
139524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) !=
139624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          FirstBaseOffsetInLayoutClass) {
139724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // We found it, stop walking the chain.
139824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        break;
139924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
140024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    } else {
1401d4f5198ae07d9a4958d8191bac694ded12173ad9Benjamin Kramer      assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
140224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             "Primary base should always be at offset 0!");
140324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
140424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
140524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!PrimaryBases.insert(PrimaryBase))
140624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      llvm_unreachable("Found a duplicate primary base!");
140724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
140824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    RD = PrimaryBase;
140924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
141024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
141124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // If the final overrider is an override of one of the primary bases,
141224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // then we know that it will be used.
141324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return OverridesIndirectMethodInBases(Overrider, PrimaryBases);
141424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
141524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1416635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovtypedef llvm::SmallSetVector<const CXXRecordDecl *, 8> BasesSetVectorTy;
1417635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
141824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// FindNearestOverriddenMethod - Given a method, returns the overridden method
141924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// from the nearest base. Returns null if no method was found.
1420635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov/// The Bases are expected to be sorted in a base-to-derived order.
1421635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovstatic const CXXMethodDecl *
142224018467ddb13857b764182f7753764d2f32f87dPeter CollingbourneFindNearestOverriddenMethod(const CXXMethodDecl *MD,
1423635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                            BasesSetVectorTy &Bases) {
142424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  OverriddenMethodsSetTy OverriddenMethods;
142524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ComputeAllOverriddenMethods(MD, OverriddenMethods);
142624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
142787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const CXXRecordDecl *PrimaryBase :
142887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar       llvm::make_range(Bases.rbegin(), Bases.rend())) {
1429635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // Now check the overridden methods.
143087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    for (const CXXMethodDecl *OverriddenMD : OverriddenMethods) {
143124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // We found our overridden method.
143224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (OverriddenMD->getParent() == PrimaryBase)
143324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        return OverriddenMD;
143424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
143524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
14366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
14376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return nullptr;
1438f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov}
143924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1440f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::AddMethods(
1441f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    BaseSubobject Base, CharUnits BaseOffsetInLayoutClass,
1442f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
1443f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    CharUnits FirstBaseOffsetInLayoutClass,
1444f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    PrimaryBasesSetVectorTy &PrimaryBases) {
14452aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  // Itanium C++ ABI 2.5.2:
14462aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  //   The order of the virtual function pointers in a virtual table is the
14472aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  //   order of declaration of the corresponding member functions in the class.
14482aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  //
14492aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  //   There is an entry for any virtual function declared in a class,
14502aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  //   whether it is a new function or overrides a base class function,
14512aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  //   unless it overrides a function from the primary base, and conversion
14522aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  //   between their return types does not require an adjustment.
14532aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
145424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *RD = Base.getBase();
145524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
145624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
145724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
145824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits PrimaryBaseOffset;
145924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits PrimaryBaseOffsetInLayoutClass;
146024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (Layout.isPrimaryBaseVirtual()) {
1461d4f5198ae07d9a4958d8191bac694ded12173ad9Benjamin Kramer      assert(Layout.getVBaseClassOffset(PrimaryBase).isZero() &&
146224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             "Primary vbase should have a zero offset!");
146324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
146424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &MostDerivedClassLayout =
146524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(MostDerivedClass);
146624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
146724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      PrimaryBaseOffset =
146824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
146924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
147024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &LayoutClassLayout =
147124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(LayoutClass);
147224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
147324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      PrimaryBaseOffsetInLayoutClass =
147424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        LayoutClassLayout.getVBaseClassOffset(PrimaryBase);
147524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    } else {
1476d4f5198ae07d9a4958d8191bac694ded12173ad9Benjamin Kramer      assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
147724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             "Primary base should have a zero offset!");
147824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
147924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      PrimaryBaseOffset = Base.getBaseOffset();
148024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass;
148124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
148224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
148324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddMethods(BaseSubobject(PrimaryBase, PrimaryBaseOffset),
148424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne               PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
148524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne               FirstBaseOffsetInLayoutClass, PrimaryBases);
148624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
148724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!PrimaryBases.insert(PrimaryBase))
148824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      llvm_unreachable("Found a duplicate primary base!");
148924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
149024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
14916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  const CXXDestructorDecl *ImplicitVirtualDtor = nullptr;
14922aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
14932aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  typedef llvm::SmallVector<const CXXMethodDecl *, 8> NewVirtualFunctionsTy;
14942aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  NewVirtualFunctionsTy NewVirtualFunctions;
14952aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
149624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Now go through all virtual member functions and add them.
1497651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto *MD : RD->methods()) {
149824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!MD->isVirtual())
149924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
15000e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    MD = MD->getCanonicalDecl();
150124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
150224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Get the final overrider.
150324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    FinalOverriders::OverriderInfo Overrider =
150424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Overriders.getOverrider(MD, Base.getBaseOffset());
150524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
150624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check if this virtual member function overrides a method in a primary
150724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // base. If this is the case, and the return type doesn't require adjustment
150824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // then we can just use the member function from the primary base.
150924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (const CXXMethodDecl *OverriddenMD =
151024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          FindNearestOverriddenMethod(MD, PrimaryBases)) {
151124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (ComputeReturnAdjustmentBaseOffset(Context, MD,
151224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                            OverriddenMD).isEmpty()) {
151324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // Replace the method info of the overridden method with our own
151424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // method.
151524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        assert(MethodInfoMap.count(OverriddenMD) &&
151624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne               "Did not find the overridden method!");
151724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
151824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
151924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass,
152024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                              OverriddenMethodInfo.VTableIndex);
152124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
152224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        assert(!MethodInfoMap.count(MD) &&
152324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne               "Should not have method info for this method yet!");
152424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
152524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
152624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        MethodInfoMap.erase(OverriddenMD);
152724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
152824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // If the overridden method exists in a virtual base class or a direct
152924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // or indirect base class of a virtual base class, we need to emit a
153024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // thunk if we ever have a class hierarchy where the base class is not
153124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // a primary base in the complete object.
153224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        if (!isBuildingConstructorVTable() && OverriddenMD != MD) {
153324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          // Compute the this adjustment.
153424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          ThisAdjustment ThisAdjustment =
153524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
153624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                  Overrider);
153724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
153858b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov          if (ThisAdjustment.Virtual.Itanium.VCallOffsetOffset &&
153924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne              Overrider.Method->getParent() == MostDerivedClass) {
154024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
154124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            // There's no return adjustment from OverriddenMD and MD,
154224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            // but that doesn't mean there isn't one between MD and
154324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            // the final overrider.
154424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            BaseOffset ReturnAdjustmentOffset =
154524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne              ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
154624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            ReturnAdjustment ReturnAdjustment =
154724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne              ComputeReturnAdjustment(ReturnAdjustmentOffset);
154824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
154924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            // This is a virtual thunk for the most derived class, add it.
155024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            AddThunk(Overrider.Method,
155124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                     ThunkInfo(ThisAdjustment, ReturnAdjustment));
155224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          }
155324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        }
155424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
155524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        continue;
155624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
155724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
155824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
15592aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
15602aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      if (MD->isImplicit()) {
15612aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov        // Itanium C++ ABI 2.5.2:
15622aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov        //   If a class has an implicitly-defined virtual destructor,
15632aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov        //   its entries come after the declared virtual function pointers.
15642aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
15652aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov        assert(!ImplicitVirtualDtor &&
15662aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov               "Did already see an implicit virtual dtor!");
15672aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov        ImplicitVirtualDtor = DD;
15682aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov        continue;
15692aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      }
15702aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    }
15712aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
15722aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    NewVirtualFunctions.push_back(MD);
15732aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  }
15742aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
15752aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  if (ImplicitVirtualDtor)
15762aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    NewVirtualFunctions.push_back(ImplicitVirtualDtor);
15772aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
157887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const CXXMethodDecl *MD : NewVirtualFunctions) {
15792aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    // Get the final overrider.
15802aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    FinalOverriders::OverriderInfo Overrider =
15812aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      Overriders.getOverrider(MD, Base.getBaseOffset());
15822aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
158324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Insert the method info for this method.
158424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass,
158524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                          Components.size());
158624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
158724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    assert(!MethodInfoMap.count(MD) &&
158824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne           "Should not have method info for this method yet!");
158924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
159024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
159124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check if this overrider is going to be used.
159224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXMethodDecl *OverriderMD = Overrider.Method;
159324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass,
159424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                         FirstBaseInPrimaryBaseChain,
159524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                         FirstBaseOffsetInLayoutClass)) {
159624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Components.push_back(VTableComponent::MakeUnusedFunction(OverriderMD));
159724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
159824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
15992aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
160024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check if this overrider needs a return adjustment.
160124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // We don't want to do this for pure virtual member functions.
160224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    BaseOffset ReturnAdjustmentOffset;
160324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!OverriderMD->isPure()) {
160424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      ReturnAdjustmentOffset =
160524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
160624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
160724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
160824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    ReturnAdjustment ReturnAdjustment =
160924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      ComputeReturnAdjustment(ReturnAdjustmentOffset);
161024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
161124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddMethod(Overrider.Method, ReturnAdjustment);
161224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
161324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
161424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1615f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::LayoutVTable() {
161624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  LayoutPrimaryAndSecondaryVTables(BaseSubobject(MostDerivedClass,
161724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                                 CharUnits::Zero()),
161824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                   /*BaseIsMorallyVirtual=*/false,
161924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                   MostDerivedClassIsVirtual,
162024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                   MostDerivedClassOffset);
162124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
162224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VisitedVirtualBasesSetTy VBases;
162324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
162424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Determine the primary virtual bases.
162524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
162624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                               VBases);
162724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VBases.clear();
162824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
162924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
163024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
163124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // -fapple-kext adds an extra entry at end of vtbl.
16324e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  bool IsAppleKext = Context.getLangOpts().AppleKext;
163324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (IsAppleKext)
163424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Components.push_back(VTableComponent::MakeVCallOffset(CharUnits::Zero()));
163524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
1636f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov
1637f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
1638f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    BaseSubobject Base, bool BaseIsMorallyVirtual,
1639f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    bool BaseIsVirtualInLayoutClass, CharUnits OffsetInLayoutClass) {
164024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!");
164124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
164224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Add vcall and vbase offsets for this vtable.
164324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders,
164424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                     Base, BaseIsVirtualInLayoutClass,
164524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                     OffsetInLayoutClass);
164624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Components.append(Builder.components_begin(), Builder.components_end());
164724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
164824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Check if we need to add these vcall offsets.
164924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) {
165024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Base.getBase()];
165124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
165224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (VCallOffsets.empty())
165324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      VCallOffsets = Builder.getVCallOffsets();
165424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
165524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
165624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // If we're laying out the most derived class we want to keep track of the
165724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // virtual base class offset offsets.
165824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (Base.getBase() == MostDerivedClass)
165924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
166024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1661a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov  // Add the offset to top.
1662a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov  CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
1663a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov  Components.push_back(VTableComponent::MakeOffsetToTop(OffsetToTop));
1664649c7316aa29181df7270732722fe5d07ab3c7adTimur Iskhodzhanov
1665a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov  // Next, add the RTTI.
1666a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov  Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
1667649c7316aa29181df7270732722fe5d07ab3c7adTimur Iskhodzhanov
166824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  uint64_t AddressPoint = Components.size();
166924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
167024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Now go through all virtual member functions and add them.
167124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  PrimaryBasesSetVectorTy PrimaryBases;
167224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  AddMethods(Base, OffsetInLayoutClass,
167324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             Base.getBase(), OffsetInLayoutClass,
167424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne             PrimaryBases);
167524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
16762aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  const CXXRecordDecl *RD = Base.getBase();
16772aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  if (RD == MostDerivedClass) {
16782aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    assert(MethodVTableIndices.empty());
167987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    for (const auto &I : MethodInfoMap) {
168087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const CXXMethodDecl *MD = I.first;
168187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const MethodInfo &MI = I.second;
16822aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1683a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov        MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
1684a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov            = MI.VTableIndex - AddressPoint;
1685a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov        MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
1686a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov            = MI.VTableIndex + 1 - AddressPoint;
16872aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      } else {
16882aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov        MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
16892aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      }
16902aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov    }
16912aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  }
16922aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
169324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Compute 'this' pointer adjustments.
169424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ComputeThisAdjustments();
169524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
169624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Add all address points.
169724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  while (true) {
169824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddressPoints.insert(std::make_pair(
169924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseSubobject(RD, OffsetInLayoutClass),
170024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      AddressPoint));
170124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
170224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
170324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
170424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
170524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!PrimaryBase)
170624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
170724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
170824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (Layout.isPrimaryBaseVirtual()) {
170924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Check if this virtual primary base is a primary base in the layout
171024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // class. If it's not, we don't want to add it.
171124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &LayoutClassLayout =
171224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(LayoutClass);
171324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
171424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) !=
171524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          OffsetInLayoutClass) {
171624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // We don't want to add this class (or any of its primary bases).
171724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        break;
171824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
171924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
172024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
172124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    RD = PrimaryBase;
172224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
172324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
172424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Layout secondary vtables.
172524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  LayoutSecondaryVTables(Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
172624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
172724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1728f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid
1729f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovItaniumVTableBuilder::LayoutSecondaryVTables(BaseSubobject Base,
1730f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                                             bool BaseIsMorallyVirtual,
1731f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                                             CharUnits OffsetInLayoutClass) {
173224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Itanium C++ ABI 2.5.2:
173324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   Following the primary virtual table of a derived class are secondary
173424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   virtual tables for each of its proper base classes, except any primary
173524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   base(s) with which it shares its primary virtual table.
173624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
173724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *RD = Base.getBase();
173824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
173924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
174024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1741651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &B : RD->bases()) {
174224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Ignore virtual bases, we'll emit them later.
1743651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (B.isVirtual())
174424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
174524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1746651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
174724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
174824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Ignore bases that don't have a vtable.
174924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!BaseDecl->isDynamicClass())
175024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
175124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
175224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (isBuildingConstructorVTable()) {
175324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      // Itanium C++ ABI 2.6.4:
175424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      //   Some of the base class subobjects may not need construction virtual
175524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      //   tables, which will therefore not be present in the construction
175624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      //   virtual table group, even though the subobject virtual tables are
175724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      //   present in the main virtual table group for the complete object.
175824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (!BaseIsMorallyVirtual && !BaseDecl->getNumVBases())
175924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        continue;
176024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
176124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
176224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Get the base offset of this base.
176324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits RelativeBaseOffset = Layout.getBaseClassOffset(BaseDecl);
176424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits BaseOffset = Base.getBaseOffset() + RelativeBaseOffset;
176524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
176624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits BaseOffsetInLayoutClass =
176724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      OffsetInLayoutClass + RelativeBaseOffset;
176824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
176924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Don't emit a secondary vtable for a primary base. We might however want
177024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // to emit secondary vtables for other bases of this base.
177124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (BaseDecl == PrimaryBase) {
177224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      LayoutSecondaryVTables(BaseSubobject(BaseDecl, BaseOffset),
177324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                             BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
177424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
177524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
177624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
177724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Layout the primary vtable (and any secondary vtables) for this base.
177824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    LayoutPrimaryAndSecondaryVTables(
177924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseSubobject(BaseDecl, BaseOffset),
178024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseIsMorallyVirtual,
178124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      /*BaseIsVirtualInLayoutClass=*/false,
178224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseOffsetInLayoutClass);
178324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
178424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
178524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1786f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
1787f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    const CXXRecordDecl *RD, CharUnits OffsetInLayoutClass,
1788f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    VisitedVirtualBasesSetTy &VBases) {
178924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
179024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
179124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Check if this base has a primary base.
179224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
179324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
179424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check if it's virtual.
179524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (Layout.isPrimaryBaseVirtual()) {
179624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      bool IsPrimaryVirtualBase = true;
179724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
179824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (isBuildingConstructorVTable()) {
179924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // Check if the base is actually a primary base in the class we use for
180024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // layout.
180124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        const ASTRecordLayout &LayoutClassLayout =
180224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Context.getASTRecordLayout(LayoutClass);
180324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
180424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        CharUnits PrimaryBaseOffsetInLayoutClass =
180524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          LayoutClassLayout.getVBaseClassOffset(PrimaryBase);
180624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
180724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // We know that the base is not a primary base in the layout class if
180824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // the base offsets are different.
180924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass)
181024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          IsPrimaryVirtualBase = false;
181124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
181224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
181324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (IsPrimaryVirtualBase)
181424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        PrimaryVirtualBases.insert(PrimaryBase);
181524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
181624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
181724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
181824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Traverse bases, looking for more primary virtual bases.
1819651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &B : RD->bases()) {
1820651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
182124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
182224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    CharUnits BaseOffsetInLayoutClass;
182324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1824651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (B.isVirtual()) {
1825176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (!VBases.insert(BaseDecl).second)
182624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        continue;
182724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
182824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &LayoutClassLayout =
182924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(LayoutClass);
183024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
183124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseOffsetInLayoutClass =
183224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        LayoutClassLayout.getVBaseClassOffset(BaseDecl);
183324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    } else {
183424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      BaseOffsetInLayoutClass =
183524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        OffsetInLayoutClass + Layout.getBaseClassOffset(BaseDecl);
183624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
183724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
183824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases);
183924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
184024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
184124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1842f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
1843f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases) {
184424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Itanium C++ ABI 2.5.2:
184524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   Then come the virtual base virtual tables, also in inheritance graph
184624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   order, and again excluding primary bases (which share virtual tables with
184724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  //   the classes for which they are primary).
1848651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &B : RD->bases()) {
1849651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
185024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
185124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Check if this base needs a vtable. (If it's virtual, not a primary base
185224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // of some other class, and we haven't visited it before).
1853176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (B.isVirtual() && BaseDecl->isDynamicClass() &&
1854176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        !PrimaryVirtualBases.count(BaseDecl) &&
1855176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        VBases.insert(BaseDecl).second) {
185624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &MostDerivedClassLayout =
185724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(MostDerivedClass);
185824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      CharUnits BaseOffset =
185924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
186024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
186124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const ASTRecordLayout &LayoutClassLayout =
186224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Context.getASTRecordLayout(LayoutClass);
186324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      CharUnits BaseOffsetInLayoutClass =
186424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        LayoutClassLayout.getVBaseClassOffset(BaseDecl);
186524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
186624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      LayoutPrimaryAndSecondaryVTables(
186724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        BaseSubobject(BaseDecl, BaseOffset),
186824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        /*BaseIsMorallyVirtual=*/true,
186924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        /*BaseIsVirtualInLayoutClass=*/true,
187024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        BaseOffsetInLayoutClass);
187124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
187224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
187324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // We only need to check the base for virtual base vtables if it actually
187424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // has virtual bases.
187524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (BaseDecl->getNumVBases())
187624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      LayoutVTablesForVirtualBases(BaseDecl, VBases);
187724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
187824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
187924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
188024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne/// dumpLayout - Dump the vtable layout.
1881f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
188215a0de95f5b364cfb96bacc644f491215bd92098Timur Iskhodzhanov  // FIXME: write more tests that actually use the dumpLayout output to prevent
1883f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov  // ItaniumVTableBuilder regressions.
188424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
188524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (isBuildingConstructorVTable()) {
188624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << "Construction vtable for ('";
1887651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    MostDerivedClass->printQualifiedName(Out);
1888651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Out << "', ";
188924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << MostDerivedClassOffset.getQuantity() << ") in '";
1890651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    LayoutClass->printQualifiedName(Out);
189124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  } else {
189224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << "Vtable for '";
1893651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    MostDerivedClass->printQualifiedName(Out);
189424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
189524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Out << "' (" << Components.size() << " entries).\n";
189624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
189724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Iterate through the address points and insert them into a new map where
189824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // they are keyed by the index and not the base object.
189924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Since an address point can be shared by multiple subobjects, we use an
190024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // STL multimap.
190124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
190287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const auto &AP : AddressPoints) {
190387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    const BaseSubobject &Base = AP.first;
190487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    uint64_t Index = AP.second;
190587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
190624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    AddressPointsByIndex.insert(std::make_pair(Index, Base));
190724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
190824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
190924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  for (unsigned I = 0, E = Components.size(); I != E; ++I) {
191024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    uint64_t Index = I;
191124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
191224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << llvm::format("%4d | ", I);
191324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
191424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    const VTableComponent &Component = Components[I];
191524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
191624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Dump the component.
191724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    switch (Component.getKind()) {
191824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
191924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_VCallOffset:
192024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << "vcall_offset ("
192124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          << Component.getVCallOffset().getQuantity()
192224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          << ")";
192324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
192424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
192524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_VBaseOffset:
192624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << "vbase_offset ("
192724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          << Component.getVBaseOffset().getQuantity()
192824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          << ")";
192924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
193024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
193124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_OffsetToTop:
193224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << "offset_to_top ("
193324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          << Component.getOffsetToTop().getQuantity()
193424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          << ")";
193524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
193624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
193724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_RTTI:
1938651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Component.getRTTIDecl()->printQualifiedName(Out);
1939651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Out << " RTTI";
194024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
194124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
194224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_FunctionPointer: {
194324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const CXXMethodDecl *MD = Component.getFunctionDecl();
194424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
194524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      std::string Str =
194624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
194724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    MD);
194824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << Str;
194924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (MD->isPure())
195024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << " [pure]";
195124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1952d954ab47c681b8afc94bc3accbee708a05e6768eDavid Blaikie      if (MD->isDeleted())
1953d954ab47c681b8afc94bc3accbee708a05e6768eDavid Blaikie        Out << " [deleted]";
1954d954ab47c681b8afc94bc3accbee708a05e6768eDavid Blaikie
195524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      ThunkInfo Thunk = VTableThunks.lookup(I);
195624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (!Thunk.isEmpty()) {
195724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // If this function pointer has a return adjustment, dump it.
195824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        if (!Thunk.Return.isEmpty()) {
195924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << "\n       [return adjustment: ";
196024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << Thunk.Return.NonVirtual << " non-virtual";
196124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1962c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov          if (Thunk.Return.Virtual.Itanium.VBaseOffsetOffset) {
1963c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov            Out << ", " << Thunk.Return.Virtual.Itanium.VBaseOffsetOffset;
196424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            Out << " vbase offset offset";
196524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          }
196624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
196724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << ']';
196824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        }
196924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
197024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // If this function pointer has a 'this' pointer adjustment, dump it.
197124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        if (!Thunk.This.isEmpty()) {
197224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << "\n       [this adjustment: ";
197324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << Thunk.This.NonVirtual << " non-virtual";
197424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
197558b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov          if (Thunk.This.Virtual.Itanium.VCallOffsetOffset) {
197658b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov            Out << ", " << Thunk.This.Virtual.Itanium.VCallOffsetOffset;
197724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            Out << " vcall offset offset";
197824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          }
197924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
198024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << ']';
198124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        }
198224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
198324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
198424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
198524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
198624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
198724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_CompleteDtorPointer:
198824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_DeletingDtorPointer: {
198924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      bool IsComplete =
199024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Component.getKind() == VTableComponent::CK_CompleteDtorPointer;
199124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
199224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const CXXDestructorDecl *DD = Component.getDestructorDecl();
199324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1994651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      DD->printQualifiedName(Out);
199524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (IsComplete)
199624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << "() [complete]";
199724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      else
199824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << "() [deleting]";
199924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
200024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (DD->isPure())
200124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << " [pure]";
200224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
200324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      ThunkInfo Thunk = VTableThunks.lookup(I);
200424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (!Thunk.isEmpty()) {
200524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // If this destructor has a 'this' pointer adjustment, dump it.
200624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        if (!Thunk.This.isEmpty()) {
200724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << "\n       [this adjustment: ";
200824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << Thunk.This.NonVirtual << " non-virtual";
200924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
201058b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov          if (Thunk.This.Virtual.Itanium.VCallOffsetOffset) {
201158b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov            Out << ", " << Thunk.This.Virtual.Itanium.VCallOffsetOffset;
201224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            Out << " vcall offset offset";
201324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          }
201424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
201524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << ']';
201624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        }
201724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
201824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
201924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      break;
202024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
202124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
202224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    case VTableComponent::CK_UnusedFunctionPointer: {
202324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      const CXXMethodDecl *MD = Component.getUnusedFunctionDecl();
202424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
202524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      std::string Str =
202624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
202724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    MD);
202824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << "[unused] " << Str;
202924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (MD->isPure())
203024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << " [pure]";
203124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
203224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
203324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
203424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
203524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << '\n';
203624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
203724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Dump the next address point.
203824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    uint64_t NextIndex = Index + 1;
203924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (AddressPointsByIndex.count(NextIndex)) {
204024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      if (AddressPointsByIndex.count(NextIndex) == 1) {
204124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        const BaseSubobject &Base =
204224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          AddressPointsByIndex.find(NextIndex)->second;
204324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2044651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        Out << "       -- (";
2045651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        Base.getBase()->printQualifiedName(Out);
204624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << ", " << Base.getBaseOffset().getQuantity();
204724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << ") vtable address --\n";
204824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      } else {
204924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        CharUnits BaseOffset =
205024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
205124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
205224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // We store the class names in a set to get a stable order.
205324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        std::set<std::string> ClassNames;
205487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        for (const auto &I :
205587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar             llvm::make_range(AddressPointsByIndex.equal_range(NextIndex))) {
205687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          assert(I.second.getBaseOffset() == BaseOffset &&
205724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                 "Invalid base offset!");
205887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          const CXXRecordDecl *RD = I.second.getBase();
205924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          ClassNames.insert(RD->getQualifiedNameAsString());
206024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        }
206187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
206287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        for (const std::string &Name : ClassNames) {
206387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          Out << "       -- (" << Name;
206424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << ", " << BaseOffset.getQuantity() << ") vtable address --\n";
206524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        }
206624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
206724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
206824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
206924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
207024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Out << '\n';
207124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
207224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (isBuildingConstructorVTable())
207324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return;
207424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
207524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (MostDerivedClass->getNumVBases()) {
207624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // We store the virtual base class names and their offsets in a map to get
207724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // a stable order.
207824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
207924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    std::map<std::string, CharUnits> ClassNamesAndOffsets;
208087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    for (const auto &I : VBaseOffsetOffsets) {
208187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      std::string ClassName = I.first->getQualifiedNameAsString();
208287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      CharUnits OffsetOffset = I.second;
208387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
208424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
208524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
208624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << "Virtual base offset offsets for '";
2087651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    MostDerivedClass->printQualifiedName(Out);
2088651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Out << "' (";
208924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << ClassNamesAndOffsets.size();
209024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << (ClassNamesAndOffsets.size() == 1 ? " entry" : " entries") << ").\n";
209124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
209287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    for (const auto &I : ClassNamesAndOffsets)
209387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      Out << "   " << I.first << " | " << I.second.getQuantity() << '\n';
209424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
209524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << "\n";
209624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
209724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
209824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (!Thunks.empty()) {
209924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // We store the method names in a map to get a stable order.
210024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
210187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
210287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    for (const auto &I : Thunks) {
210387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const CXXMethodDecl *MD = I.first;
210424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      std::string MethodName =
210524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
210624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                    MD);
210724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
210824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
210924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
211024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
211187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    for (const auto &I : MethodNamesAndDecls) {
211287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const std::string &MethodName = I.first;
211387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const CXXMethodDecl *MD = I.second;
211424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
211524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      ThunkInfoVectorTy ThunksVector = Thunks[MD];
21162cb17a06befb61b1434aaa991652fea4338c95d7Timur Iskhodzhanov      std::sort(ThunksVector.begin(), ThunksVector.end(),
2117651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                [](const ThunkInfo &LHS, const ThunkInfo &RHS) {
21186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        assert(LHS.Method == nullptr && RHS.Method == nullptr);
2119651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return);
2120651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      });
212124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
212224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size();
212324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n";
212424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
212524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      for (unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
212624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        const ThunkInfo &Thunk = ThunksVector[I];
212724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
212824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << llvm::format("%4d | ", I);
212924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
213024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // If this function pointer has a return pointer adjustment, dump it.
213124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        if (!Thunk.Return.isEmpty()) {
213215a0de95f5b364cfb96bacc644f491215bd92098Timur Iskhodzhanov          Out << "return adjustment: " << Thunk.Return.NonVirtual;
213324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << " non-virtual";
2134c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov          if (Thunk.Return.Virtual.Itanium.VBaseOffsetOffset) {
2135c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov            Out << ", " << Thunk.Return.Virtual.Itanium.VBaseOffsetOffset;
213624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            Out << " vbase offset offset";
213724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          }
213824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
213924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          if (!Thunk.This.isEmpty())
214024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            Out << "\n       ";
214124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        }
214224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
214324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        // If this function pointer has a 'this' pointer adjustment, dump it.
214424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        if (!Thunk.This.isEmpty()) {
214524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << "this adjustment: ";
214624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          Out << Thunk.This.NonVirtual << " non-virtual";
214724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
214858b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov          if (Thunk.This.Virtual.Itanium.VCallOffsetOffset) {
214958b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov            Out << ", " << Thunk.This.Virtual.Itanium.VCallOffsetOffset;
215024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne            Out << " vcall offset offset";
215124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne          }
215224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        }
215324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
215424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne        Out << '\n';
215524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      }
215624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
215724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      Out << '\n';
215824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
215924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
216024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
216124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Compute the vtable indices for all the member functions.
216224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Store them in a map keyed by the index so we'll get a sorted table.
216324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  std::map<uint64_t, std::string> IndicesMap;
216424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2165651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto *MD : MostDerivedClass->methods()) {
216624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // We only want virtual member functions.
216724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (!MD->isVirtual())
216824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      continue;
21690e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    MD = MD->getCanonicalDecl();
217024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
217124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    std::string MethodName =
217224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
217324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                  MD);
217424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
217524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2176a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov      GlobalDecl GD(DD, Dtor_Complete);
2177a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov      assert(MethodVTableIndices.count(GD));
2178a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov      uint64_t VTableIndex = MethodVTableIndices[GD];
2179a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov      IndicesMap[VTableIndex] = MethodName + " [complete]";
2180a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov      IndicesMap[VTableIndex + 1] = MethodName + " [deleting]";
218124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    } else {
21822aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      assert(MethodVTableIndices.count(MD));
21832aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      IndicesMap[MethodVTableIndices[MD]] = MethodName;
218424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
218524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
218624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
218724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Print the vtable indices for all the member functions.
218824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (!IndicesMap.empty()) {
218924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << "VTable indices for '";
2190651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    MostDerivedClass->printQualifiedName(Out);
219124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    Out << "' (" << IndicesMap.size() << " entries).\n";
219224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
219387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    for (const auto &I : IndicesMap) {
219487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      uint64_t VTableIndex = I.first;
219587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const std::string &MethodName = I.second;
219624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
21972aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov      Out << llvm::format("%4" PRIu64 " | ", VTableIndex) << MethodName
219879a55010ed5afa88939e74186494ecfadefbfa43Benjamin Kramer          << '\n';
219924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
220024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
220124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
220224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Out << '\n';
220324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
220424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
220524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
220624018467ddb13857b764182f7753764d2f32f87dPeter CollingbourneVTableLayout::VTableLayout(uint64_t NumVTableComponents,
220724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                           const VTableComponent *VTableComponents,
220824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                           uint64_t NumVTableThunks,
220924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                           const VTableThunkTy *VTableThunks,
2210649c7316aa29181df7270732722fe5d07ab3c7adTimur Iskhodzhanov                           const AddressPointsMapTy &AddressPoints,
2211649c7316aa29181df7270732722fe5d07ab3c7adTimur Iskhodzhanov                           bool IsMicrosoftABI)
221224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  : NumVTableComponents(NumVTableComponents),
221324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VTableComponents(new VTableComponent[NumVTableComponents]),
221424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    NumVTableThunks(NumVTableThunks),
221524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VTableThunks(new VTableThunkTy[NumVTableThunks]),
2216649c7316aa29181df7270732722fe5d07ab3c7adTimur Iskhodzhanov    AddressPoints(AddressPoints),
2217649c7316aa29181df7270732722fe5d07ab3c7adTimur Iskhodzhanov    IsMicrosoftABI(IsMicrosoftABI) {
221824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  std::copy(VTableComponents, VTableComponents+NumVTableComponents,
22198fb9fb66d415ee40447277f649ecdb12b4964385Benjamin Kramer            this->VTableComponents.get());
22208fb9fb66d415ee40447277f649ecdb12b4964385Benjamin Kramer  std::copy(VTableThunks, VTableThunks+NumVTableThunks,
22218fb9fb66d415ee40447277f649ecdb12b4964385Benjamin Kramer            this->VTableThunks.get());
22222cb17a06befb61b1434aaa991652fea4338c95d7Timur Iskhodzhanov  std::sort(this->VTableThunks.get(),
22232cb17a06befb61b1434aaa991652fea4338c95d7Timur Iskhodzhanov            this->VTableThunks.get() + NumVTableThunks,
2224651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            [](const VTableLayout::VTableThunkTy &LHS,
2225651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines               const VTableLayout::VTableThunkTy &RHS) {
2226651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
2227651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines           "Different thunks should have unique indices!");
2228651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return LHS.first < RHS.first;
2229651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  });
223024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
223124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
22328fb9fb66d415ee40447277f649ecdb12b4964385Benjamin KramerVTableLayout::~VTableLayout() { }
223324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2234f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovItaniumVTableContext::ItaniumVTableContext(ASTContext &Context)
2235651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    : VTableContextBase(/*MS=*/false) {}
2236649c7316aa29181df7270732722fe5d07ab3c7adTimur Iskhodzhanov
2237f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovItaniumVTableContext::~ItaniumVTableContext() {
223824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  llvm::DeleteContainerSeconds(VTableLayouts);
223924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
224024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2241f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovuint64_t ItaniumVTableContext::getMethodVTableIndex(GlobalDecl GD) {
224224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
224324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (I != MethodVTableIndices.end())
224424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return I->second;
224524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
224624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
224724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2248635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  computeVTableRelatedInformation(RD);
224924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
225024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  I = MethodVTableIndices.find(GD);
225124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  assert(I != MethodVTableIndices.end() && "Did not find index!");
225224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return I->second;
225324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
225424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2255f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovCharUnits
2256f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovItaniumVTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
2257f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                                                 const CXXRecordDecl *VBase) {
225824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  ClassPairTy ClassPair(RD, VBase);
225924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
226024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  VirtualBaseClassOffsetOffsetsMapTy::iterator I =
226124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VirtualBaseClassOffsetOffsets.find(ClassPair);
226224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (I != VirtualBaseClassOffsetOffsets.end())
226324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return I->second;
22646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
22656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  VCallAndVBaseOffsetBuilder Builder(RD, RD, /*FinalOverriders=*/nullptr,
226624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                     BaseSubobject(RD, CharUnits::Zero()),
226724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                     /*BaseIsVirtual=*/false,
226824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                                     /*OffsetInLayoutClass=*/CharUnits::Zero());
226924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
227087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const auto &I : Builder.getVBaseOffsetOffsets()) {
227124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Insert all types.
227287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    ClassPairTy ClassPair(RD, I.first);
227387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
227487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
227524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
227624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
227724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  I = VirtualBaseClassOffsetOffsets.find(ClassPair);
227824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  assert(I != VirtualBaseClassOffsetOffsets.end() && "Did not find index!");
227924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
228024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return I->second;
228124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
228224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2283f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovstatic VTableLayout *CreateVTableLayout(const ItaniumVTableBuilder &Builder) {
228424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  SmallVector<VTableLayout::VTableThunkTy, 1>
228524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
228624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
228724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return new VTableLayout(Builder.getNumVTableComponents(),
228824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                          Builder.vtable_component_begin(),
228924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                          VTableThunks.size(),
229024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne                          VTableThunks.data(),
2291649c7316aa29181df7270732722fe5d07ab3c7adTimur Iskhodzhanov                          Builder.getAddressPoints(),
2292a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov                          /*IsMicrosoftABI=*/false);
229324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
229424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2295f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanovvoid
2296f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovItaniumVTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD) {
229724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const VTableLayout *&Entry = VTableLayouts[RD];
229824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
229924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Check if we've computed this information before.
230024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (Entry)
230124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return;
230224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2303f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov  ItaniumVTableBuilder Builder(*this, RD, CharUnits::Zero(),
2304f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                               /*MostDerivedClassIsVirtual=*/0, RD);
230524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Entry = CreateVTableLayout(Builder);
230624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
23072aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov  MethodVTableIndices.insert(Builder.vtable_indices_begin(),
23082aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov                             Builder.vtable_indices_end());
23092aae5ba15d07e9aa37ff9b03ad0024c0707068f5Timur Iskhodzhanov
231024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // Add the known thunks.
231124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
231224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
231324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // If we don't have the vbase information for this class, insert it.
231424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // getVirtualBaseOffsetOffset will compute it separately without computing
231524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // the rest of the vtable related information.
231624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (!RD->getNumVBases())
231724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return;
231824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2319432d488305492bd998dbcd200ed500389c7602f5Timur Iskhodzhanov  const CXXRecordDecl *VBase =
2320432d488305492bd998dbcd200ed500389c7602f5Timur Iskhodzhanov    RD->vbases_begin()->getType()->getAsCXXRecordDecl();
232124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
232224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
232324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return;
2324f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov
232587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const auto &I : Builder.getVBaseOffsetOffsets()) {
232624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    // Insert all types.
232787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    ClassPairTy ClassPair(RD, I.first);
232887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
232987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
233024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
233124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
233224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2333f07465828da2a07297646a2277ba8fe3abd2d4c3Timur IskhodzhanovVTableLayout *ItaniumVTableContext::createConstructionVTableLayout(
2334f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset,
2335f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov    bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass) {
2336f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov  ItaniumVTableBuilder Builder(*this, MostDerivedClass, MostDerivedClassOffset,
2337f07465828da2a07297646a2277ba8fe3abd2d4c3Timur Iskhodzhanov                               MostDerivedClassIsVirtual, LayoutClass);
233824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return CreateVTableLayout(Builder);
233924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
2340635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2341635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovnamespace {
2342635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2343635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov// Vtables in the Microsoft ABI are different from the Itanium ABI.
2344635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//
2345635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov// The main differences are:
2346635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//  1. Separate vftable and vbtable.
2347635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//
2348635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//  2. Each subobject with a vfptr gets its own vftable rather than an address
2349635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     point in a single vtable shared between all the subobjects.
2350635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     Each vftable is represented by a separate section and virtual calls
2351635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     must be done using the vftable which has a slot for the function to be
2352635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     called.
2353635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//
2354635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//  3. Virtual method definitions expect their 'this' parameter to point to the
2355635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     first vfptr whose table provides a compatible overridden method.  In many
2356635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     cases, this permits the original vf-table entry to directly call
2357635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     the method instead of passing through a thunk.
2358176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     See example before VFTableBuilder::ComputeThisOffset below.
2359635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//
2360635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     A compatible overridden method is one which does not have a non-trivial
2361635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     covariant-return adjustment.
2362635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//
2363635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     The first vfptr is the one with the lowest offset in the complete-object
2364635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     layout of the defining class, and the method definition will subtract
2365635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     that constant offset from the parameter value to get the real 'this'
2366635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     value.  Therefore, if the offset isn't really constant (e.g. if a virtual
2367635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     function defined in a virtual base is overridden in a more derived
2368635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     virtual base and these bases have a reverse order in the complete
2369635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     object), the vf-table may require a this-adjustment thunk.
2370635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//
2371635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//  4. vftables do not contain new entries for overrides that merely require
2372635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     this-adjustment.  Together with #3, this keeps vf-tables smaller and
2373635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     eliminates the need for this-adjustment thunks in many cases, at the cost
2374635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     of often requiring redundant work to adjust the "this" pointer.
2375635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//
2376635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//  5. Instead of VTT and constructor vtables, vbtables and vtordisps are used.
2377635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     Vtordisps are emitted into the class layout if a class has
2378635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//      a) a user-defined ctor/dtor
2379635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//     and
2380635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov//      b) a method overriding a method in a virtual base.
2381176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2382176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  To get a better understanding of this code,
2383176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  you might want to see examples in test/CodeGenCXX/microsoft-abi-vtables-*.cpp
2384635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2385635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovclass VFTableBuilder {
2386635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovpublic:
23875f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov  typedef MicrosoftVTableContext::MethodVFTableLocation MethodVFTableLocation;
2388635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2389635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
2390635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    MethodVFTableLocationsTy;
2391635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2392651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator>
2393651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    method_locations_range;
2394651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
2395635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovprivate:
23965f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov  /// VTables - Global vtable information.
23975f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov  MicrosoftVTableContext &VTables;
23985f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov
2399635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// Context - The ASTContext which we will use for layout information.
2400635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  ASTContext &Context;
2401635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2402635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// MostDerivedClass - The most derived class for which we're building this
2403635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// vtable.
2404635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const CXXRecordDecl *MostDerivedClass;
2405635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2406635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const ASTRecordLayout &MostDerivedClassLayout;
2407635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2408651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const VPtrInfo &WhichVFPtr;
2409635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2410635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// FinalOverriders - The final overriders of the most derived class.
2411635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const FinalOverriders Overriders;
2412635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2413635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// Components - The components of the vftable being built.
2414635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  SmallVector<VTableComponent, 64> Components;
2415635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2416635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  MethodVFTableLocationsTy MethodVFTableLocations;
2417635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2418c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// \brief Does this class have an RTTI component?
24194967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  bool HasRTTIComponent = false;
2420c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2421635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// MethodInfo - Contains information about a method in a vtable.
2422635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// (Used for computing 'this' pointer adjustment thunks.
2423635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  struct MethodInfo {
2424635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    /// VBTableIndex - The nonzero index in the vbtable that
2425635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    /// this method's base has, or zero.
2426635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    const uint64_t VBTableIndex;
2427635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2428635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    /// VFTableIndex - The index in the vftable that this method has.
2429635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    const uint64_t VFTableIndex;
2430635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2431635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    /// Shadowed - Indicates if this vftable slot is shadowed by
2432635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    /// a slot for a covariant-return override. If so, it shouldn't be printed
2433635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    /// or used for vcalls in the most derived class.
2434635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    bool Shadowed;
2435635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2436176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    /// UsesExtraSlot - Indicates if this vftable slot was created because
2437176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    /// any of the overridden slots required a return adjusting thunk.
2438176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    bool UsesExtraSlot;
2439176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
2440176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex,
2441176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines               bool UsesExtraSlot = false)
2442e39c0f32fd9e6c6de68b50a1b20bca58759ba8d5Timur Iskhodzhanov        : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
2443176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          Shadowed(false), UsesExtraSlot(UsesExtraSlot) {}
2444635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2445176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    MethodInfo()
2446176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        : VBTableIndex(0), VFTableIndex(0), Shadowed(false),
2447176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          UsesExtraSlot(false) {}
2448635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  };
2449635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2450635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
2451635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2452635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// MethodInfoMap - The information for all methods in the vftable we're
2453635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// currently building.
2454635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  MethodInfoMapTy MethodInfoMap;
2455635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2456635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
2457635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2458635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// VTableThunks - The thunks by vftable index in the vftable currently being
2459635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// built.
2460635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  VTableThunksMapTy VTableThunks;
2461635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2462635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
2463635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
2464635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2465635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// Thunks - A map that contains all the thunks needed for all methods in the
2466635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// most derived class for which the vftable is currently being built.
2467635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  ThunksMapTy Thunks;
2468635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2469635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// AddThunk - Add a thunk for the given method.
2470635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  void AddThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk) {
2471635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    SmallVector<ThunkInfo, 1> &ThunksVector = Thunks[MD];
2472635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2473635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // Check if we have this thunk already.
2474635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
2475635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        ThunksVector.end())
2476635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      return;
2477635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2478635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    ThunksVector.push_back(Thunk);
2479635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2480635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2481635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// ComputeThisOffset - Returns the 'this' argument offset for the given
2482651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// method, relative to the beginning of the MostDerivedClass.
2483651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
2484635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
248558b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
248658b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov                                   CharUnits ThisOffset, ThisAdjustment &TA);
248758b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov
2488635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// AddMethod - Add a single virtual member function to the vftable
2489635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// components vector.
24902cb17a06befb61b1434aaa991652fea4338c95d7Timur Iskhodzhanov  void AddMethod(const CXXMethodDecl *MD, ThunkInfo TI) {
2491651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!TI.isEmpty()) {
2492651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      VTableThunks[Components.size()] = TI;
2493651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      AddThunk(MD, TI);
2494651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
2495635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
24962cb17a06befb61b1434aaa991652fea4338c95d7Timur Iskhodzhanov      assert(TI.Return.isEmpty() &&
2497635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov             "Destructor can't have return adjustment!");
2498635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Components.push_back(VTableComponent::MakeDeletingDtor(DD));
2499635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    } else {
2500635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Components.push_back(VTableComponent::MakeFunction(MD));
2501635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
2502635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2503635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2504635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// AddMethods - Add the methods of this base subobject and the relevant
2505635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  /// subbases to the vftable we're currently laying out.
2506635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  void AddMethods(BaseSubobject Base, unsigned BaseDepth,
2507635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                  const CXXRecordDecl *LastVBase,
2508635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                  BasesSetVectorTy &VisitedBases);
2509635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2510635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  void LayoutVFTable() {
2511176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // RTTI data goes before all other entries.
2512176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (HasRTTIComponent)
2513176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
2514635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2515635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    BasesSetVectorTy VisitedBases;
25166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    AddMethods(BaseSubobject(MostDerivedClass, CharUnits::Zero()), 0, nullptr,
2517635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov               VisitedBases);
2518176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    assert((HasRTTIComponent ? Components.size() - 1 : Components.size()) &&
2519176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines           "vftable can't be empty");
2520635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2521635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    assert(MethodVFTableLocations.empty());
252287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    for (const auto &I : MethodInfoMap) {
252387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const CXXMethodDecl *MD = I.first;
252487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const MethodInfo &MI = I.second;
2525635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      // Skip the methods that the MostDerivedClass didn't override
2526635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      // and the entries shadowed by return adjusting thunks.
2527635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (MD->getParent() != MostDerivedClass || MI.Shadowed)
2528635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        continue;
2529651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      MethodVFTableLocation Loc(MI.VBTableIndex, WhichVFPtr.getVBaseWithVPtr(),
2530651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                WhichVFPtr.NonVirtualOffset, MI.VFTableIndex);
2531635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2532635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        MethodVFTableLocations[GlobalDecl(DD, Dtor_Deleting)] = Loc;
2533635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      } else {
2534635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        MethodVFTableLocations[MD] = Loc;
2535635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      }
2536635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
2537635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2538635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2539635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovpublic:
25405f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov  VFTableBuilder(MicrosoftVTableContext &VTables,
2541651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                 const CXXRecordDecl *MostDerivedClass, const VPtrInfo *Which)
25425f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov      : VTables(VTables),
25435f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov        Context(MostDerivedClass->getASTContext()),
2544635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        MostDerivedClass(MostDerivedClass),
2545635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)),
2546651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        WhichVFPtr(*Which),
2547635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) {
25484967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    // Provide the RTTI component if RTTIData is enabled. If the vftable would
25494967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    // be available externally, we should not provide the RTTI componenent. It
25504967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    // is currently impossible to get available externally vftables with either
25514967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    // dllimport or extern template instantiations, but eventually we may add a
25524967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    // flag to support additional devirtualization that needs this.
25534967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    if (Context.getLangOpts().RTTIData)
25544967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      HasRTTIComponent = true;
2555c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2556635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    LayoutVFTable();
2557635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2558635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    if (Context.getLangOpts().DumpVTableLayouts)
2559152eee9f81f1b4f00e1bce655903fc78cafb1342Reid Kleckner      dumpLayout(llvm::outs());
2560635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2561635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2562635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  uint64_t getNumThunks() const { return Thunks.size(); }
2563635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2564635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  ThunksMapTy::const_iterator thunks_begin() const { return Thunks.begin(); }
2565635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2566635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  ThunksMapTy::const_iterator thunks_end() const { return Thunks.end(); }
2567635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2568651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  method_locations_range vtable_locations() const {
2569651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return method_locations_range(MethodVFTableLocations.begin(),
2570651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                  MethodVFTableLocations.end());
2571635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2572635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2573635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  uint64_t getNumVTableComponents() const { return Components.size(); }
2574635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2575635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const VTableComponent *vtable_component_begin() const {
2576635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    return Components.begin();
2577635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2578635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2579635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const VTableComponent *vtable_component_end() const {
2580635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    return Components.end();
2581635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2582635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2583635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  VTableThunksMapTy::const_iterator vtable_thunks_begin() const {
2584635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    return VTableThunks.begin();
2585635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2586635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2587635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  VTableThunksMapTy::const_iterator vtable_thunks_end() const {
2588635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    return VTableThunks.end();
2589635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2590635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2591635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  void dumpLayout(raw_ostream &);
2592635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov};
2593635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
25943ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar} // end namespace
25953ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
2596176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Let's study one class hierarchy as an example:
2597176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct A {
2598176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     virtual void f();
2599176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     int x;
2600176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   };
2601176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2602176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct B : virtual A {
2603176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     virtual void f();
2604176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   };
2605176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2606176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Record layouts:
2607176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct A:
2608176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   0 |   (A vftable pointer)
2609176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   4 |   int x
2610176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2611176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct B:
2612176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   0 |   (B vbtable pointer)
2613176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   4 |   struct A (virtual base)
2614176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   4 |     (A vftable pointer)
2615176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   8 |     int x
2616176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2617176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Let's assume we have a pointer to the A part of an object of dynamic type B:
2618176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   B b;
2619176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   A *a = (A*)&b;
2620176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   a->f();
2621176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2622176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// In this hierarchy, f() belongs to the vftable of A, so B::f() expects
2623176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// "this" parameter to point at the A subobject, which is B+4.
2624176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// In the B::f() prologue, it adjusts "this" back to B by subtracting 4,
26250e2c34f92f00628d48968dfea096d36381f494cbStephen Hines// performed as a *static* adjustment.
2626176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2627176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Interesting thing happens when we alter the relative placement of A and B
2628176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// subobjects in a class:
2629176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct C : virtual B { };
2630176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2631176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   C c;
2632176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   A *a = (A*)&c;
2633176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   a->f();
2634176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2635176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Respective record layout is:
2636176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   0 |   (C vbtable pointer)
2637176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   4 |   struct A (virtual base)
2638176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   4 |     (A vftable pointer)
2639176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   8 |     int x
2640176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  12 |   struct B (virtual base)
2641176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  12 |     (B vbtable pointer)
2642176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2643176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// The final overrider of f() in class C is still B::f(), so B+4 should be
2644176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// passed as "this" to that code.  However, "a" points at B-8, so the respective
2645176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// vftable entry should hold a thunk that adds 12 to the "this" argument before
2646176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// performing a tail call to B::f().
2647176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2648176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// With this example in mind, we can now calculate the 'this' argument offset
2649176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// for the given method, relative to the beginning of the MostDerivedClass.
2650635de28950ef84ae26308ff734e778bad1ddde92Timur IskhodzhanovCharUnits
2651651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesVFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
265287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  BasesSetVectorTy Bases;
265387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
265487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  {
265587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    // Find the set of least derived bases that define the given method.
265687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    OverriddenMethodsSetTy VisitedOverriddenMethods;
265787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    auto InitialOverriddenDefinitionCollector = [&](
265887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        const CXXMethodDecl *OverriddenMD) {
265987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (OverriddenMD->size_overridden_methods() == 0)
266087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        Bases.insert(OverriddenMD->getParent());
266187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      // Don't recurse on this method if we've already collected it.
266287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      return VisitedOverriddenMethods.insert(OverriddenMD).second;
266387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    };
266487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    visitAllOverriddenMethods(Overrider.Method,
266587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                              InitialOverriddenDefinitionCollector);
266687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  }
2667651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
2668651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // If there are no overrides then 'this' is located
2669651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // in the base that defines the method.
267087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  if (Bases.size() == 0)
2671651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return Overrider.Offset;
2672635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2673635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  CXXBasePaths Paths;
267487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  Overrider.Method->getParent()->lookupInBases(
267587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      [&Bases](const CXXBaseSpecifier *Specifier, CXXBasePath &) {
267687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        return Bases.count(Specifier->getType()->getAsCXXRecordDecl());
267787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      },
267887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      Paths);
2679635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2680635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // This will hold the smallest this offset among overridees of MD.
2681635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // This implies that an offset of a non-virtual base will dominate an offset
2682635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // of a virtual base to potentially reduce the number of thunks required
2683635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // in the derived classes that inherit this method.
2684635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  CharUnits Ret;
2685635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  bool First = true;
2686635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
26876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  const ASTRecordLayout &OverriderRDLayout =
26886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      Context.getASTRecordLayout(Overrider.Method->getParent());
268987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const CXXBasePath &Path : Paths) {
2690651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    CharUnits ThisOffset = Overrider.Offset;
269158b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    CharUnits LastVBaseOffset;
2692635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2693b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    // For each path from the overrider to the parents of the overridden
2694b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    // methods, traverse the path, calculating the this offset in the most
2695b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    // derived class.
269687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    for (const CXXBasePathElement &Element : Path) {
2697635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      QualType CurTy = Element.Base->getType();
2698635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      const CXXRecordDecl *PrevRD = Element.Class,
2699635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                          *CurRD = CurTy->getAsCXXRecordDecl();
2700635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      const ASTRecordLayout &Layout = Context.getASTRecordLayout(PrevRD);
2701635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2702635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (Element.Base->isVirtual()) {
27036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // The interesting things begin when you have virtual inheritance.
27046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // The final overrider will use a static adjustment equal to the offset
27056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // of the vbase in the final overrider class.
27066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // For example, if the final overrider is in a vbase B of the most
27076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // derived class and it overrides a method of the B's own vbase A,
27086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // it uses A* as "this".  In its prologue, it can cast A* to B* with
27096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // a static offset.  This offset is used regardless of the actual
27106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // offset of A from B in the most derived class, requiring an
27116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // this-adjusting thunk in the vftable if A and B are laid out
27126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        // differently in the most derived class.
27136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        LastVBaseOffset = ThisOffset =
27146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines            Overrider.Offset + OverriderRDLayout.getVBaseClassOffset(CurRD);
2715635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      } else {
2716635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        ThisOffset += Layout.getBaseClassOffset(CurRD);
2717635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      }
2718635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
2719635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2720651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (isa<CXXDestructorDecl>(Overrider.Method)) {
272158b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      if (LastVBaseOffset.isZero()) {
272258b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov        // If a "Base" class has at least one non-virtual base with a virtual
272358b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov        // destructor, the "Base" virtual destructor will take the address
272458b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov        // of the "Base" subobject as the "this" argument.
2725651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        ThisOffset = Overrider.Offset;
272658b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      } else {
272758b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov        // A virtual destructor of a virtual base takes the address of the
272858b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov        // virtual base subobject as the "this" argument.
2729651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        ThisOffset = LastVBaseOffset;
273058b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      }
273158b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    }
273282552742a1002cf1408d6f371efc9cc6a9f2d7ccTimur Iskhodzhanov
2733635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    if (Ret > ThisOffset || First) {
2734635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      First = false;
2735635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Ret = ThisOffset;
2736635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
2737635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2738635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2739635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  assert(!First && "Method not found in the given subobject?");
2740635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  return Ret;
2741635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
2742635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2743176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Things are getting even more complex when the "this" adjustment has to
2744176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// use a dynamic offset instead of a static one, or even two dynamic offsets.
2745176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// This is sometimes required when a virtual call happens in the middle of
2746176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// a non-most-derived class construction or destruction.
2747176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2748176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Let's take a look at the following example:
2749176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct A {
2750176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     virtual void f();
2751176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   };
2752176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2753176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   void foo(A *a) { a->f(); }  // Knows nothing about siblings of A.
2754176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2755176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct B : virtual A {
2756176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     virtual void f();
2757176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     B() {
2758176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//       foo(this);
2759176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     }
2760176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   };
2761176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2762176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct C : virtual B {
2763176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     virtual void f();
2764176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   };
2765176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2766176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Record layouts for these classes are:
2767176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct A
2768176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   0 |   (A vftable pointer)
2769176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2770176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct B
2771176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   0 |   (B vbtable pointer)
2772176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   4 |   (vtordisp for vbase A)
2773176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   8 |   struct A (virtual base)
2774176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   8 |     (A vftable pointer)
2775176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2776176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct C
2777176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   0 |   (C vbtable pointer)
2778176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   4 |   (vtordisp for vbase A)
2779176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   8 |   struct A (virtual base)  // A precedes B!
2780176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   8 |     (A vftable pointer)
2781176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  12 |   struct B (virtual base)
2782176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  12 |     (B vbtable pointer)
2783176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2784176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// When one creates an object of type C, the C constructor:
2785176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// - initializes all the vbptrs, then
2786176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// - calls the A subobject constructor
2787176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   (initializes A's vfptr with an address of A vftable), then
2788176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// - calls the B subobject constructor
2789176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   (initializes A's vfptr with an address of B vftable and vtordisp for A),
2790176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   that in turn calls foo(), then
2791176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// - initializes A's vfptr with an address of C vftable and zeroes out the
2792176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   vtordisp
2793176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   FIXME: if a structor knows it belongs to MDC, why doesn't it use a vftable
2794176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   without vtordisp thunks?
2795176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   FIXME: how are vtordisp handled in the presence of nooverride/final?
2796176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2797176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// When foo() is called, an object with a layout of class C has a vftable
2798176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// referencing B::f() that assumes a B layout, so the "this" adjustments are
2799176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// incorrect, unless an extra adjustment is done.  This adjustment is called
2800176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// "vtordisp adjustment".  Vtordisp basically holds the difference between the
2801176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// actual location of a vbase in the layout class and the location assumed by
2802176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// the vftable of the class being constructed/destructed.  Vtordisp is only
2803176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// needed if "this" escapes a
2804176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// structor (or we can't prove otherwise).
2805176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// [i.e. vtordisp is a dynamic adjustment for a static adjustment, which is an
2806176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// estimation of a dynamic adjustment]
2807176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2808176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// foo() gets a pointer to the A vbase and doesn't know anything about B or C,
2809176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// so it just passes that pointer as "this" in a virtual call.
2810176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// If there was no vtordisp, that would just dispatch to B::f().
2811176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// However, B::f() assumes B+8 is passed as "this",
2812176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// yet the pointer foo() passes along is B-4 (i.e. C+8).
2813176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// An extra adjustment is needed, so we emit a thunk into the B vftable.
2814176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// This vtordisp thunk subtracts the value of vtordisp
2815176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// from the "this" argument (-12) before making a tailcall to B::f().
2816176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2817176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// Let's consider an even more complex example:
2818176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct D : virtual B, virtual C {
2819176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     D() {
2820176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//       foo(this);
2821176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//     }
2822176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   };
2823176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2824176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   struct D
2825176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   0 |   (D vbtable pointer)
2826176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   4 |   (vtordisp for vbase A)
2827176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   8 |   struct A (virtual base)  // A precedes both B and C!
2828176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   8 |     (A vftable pointer)
2829176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  12 |   struct B (virtual base)  // B precedes C!
2830176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  12 |     (B vbtable pointer)
2831176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  16 |   struct C (virtual base)
2832176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//  16 |     (C vbtable pointer)
2833176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
2834176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// When D::D() calls foo(), we find ourselves in a thunk that should tailcall
2835176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// to C::f(), which assumes C+8 as its "this" parameter.  This time, foo()
2836176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// passes along A, which is C-8.  The A vtordisp holds
2837176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//   "D.vbptr[index_of_A] - offset_of_A_in_D"
2838176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// and we statically know offset_of_A_in_D, so can get a pointer to D.
2839176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// When we know it, we can make an extra vbtable lookup to locate the C vbase
2840176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// and one extra static adjustment to calculate the expected value of C+8.
284158b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanovvoid VFTableBuilder::CalculateVtordispAdjustment(
284258b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    FinalOverriders::OverriderInfo Overrider, CharUnits ThisOffset,
284358b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    ThisAdjustment &TA) {
284458b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  const ASTRecordLayout::VBaseOffsetsMapTy &VBaseMap =
284558b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      MostDerivedClassLayout.getVBaseOffsetsMap();
284658b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2847651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      VBaseMap.find(WhichVFPtr.getVBaseWithVPtr());
284858b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  assert(VBaseMapEntry != VBaseMap.end());
284958b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov
28506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // If there's no vtordisp or the final overrider is defined in the same vbase
28516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // as the initial declaration, we don't need any vtordisp adjustment.
28526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (!VBaseMapEntry->second.hasVtorDisp() ||
28536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      Overrider.VirtualBase == WhichVFPtr.getVBaseWithVPtr())
285458b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    return;
285558b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov
28566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // OK, now we know we need to use a vtordisp thunk.
285758b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  // The implicit vtordisp field is located right before the vbase.
2858176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
285958b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  TA.Virtual.Microsoft.VtordispOffset =
2860176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      (OffsetOfVBaseWithVFPtr - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4;
286158b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov
28626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // A simple vtordisp thunk will suffice if the final overrider is defined
28636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // in either the most derived class or its non-virtual base.
28646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (Overrider.Method->getParent() == MostDerivedClass ||
28656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      !Overrider.VirtualBase)
286658b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    return;
286758b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov
286858b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  // Otherwise, we need to do use the dynamic offset of the final overrider
286958b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  // in order to get "this" adjustment right.
287058b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  TA.Virtual.Microsoft.VBPtrOffset =
2871176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      (OffsetOfVBaseWithVFPtr + WhichVFPtr.NonVirtualOffset -
287258b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov       MostDerivedClassLayout.getVBPtrOffset()).getQuantity();
287358b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  TA.Virtual.Microsoft.VBOffsetOffset =
287458b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      Context.getTypeSizeInChars(Context.IntTy).getQuantity() *
28756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      VTables.getVBTableIndex(MostDerivedClass, Overrider.VirtualBase);
287658b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov
287758b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov  TA.NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
287858b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov}
287958b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov
2880cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanovstatic void GroupNewVirtualOverloads(
2881cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov    const CXXRecordDecl *RD,
2882cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov    SmallVector<const CXXMethodDecl *, 10> &VirtualMethods) {
2883cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  // Put the virtual methods into VirtualMethods in the proper order:
2884cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  // 1) Group overloads by declaration name. New groups are added to the
2885cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  //    vftable in the order of their first declarations in this class
288687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  //    (including overrides, non-virtual methods and any other named decl that
288787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  //    might be nested within the class).
2888cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  // 2) In each group, new overloads appear in the reverse order of declaration.
2889cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  typedef SmallVector<const CXXMethodDecl *, 1> MethodGroup;
2890cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  SmallVector<MethodGroup, 10> Groups;
2891cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
2892cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  VisitedGroupIndicesTy VisitedGroupIndices;
289387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const auto *D : RD->decls()) {
289487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    const auto *ND = dyn_cast<NamedDecl>(D);
289587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    if (!ND)
289687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      continue;
2897cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov    VisitedGroupIndicesTy::iterator J;
2898cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov    bool Inserted;
2899651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    std::tie(J, Inserted) = VisitedGroupIndices.insert(
290087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        std::make_pair(ND->getDeclName(), Groups.size()));
2901cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov    if (Inserted)
2902651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Groups.push_back(MethodGroup());
290387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    if (const auto *MD = dyn_cast<CXXMethodDecl>(ND))
290487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (MD->isVirtual())
290587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        Groups[J->second].push_back(MD->getCanonicalDecl());
2906cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  }
2907cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov
290887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const MethodGroup &Group : Groups)
290987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    VirtualMethods.append(Group.rbegin(), Group.rend());
2910cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov}
2911cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov
2912651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool isDirectVBase(const CXXRecordDecl *Base, const CXXRecordDecl *RD) {
2913651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &B : RD->bases()) {
2914651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() == Base)
2915651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return true;
2916651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
2917651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return false;
2918651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
2919651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
2920635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovvoid VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
2921635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                                const CXXRecordDecl *LastVBase,
2922635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                                BasesSetVectorTy &VisitedBases) {
2923635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const CXXRecordDecl *RD = Base.getBase();
2924635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  if (!RD->isPolymorphic())
2925635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    return;
2926635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2927635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
2928635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2929635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // See if this class expands a vftable of the base we look at, which is either
2930b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  // the one defined by the vfptr base path or the primary base of the current
2931b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  // class.
29326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  const CXXRecordDecl *NextBase = nullptr, *NextLastVBase = LastVBase;
2933635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  CharUnits NextBaseOffset;
2934651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (BaseDepth < WhichVFPtr.PathToBaseWithVPtr.size()) {
2935651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    NextBase = WhichVFPtr.PathToBaseWithVPtr[BaseDepth];
2936651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (isDirectVBase(NextBase, RD)) {
2937635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      NextLastVBase = NextBase;
2938635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(NextBase);
2939635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    } else {
2940635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      NextBaseOffset =
2941635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          Base.getBaseOffset() + Layout.getBaseClassOffset(NextBase);
2942635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
2943635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  } else if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
2944635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    assert(!Layout.isPrimaryBaseVirtual() &&
2945635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov           "No primary virtual bases in this ABI");
2946635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    NextBase = PrimaryBase;
2947635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    NextBaseOffset = Base.getBaseOffset();
2948635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2949635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2950635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  if (NextBase) {
2951635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    AddMethods(BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
2952635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov               NextLastVBase, VisitedBases);
2953635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    if (!VisitedBases.insert(NextBase))
2954635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      llvm_unreachable("Found a duplicate primary base!");
2955635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
2956635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2957cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  SmallVector<const CXXMethodDecl*, 10> VirtualMethods;
2958cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  // Put virtual methods in the proper order.
2959cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov  GroupNewVirtualOverloads(RD, VirtualMethods);
2960cbf8dde9e39ab8e95477e3bdf4ee0d269fac0637Timur Iskhodzhanov
2961635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // Now go through all virtual member functions and add them to the current
2962635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // vftable. This is done by
2963635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  //  - replacing overridden methods in their existing slots, as long as they
2964635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  //    don't require return adjustment; calculating This adjustment if needed.
2965635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  //  - adding new slots for methods of the current base not present in any
2966635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  //    sub-bases;
2967635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  //  - adding new slots for methods that require Return adjustment.
2968635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // We keep track of the methods visited in the sub-bases in MethodInfoMap.
296987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const CXXMethodDecl *MD : VirtualMethods) {
2970176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    FinalOverriders::OverriderInfo FinalOverrider =
2971635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Overriders.getOverrider(MD, Base.getBaseOffset());
2972176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
2973651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXMethodDecl *OverriddenMD =
2974651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        FindNearestOverriddenMethod(MD, VisitedBases);
2975635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2976651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ThisAdjustment ThisAdjustmentOffset;
2977176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    bool ReturnAdjustingThunk = false, ForceReturnAdjustmentMangling = false;
2978176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
2979651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ThisAdjustmentOffset.NonVirtual =
2980651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        (ThisOffset - WhichVFPtr.FullOffsetInMDC).getQuantity();
2981176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if ((OverriddenMD || FinalOverriderMD != MD) &&
2982651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        WhichVFPtr.getVBaseWithVPtr())
2983176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
2984176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                  ThisAdjustmentOffset);
2985651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
2986651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (OverriddenMD) {
2987b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      // If MD overrides anything in this vftable, we need to update the
2988b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      // entries.
2989635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      MethodInfoMapTy::iterator OverriddenMDIterator =
2990635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          MethodInfoMap.find(OverriddenMD);
2991635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2992635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      // If the overridden method went to a different vftable, skip it.
2993635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (OverriddenMDIterator == MethodInfoMap.end())
2994635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        continue;
2995635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2996635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
2997635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
2998176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // Let's check if the overrider requires any return adjustments.
2999176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // We must create a new slot if the MD's return type is not trivially
3000176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // convertible to the OverriddenMD's one.
3001176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // Once a chain of method overrides adds a return adjusting vftable slot,
3002176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // all subsequent overrides will also use an extra method slot.
3003176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
3004176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                  Context, MD, OverriddenMD).isEmpty() ||
3005176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                             OverriddenMethodInfo.UsesExtraSlot;
3006176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
3007176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (!ReturnAdjustingThunk) {
3008635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        // No return adjustment needed - just replace the overridden method info
3009635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        // with the current info.
3010635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        MethodInfo MI(OverriddenMethodInfo.VBTableIndex,
3011635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                      OverriddenMethodInfo.VFTableIndex);
3012635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        MethodInfoMap.erase(OverriddenMDIterator);
3013635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3014635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        assert(!MethodInfoMap.count(MD) &&
3015635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov               "Should not have method info for this method yet!");
3016635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        MethodInfoMap.insert(std::make_pair(MD, MI));
3017635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        continue;
3018635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      }
3019651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3020651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // In case we need a return adjustment, we'll add a new slot for
3021651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // the overrider. Mark the overriden method as shadowed by the new slot.
3022651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      OverriddenMethodInfo.Shadowed = true;
3023651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3024651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // Force a special name mangling for a return-adjusting thunk
3025651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // unless the method is the final overrider without this adjustment.
3026176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      ForceReturnAdjustmentMangling =
3027176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          !(MD == FinalOverriderMD && ThisAdjustmentOffset.isEmpty());
3028651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    } else if (Base.getBaseOffset() != WhichVFPtr.FullOffsetInMDC ||
3029635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov               MD->size_overridden_methods()) {
3030635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      // Skip methods that don't belong to the vftable of the current class,
3031635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      // e.g. each method that wasn't seen in any of the visited sub-bases
3032635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      // but overrides multiple methods of other sub-bases.
3033635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      continue;
3034635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3035635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3036635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // If we got here, MD is a method not seen in any of the sub-bases or
3037635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // it requires return adjustment. Insert the method info for this method.
3038635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    unsigned VBIndex =
30395f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov        LastVBase ? VTables.getVBTableIndex(MostDerivedClass, LastVBase) : 0;
3040c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    MethodInfo MI(VBIndex,
3041176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                  HasRTTIComponent ? Components.size() - 1 : Components.size(),
3042176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                  ReturnAdjustingThunk);
3043635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3044635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    assert(!MethodInfoMap.count(MD) &&
3045635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov           "Should not have method info for this method yet!");
3046635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    MethodInfoMap.insert(std::make_pair(MD, MI));
3047635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3048635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // Check if this overrider needs a return adjustment.
3049635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // We don't want to do this for pure virtual member functions.
3050635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    BaseOffset ReturnAdjustmentOffset;
3051635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    ReturnAdjustment ReturnAdjustment;
3052176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (!FinalOverriderMD->isPure()) {
3053635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      ReturnAdjustmentOffset =
3054176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          ComputeReturnAdjustmentBaseOffset(Context, FinalOverriderMD, MD);
3055635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3056635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    if (!ReturnAdjustmentOffset.isEmpty()) {
3057176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      ForceReturnAdjustmentMangling = true;
3058635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      ReturnAdjustment.NonVirtual =
3059635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          ReturnAdjustmentOffset.NonVirtualOffset.getQuantity();
3060635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (ReturnAdjustmentOffset.VirtualBase) {
3061c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov        const ASTRecordLayout &DerivedLayout =
3062c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov            Context.getASTRecordLayout(ReturnAdjustmentOffset.DerivedClass);
3063c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov        ReturnAdjustment.Virtual.Microsoft.VBPtrOffset =
3064c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov            DerivedLayout.getVBPtrOffset().getQuantity();
3065c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov        ReturnAdjustment.Virtual.Microsoft.VBIndex =
30665f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov            VTables.getVBTableIndex(ReturnAdjustmentOffset.DerivedClass,
30675f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov                                    ReturnAdjustmentOffset.VirtualBase);
3068635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      }
3069635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3070635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3071176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    AddMethod(FinalOverriderMD,
3072176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines              ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment,
3073176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                        ForceReturnAdjustmentMangling ? MD : nullptr));
3074635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
3075635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3076635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3077651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void PrintBasePath(const VPtrInfo::BasePath &Path, raw_ostream &Out) {
307887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const CXXRecordDecl *Elem :
307987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar       llvm::make_range(Path.rbegin(), Path.rend())) {
3080651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Out << "'";
308187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    Elem->printQualifiedName(Out);
3082651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Out << "' in ";
3083635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
3084635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3085635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3086c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanovstatic void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out,
3087c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov                                         bool ContinueFirstLine) {
3088c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov  const ReturnAdjustment &R = TI.Return;
3089c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov  bool Multiline = false;
3090651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const char *LinePrefix = "\n       ";
3091651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (!R.isEmpty() || TI.Method) {
3092c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov    if (!ContinueFirstLine)
3093c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov      Out << LinePrefix;
3094651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Out << "[return adjustment (to type '"
3095651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        << TI.Method->getReturnType().getCanonicalType().getAsString()
3096651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        << "'): ";
3097c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov    if (R.Virtual.Microsoft.VBPtrOffset)
3098c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov      Out << "vbptr at offset " << R.Virtual.Microsoft.VBPtrOffset << ", ";
3099c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov    if (R.Virtual.Microsoft.VBIndex)
3100c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov      Out << "vbase #" << R.Virtual.Microsoft.VBIndex << ", ";
3101c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov    Out << R.NonVirtual << " non-virtual]";
3102c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov    Multiline = true;
3103c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov  }
3104c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov
3105c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov  const ThisAdjustment &T = TI.This;
3106c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov  if (!T.isEmpty()) {
3107c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov    if (Multiline || !ContinueFirstLine)
3108c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov      Out << LinePrefix;
3109c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov    Out << "[this adjustment: ";
311058b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    if (!TI.This.Virtual.isEmpty()) {
311158b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      assert(T.Virtual.Microsoft.VtordispOffset < 0);
311258b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      Out << "vtordisp at " << T.Virtual.Microsoft.VtordispOffset << ", ";
311358b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      if (T.Virtual.Microsoft.VBPtrOffset) {
311458b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov        Out << "vbptr at " << T.Virtual.Microsoft.VBPtrOffset
3115651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            << " to the left,";
311658b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov        assert(T.Virtual.Microsoft.VBOffsetOffset > 0);
311758b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov        Out << LinePrefix << " vboffset at "
311858b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov            << T.Virtual.Microsoft.VBOffsetOffset << " in the vbtable, ";
311958b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov      }
312058b6db76adab8dee2e64fbc300360f9b46c561baTimur Iskhodzhanov    }
3121c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov    Out << T.NonVirtual << " non-virtual]";
3122c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov  }
3123c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov}
3124c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov
3125635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovvoid VFTableBuilder::dumpLayout(raw_ostream &Out) {
3126635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  Out << "VFTable for ";
3127651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  PrintBasePath(WhichVFPtr.PathToBaseWithVPtr, Out);
3128651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Out << "'";
3129651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  MostDerivedClass->printQualifiedName(Out);
3130651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Out << "' (" << Components.size()
3131651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      << (Components.size() == 1 ? " entry" : " entries") << ").\n";
3132635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3133635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  for (unsigned I = 0, E = Components.size(); I != E; ++I) {
3134635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    Out << llvm::format("%4d | ", I);
3135635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3136635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    const VTableComponent &Component = Components[I];
3137635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3138635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // Dump the component.
3139635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    switch (Component.getKind()) {
3140635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    case VTableComponent::CK_RTTI:
3141651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Component.getRTTIDecl()->printQualifiedName(Out);
3142651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Out << " RTTI";
3143635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      break;
3144635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3145635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    case VTableComponent::CK_FunctionPointer: {
3146635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      const CXXMethodDecl *MD = Component.getFunctionDecl();
3147635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3148651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // FIXME: Figure out how to print the real thunk type, since they can
3149651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // differ in the return type.
3150635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      std::string Str = PredefinedExpr::ComputeName(
3151635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          PredefinedExpr::PrettyFunctionNoVirtual, MD);
3152635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Out << Str;
3153635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (MD->isPure())
3154635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Out << " [pure]";
3155635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3156176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (MD->isDeleted())
3157635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Out << " [deleted]";
3158635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3159635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      ThunkInfo Thunk = VTableThunks.lookup(I);
3160c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov      if (!Thunk.isEmpty())
3161c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov        dumpMicrosoftThunkAdjustment(Thunk, Out, /*ContinueFirstLine=*/false);
3162635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3163635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      break;
3164635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3165635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3166635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    case VTableComponent::CK_DeletingDtorPointer: {
3167635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      const CXXDestructorDecl *DD = Component.getDestructorDecl();
3168635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3169651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      DD->printQualifiedName(Out);
3170635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Out << "() [scalar deleting]";
3171635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3172635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (DD->isPure())
3173635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Out << " [pure]";
3174635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3175635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      ThunkInfo Thunk = VTableThunks.lookup(I);
3176635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (!Thunk.isEmpty()) {
3177635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        assert(Thunk.Return.isEmpty() &&
3178635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov               "No return adjustment needed for destructors!");
3179c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov        dumpMicrosoftThunkAdjustment(Thunk, Out, /*ContinueFirstLine=*/false);
3180635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      }
3181635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3182635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      break;
3183635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3184635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3185635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    default:
3186635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      DiagnosticsEngine &Diags = Context.getDiagnostics();
3187635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      unsigned DiagID = Diags.getCustomDiagID(
3188635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          DiagnosticsEngine::Error,
3189635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          "Unexpected vftable component type %0 for component number %1");
3190635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Diags.Report(MostDerivedClass->getLocation(), DiagID)
3191635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          << I << Component.getKind();
3192635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3193635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3194635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    Out << '\n';
3195635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
3196635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3197635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  Out << '\n';
3198635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3199635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  if (!Thunks.empty()) {
3200635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    // We store the method names in a map to get a stable order.
3201635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3202635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
320387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    for (const auto &I : Thunks) {
320487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const CXXMethodDecl *MD = I.first;
3205635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      std::string MethodName = PredefinedExpr::ComputeName(
3206635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          PredefinedExpr::PrettyFunctionNoVirtual, MD);
3207635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3208635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3209635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3210635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
321187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    for (const auto &MethodNameAndDecl : MethodNamesAndDecls) {
321287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const std::string &MethodName = MethodNameAndDecl.first;
321387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const CXXMethodDecl *MD = MethodNameAndDecl.second;
3214635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3215635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      ThunkInfoVectorTy ThunksVector = Thunks[MD];
32162cb17a06befb61b1434aaa991652fea4338c95d7Timur Iskhodzhanov      std::stable_sort(ThunksVector.begin(), ThunksVector.end(),
3217651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                       [](const ThunkInfo &LHS, const ThunkInfo &RHS) {
3218651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        // Keep different thunks with the same adjustments in the order they
3219651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        // were put into the vector.
3220651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return);
3221651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      });
3222635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3223635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size();
3224635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n";
3225635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3226635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      for (unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
3227635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        const ThunkInfo &Thunk = ThunksVector[I];
3228635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3229635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Out << llvm::format("%4d | ", I);
3230c70cc5d90403f99ccce5cab3a6c022ad9cdcb66cTimur Iskhodzhanov        dumpMicrosoftThunkAdjustment(Thunk, Out, /*ContinueFirstLine=*/true);
3231635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Out << '\n';
3232635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      }
3233635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3234635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Out << '\n';
3235635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3236635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
3237651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3238651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Out.flush();
3239635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3240635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3241651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool setsIntersect(const llvm::SmallPtrSet<const CXXRecordDecl *, 4> &A,
3242176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                          ArrayRef<const CXXRecordDecl *> B) {
324387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const CXXRecordDecl *Decl : B) {
324487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    if (A.count(Decl))
3245651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return true;
3246635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
3247651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return false;
3248651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
3249635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3250651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool rebucketPaths(VPtrInfoVector &Paths);
3251635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3252651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// Produces MSVC-compatible vbtable data.  The symbols produced by this
3253651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// algorithm match those produced by MSVC 2012 and newer, which is different
3254651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// from MSVC 2010.
3255651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines///
3256651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// MSVC 2012 appears to minimize the vbtable names using the following
3257651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// algorithm.  First, walk the class hierarchy in the usual order, depth first,
3258651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// left to right, to find all of the subobjects which contain a vbptr field.
3259651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// Visiting each class node yields a list of inheritance paths to vbptrs.  Each
3260651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// record with a vbptr creates an initially empty path.
3261651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines///
3262651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// To combine paths from child nodes, the paths are compared to check for
3263651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// ambiguity.  Paths are "ambiguous" if multiple paths have the same set of
3264651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// components in the same order.  Each group of ambiguous paths is extended by
3265651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// appending the class of the base from which it came.  If the current class
3266651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// node produced an ambiguous path, its path is extended with the current class.
3267651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// After extending paths, MSVC again checks for ambiguity, and extends any
3268651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// ambiguous path which wasn't already extended.  Because each node yields an
3269651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// unambiguous set of paths, MSVC doesn't need to extend any path more than once
3270651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// to produce an unambiguous set of paths.
3271651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines///
3272651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// TODO: Presumably vftables use the same algorithm.
3273651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid MicrosoftVTableContext::computeVTablePaths(bool ForVBTables,
3274651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                                const CXXRecordDecl *RD,
3275651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                                VPtrInfoVector &Paths) {
3276651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  assert(Paths.empty());
3277651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3278635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3279651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Base case: this subobject has its own vptr.
3280651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (ForVBTables ? Layout.hasOwnVBPtr() : Layout.hasOwnVFPtr())
3281651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Paths.push_back(new VPtrInfo(RD));
3282635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3283651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Recursive case: get all the vbtables from our bases and remove anything
3284651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // that shares a virtual base.
3285651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
3286651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &B : RD->bases()) {
3287651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
3288651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (B.isVirtual() && VBasesSeen.count(Base))
3289651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      continue;
3290635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3291651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!Base->isDynamicClass())
3292651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      continue;
3293651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3294651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const VPtrInfoVector &BasePaths =
3295651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        ForVBTables ? enumerateVBTables(Base) : getVFPtrOffsets(Base);
3296a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov
32976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    for (VPtrInfo *BaseInfo : BasePaths) {
3298651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // Don't include the path if it goes through a virtual base that we've
3299651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // already included.
3300651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (setsIntersect(VBasesSeen, BaseInfo->ContainingVBases))
3301651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        continue;
3302a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov
3303651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // Copy the path and adjust it as necessary.
3304651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      VPtrInfo *P = new VPtrInfo(*BaseInfo);
3305651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3306651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // We mangle Base into the path if the path would've been ambiguous and it
3307651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // wasn't already extended with Base.
3308651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (P->MangledPath.empty() || P->MangledPath.back() != Base)
3309651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        P->NextBaseToMangle = Base;
3310651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
33116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      // Keep track of which vtable the derived class is going to extend with
33126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      // new methods or bases.  We append to either the vftable of our primary
33136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      // base, or the first non-virtual base that has a vbtable.
33146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (P->ReusingBase == Base &&
33156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          Base == (ForVBTables ? Layout.getBaseSharingVBPtr()
3316651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                               : Layout.getPrimaryBase()))
3317651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        P->ReusingBase = RD;
33186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
33196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      // Keep track of the full adjustment from the MDC to this vtable.  The
33206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      // adjustment is captured by an optional vbase and a non-virtual offset.
3321651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (B.isVirtual())
3322651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        P->ContainingVBases.push_back(Base);
3323651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      else if (P->ContainingVBases.empty())
3324651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        P->NonVirtualOffset += Layout.getBaseClassOffset(Base);
3325651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3326651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // Update the full offset in the MDC.
3327651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      P->FullOffsetInMDC = P->NonVirtualOffset;
3328651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (const CXXRecordDecl *VB = P->getVBaseWithVPtr())
3329651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        P->FullOffsetInMDC += Layout.getVBaseClassOffset(VB);
3330651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3331651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Paths.push_back(P);
3332a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov    }
3333651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3334651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (B.isVirtual())
3335651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      VBasesSeen.insert(Base);
3336651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3337651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // After visiting any direct base, we've transitively visited all of its
3338651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // morally virtual bases.
3339651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (const auto &VB : Base->vbases())
3340651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3341a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov  }
3342a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov
3343651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Sort the paths into buckets, and if any of them are ambiguous, extend all
3344651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // paths in ambiguous buckets.
3345651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool Changed = true;
3346651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  while (Changed)
3347651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Changed = rebucketPaths(Paths);
3348651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
3349a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov
3350651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool extendPath(VPtrInfo *P) {
3351651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (P->NextBaseToMangle) {
3352651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    P->MangledPath.push_back(P->NextBaseToMangle);
33536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    P->NextBaseToMangle = nullptr;// Prevent the path from being extended twice.
3354651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return true;
3355a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov  }
3356651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return false;
3357a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov}
3358a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov
3359651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool rebucketPaths(VPtrInfoVector &Paths) {
3360651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // What we're essentially doing here is bucketing together ambiguous paths.
3361651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Any bucket with more than one path in it gets extended by NextBase, which
3362651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // is usually the direct base of the inherited the vbptr.  This code uses a
3363651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // sorted vector to implement a multiset to form the buckets.  Note that the
3364651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // ordering is based on pointers, but it doesn't change our output order.  The
3365651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // current algorithm is designed to match MSVC 2012's names.
3366651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  VPtrInfoVector PathsSorted(Paths);
3367651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::sort(PathsSorted.begin(), PathsSorted.end(),
3368651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            [](const VPtrInfo *LHS, const VPtrInfo *RHS) {
3369651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return LHS->MangledPath < RHS->MangledPath;
3370651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  });
3371651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool Changed = false;
3372651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (size_t I = 0, E = PathsSorted.size(); I != E;) {
3373651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // Scan forward to find the end of the bucket.
3374651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    size_t BucketStart = I;
3375651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    do {
3376651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      ++I;
3377651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    } while (I != E && PathsSorted[BucketStart]->MangledPath ==
3378651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                           PathsSorted[I]->MangledPath);
3379651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3380651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // If this bucket has multiple paths, extend them all.
3381651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (I - BucketStart > 1) {
3382651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      for (size_t II = BucketStart; II != I; ++II)
3383651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        Changed |= extendPath(PathsSorted[II]);
3384651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      assert(Changed && "no paths were extended to fix ambiguity");
3385651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
3386a53d7a0259ff88f78ba8ecac7d0cb3ea96302b1dTimur Iskhodzhanov  }
3387651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return Changed;
3388651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
3389651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3390651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesMicrosoftVTableContext::~MicrosoftVTableContext() {
33916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (auto &P : VFPtrLocations)
33926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    llvm::DeleteContainerPointers(*P.second);
3393651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::DeleteContainerSeconds(VFPtrLocations);
3394651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::DeleteContainerSeconds(VFTableLayouts);
3395651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::DeleteContainerSeconds(VBaseInfo);
3396635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3397635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3398b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainarnamespace {
3399b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainartypedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
3400b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                        llvm::DenseSet<BaseSubobject>> FullPathTy;
3401b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar}
3402b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar
3403b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar// This recursive function finds all paths from a subobject centered at
3404b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar// (RD, Offset) to the subobject located at BaseWithVPtr.
3405b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainarstatic void findPathsToSubobject(ASTContext &Context,
3406b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                                 const ASTRecordLayout &MostDerivedLayout,
3407b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                                 const CXXRecordDecl *RD, CharUnits Offset,
3408b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                                 BaseSubobject BaseWithVPtr,
3409b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                                 FullPathTy &FullPath,
3410b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                                 std::list<FullPathTy> &Paths) {
3411b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  if (BaseSubobject(RD, Offset) == BaseWithVPtr) {
3412b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    Paths.push_back(FullPath);
3413b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    return;
3414176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
3415176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
3416176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3417176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
3418b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  for (const CXXBaseSpecifier &BS : RD->bases()) {
3419b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    const CXXRecordDecl *Base = BS.getType()->getAsCXXRecordDecl();
3420b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    CharUnits NewOffset = BS.isVirtual()
3421b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                              ? MostDerivedLayout.getVBaseClassOffset(Base)
3422b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                              : Offset + Layout.getBaseClassOffset(Base);
3423b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    FullPath.insert(BaseSubobject(Base, NewOffset));
3424b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    findPathsToSubobject(Context, MostDerivedLayout, Base, NewOffset,
3425b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                         BaseWithVPtr, FullPath, Paths);
3426b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    FullPath.pop_back();
3427b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  }
3428b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar}
3429176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
3430b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar// Return the paths which are not subsets of other paths.
3431b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainarstatic void removeRedundantPaths(std::list<FullPathTy> &FullPaths) {
3432b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  FullPaths.remove_if([&](const FullPathTy &SpecificPath) {
3433b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    for (const FullPathTy &OtherPath : FullPaths) {
3434b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      if (&SpecificPath == &OtherPath)
3435b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar        continue;
3436b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      if (std::all_of(SpecificPath.begin(), SpecificPath.end(),
3437b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                      [&](const BaseSubobject &BSO) {
3438b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                        return OtherPath.count(BSO) != 0;
3439b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                      })) {
3440b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar        return true;
3441b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      }
3442b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    }
3443b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    return false;
3444b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  });
3445b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar}
3446b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar
3447b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainarstatic CharUnits getOffsetOfFullPath(ASTContext &Context,
3448b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                                     const CXXRecordDecl *RD,
3449b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                                     const FullPathTy &FullPath) {
3450b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  const ASTRecordLayout &MostDerivedLayout =
3451b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      Context.getASTRecordLayout(RD);
3452b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  CharUnits Offset = CharUnits::fromQuantity(-1);
3453b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  for (const BaseSubobject &BSO : FullPath) {
3454b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    const CXXRecordDecl *Base = BSO.getBase();
3455b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    // The first entry in the path is always the most derived record, skip it.
3456b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    if (Base == RD) {
3457b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      assert(Offset.getQuantity() == -1);
3458b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      Offset = CharUnits::Zero();
3459b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      continue;
3460b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    }
3461b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    assert(Offset.getQuantity() != -1);
3462b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3463b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    // While we know which base has to be traversed, we don't know if that base
3464b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    // was a virtual base.
3465b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    const CXXBaseSpecifier *BaseBS = std::find_if(
3466b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar        RD->bases_begin(), RD->bases_end(), [&](const CXXBaseSpecifier &BS) {
3467b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar          return BS.getType()->getAsCXXRecordDecl() == Base;
3468b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar        });
3469b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    Offset = BaseBS->isVirtual() ? MostDerivedLayout.getVBaseClassOffset(Base)
3470b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                                 : Offset + Layout.getBaseClassOffset(Base);
3471b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    RD = Base;
3472b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  }
3473b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  return Offset;
3474b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar}
3475b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar
3476b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar// We want to select the path which introduces the most covariant overrides.  If
3477b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar// two paths introduce overrides which the other path doesn't contain, issue a
3478b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar// diagnostic.
3479b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainarstatic const FullPathTy *selectBestPath(ASTContext &Context,
3480b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                                        const CXXRecordDecl *RD, VPtrInfo *Info,
3481b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                                        std::list<FullPathTy> &FullPaths) {
3482b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  // Handle some easy cases first.
3483b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  if (FullPaths.empty())
3484b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    return nullptr;
3485b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  if (FullPaths.size() == 1)
3486b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    return &FullPaths.front();
3487b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar
3488b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  const FullPathTy *BestPath = nullptr;
3489b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  typedef std::set<const CXXMethodDecl *> OverriderSetTy;
3490b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  OverriderSetTy LastOverrides;
3491b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  for (const FullPathTy &SpecificPath : FullPaths) {
3492b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    assert(!SpecificPath.empty());
3493b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    OverriderSetTy CurrentOverrides;
3494b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
3495b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    // Find the distance from the start of the path to the subobject with the
3496b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    // VPtr.
3497b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    CharUnits BaseOffset =
3498b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar        getOffsetOfFullPath(Context, TopLevelRD, SpecificPath);
3499b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    FinalOverriders Overriders(TopLevelRD, CharUnits::Zero(), TopLevelRD);
3500b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    for (const CXXMethodDecl *MD : Info->BaseWithVPtr->methods()) {
3501b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      if (!MD->isVirtual())
3502b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar        continue;
3503b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      FinalOverriders::OverriderInfo OI =
3504b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar          Overriders.getOverrider(MD->getCanonicalDecl(), BaseOffset);
3505b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      const CXXMethodDecl *OverridingMethod = OI.Method;
3506b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      // Only overriders which have a return adjustment introduce problematic
3507b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      // thunks.
3508b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
3509b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar              .isEmpty())
3510b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar        continue;
3511b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      // It's possible that the overrider isn't in this path.  If so, skip it
3512b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      // because this path didn't introduce it.
3513b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      const CXXRecordDecl *OverridingParent = OverridingMethod->getParent();
3514b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      if (std::none_of(SpecificPath.begin(), SpecificPath.end(),
3515b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                       [&](const BaseSubobject &BSO) {
3516b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                         return BSO.getBase() == OverridingParent;
3517b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                       }))
3518b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar        continue;
3519b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      CurrentOverrides.insert(OverridingMethod);
3520b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    }
3521b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    OverriderSetTy NewOverrides =
3522b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar        llvm::set_difference(CurrentOverrides, LastOverrides);
3523b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    if (NewOverrides.empty())
3524b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      continue;
3525b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    OverriderSetTy MissingOverrides =
3526b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar        llvm::set_difference(LastOverrides, CurrentOverrides);
3527b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    if (MissingOverrides.empty()) {
3528b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      // This path is a strict improvement over the last path, let's use it.
3529b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      BestPath = &SpecificPath;
3530b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      std::swap(CurrentOverrides, LastOverrides);
3531b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    } else {
3532b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      // This path introduces an overrider with a conflicting covariant thunk.
3533b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      DiagnosticsEngine &Diags = Context.getDiagnostics();
3534b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      const CXXMethodDecl *CovariantMD = *NewOverrides.begin();
3535b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
3536b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      Diags.Report(RD->getLocation(), diag::err_vftable_ambiguous_component)
3537b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar          << RD;
3538b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      Diags.Report(CovariantMD->getLocation(), diag::note_covariant_thunk)
3539b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar          << CovariantMD;
3540b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      Diags.Report(ConflictMD->getLocation(), diag::note_covariant_thunk)
3541b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar          << ConflictMD;
3542176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
3543176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
3544b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  // Go with the path that introduced the most covariant overrides.  If there is
3545b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  // no such path, pick the first path.
3546b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  return BestPath ? BestPath : &FullPaths.front();
3547176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
3548176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
3549176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstatic void computeFullPathsForVFTables(ASTContext &Context,
3550176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                        const CXXRecordDecl *RD,
3551176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                        VPtrInfoVector &Paths) {
3552176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  const ASTRecordLayout &MostDerivedLayout = Context.getASTRecordLayout(RD);
3553b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  FullPathTy FullPath;
3554b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  std::list<FullPathTy> FullPaths;
3555176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  for (VPtrInfo *Info : Paths) {
3556b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    findPathsToSubobject(
3557b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar        Context, MostDerivedLayout, RD, CharUnits::Zero(),
3558b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar        BaseSubobject(Info->BaseWithVPtr, Info->FullOffsetInMDC), FullPath,
3559b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar        FullPaths);
3560176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    FullPath.clear();
3561b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    removeRedundantPaths(FullPaths);
3562b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    Info->PathToBaseWithVPtr.clear();
3563b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    if (const FullPathTy *BestPath =
3564b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar            selectBestPath(Context, RD, Info, FullPaths))
3565b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      for (const BaseSubobject &BSO : *BestPath)
3566b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar        Info->PathToBaseWithVPtr.push_back(BSO.getBase());
3567b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    FullPaths.clear();
3568176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
3569176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
3570176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
35715f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanovvoid MicrosoftVTableContext::computeVTableRelatedInformation(
3572635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    const CXXRecordDecl *RD) {
3573635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  assert(RD->isDynamicClass());
3574635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3575635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // Check if we've computed this information before.
3576635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  if (VFPtrLocations.count(RD))
3577635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    return;
3578635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3579635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const VTableLayout::AddressPointsMapTy EmptyAddressPointsMap;
3580635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3581651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  VPtrInfoVector *VFPtrs = new VPtrInfoVector();
3582651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  computeVTablePaths(/*ForVBTables=*/false, RD, *VFPtrs);
3583176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  computeFullPathsForVFTables(Context, RD, *VFPtrs);
3584651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  VFPtrLocations[RD] = VFPtrs;
3585635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3586635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  MethodVFTableLocationsTy NewMethodLocations;
358787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const VPtrInfo *VFPtr : *VFPtrs) {
358887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    VFTableBuilder Builder(*this, RD, VFPtr);
3589635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
359087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    VFTableIdTy id(RD, VFPtr->FullOffsetInMDC);
3591635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    assert(VFTableLayouts.count(id) == 0);
3592635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks(
3593635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
3594635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    VFTableLayouts[id] = new VTableLayout(
3595635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Builder.getNumVTableComponents(), Builder.vtable_component_begin(),
3596635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        VTableThunks.size(), VTableThunks.data(), EmptyAddressPointsMap, true);
3597635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
3598651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3599651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (const auto &Loc : Builder.vtable_locations()) {
3600651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      GlobalDecl GD = Loc.first;
3601651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      MethodVFTableLocation NewLoc = Loc.second;
3602651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      auto M = NewMethodLocations.find(GD);
3603651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (M == NewMethodLocations.end() || NewLoc < M->second)
3604651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        NewMethodLocations[GD] = NewLoc;
3605651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
3606635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
3607635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3608635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  MethodVFTableLocations.insert(NewMethodLocations.begin(),
3609635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov                                NewMethodLocations.end());
3610635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  if (Context.getLangOpts().DumpVTableLayouts)
3611152eee9f81f1b4f00e1bce655903fc78cafb1342Reid Kleckner    dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3612635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3613635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
36145f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanovvoid MicrosoftVTableContext::dumpMethodLocations(
3615635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    const CXXRecordDecl *RD, const MethodVFTableLocationsTy &NewMethods,
3616635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    raw_ostream &Out) {
3617635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // Compute the vtable indices for all the member functions.
3618635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // Store them in a map keyed by the location so we'll get a sorted table.
3619635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  std::map<MethodVFTableLocation, std::string> IndicesMap;
3620635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  bool HasNonzeroOffset = false;
3621635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
362287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (const auto &I : NewMethods) {
362387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    const CXXMethodDecl *MD = cast<const CXXMethodDecl>(I.first.getDecl());
3624635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    assert(MD->isVirtual());
3625635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3626635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    std::string MethodName = PredefinedExpr::ComputeName(
3627635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        PredefinedExpr::PrettyFunctionNoVirtual, MD);
3628635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3629635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    if (isa<CXXDestructorDecl>(MD)) {
363087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      IndicesMap[I.second] = MethodName + " [scalar deleting]";
3631635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    } else {
363287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      IndicesMap[I.second] = MethodName;
3633635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3634635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
363587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    if (!I.second.VFPtrOffset.isZero() || I.second.VBTableIndex != 0)
3636635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      HasNonzeroOffset = true;
3637635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
3638635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3639635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  // Print the vtable indices for all the member functions.
3640635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  if (!IndicesMap.empty()) {
3641635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    Out << "VFTable indices for ";
3642651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Out << "'";
3643651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    RD->printQualifiedName(Out);
3644651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Out << "' (" << IndicesMap.size()
3645651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        << (IndicesMap.size() == 1 ? " entry" : " entries") << ").\n";
3646635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3647635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    CharUnits LastVFPtrOffset = CharUnits::fromQuantity(-1);
3648635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    uint64_t LastVBIndex = 0;
364987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    for (const auto &I : IndicesMap) {
365087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      CharUnits VFPtrOffset = I.first.VFPtrOffset;
365187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      uint64_t VBIndex = I.first.VBTableIndex;
3652635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      if (HasNonzeroOffset &&
3653635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3654635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3655635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Out << " -- accessible via ";
3656635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        if (VBIndex)
3657635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov          Out << "vbtable index " << VBIndex << ", ";
3658635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        Out << "vfptr at offset " << VFPtrOffset.getQuantity() << " --\n";
3659635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        LastVFPtrOffset = VFPtrOffset;
3660635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov        LastVBIndex = VBIndex;
3661635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      }
3662635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
366387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      uint64_t VTableIndex = I.first.Index;
366487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const std::string &MethodName = I.second;
3665635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov      Out << llvm::format("%4" PRIu64 " | ", VTableIndex) << MethodName << '\n';
3666635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    }
3667635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    Out << '\n';
3668635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  }
3669651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3670651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Out.flush();
3671635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3672635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3673651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesconst VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation(
36745f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov    const CXXRecordDecl *RD) {
3675651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  VirtualBaseInfo *VBI;
36765f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov
3677651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  {
3678651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // Get or create a VBI for RD.  Don't hold a reference to the DenseMap cell,
3679651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // as it may be modified and rehashed under us.
3680651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    VirtualBaseInfo *&Entry = VBaseInfo[RD];
3681651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (Entry)
3682651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return Entry;
3683651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Entry = VBI = new VirtualBaseInfo();
3684651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
3685651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3686651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  computeVTablePaths(/*ForVBTables=*/true, RD, VBI->VBPtrPaths);
36875f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov
36886acb04f755cfc73d05772457d70aeb5adfaf6d8fTimur Iskhodzhanov  // First, see if the Derived class shared the vbptr with a non-virtual base.
3689651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
36906acb04f755cfc73d05772457d70aeb5adfaf6d8fTimur Iskhodzhanov  if (const CXXRecordDecl *VBPtrBase = Layout.getBaseSharingVBPtr()) {
3691651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // If the Derived class shares the vbptr with a non-virtual base, the shared
3692651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // virtual bases come first so that the layout is the same.
3693651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const VirtualBaseInfo *BaseInfo =
3694651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        computeVBTableRelatedInformation(VBPtrBase);
3695651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    VBI->VBTableIndices.insert(BaseInfo->VBTableIndices.begin(),
3696651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                               BaseInfo->VBTableIndices.end());
36975f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov  }
36985f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov
36995f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov  // New vbases are added to the end of the vbtable.
37005f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov  // Skip the self entry and vbases visited in the non-virtual base, if any.
3701651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  unsigned VBTableIndex = 1 + VBI->VBTableIndices.size();
3702651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &VB : RD->vbases()) {
3703651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3704651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!VBI->VBTableIndices.count(CurVBase))
3705651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      VBI->VBTableIndices[CurVBase] = VBTableIndex++;
37065f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov  }
3707651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3708651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return VBI;
3709651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
3710651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3711651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesunsigned MicrosoftVTableContext::getVBTableIndex(const CXXRecordDecl *Derived,
3712651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                                 const CXXRecordDecl *VBase) {
3713651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const VirtualBaseInfo *VBInfo = computeVBTableRelatedInformation(Derived);
3714651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  assert(VBInfo->VBTableIndices.count(VBase));
3715651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return VBInfo->VBTableIndices.find(VBase)->second;
3716651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
3717651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3718651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesconst VPtrInfoVector &
3719651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesMicrosoftVTableContext::enumerateVBTables(const CXXRecordDecl *RD) {
3720651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return computeVBTableRelatedInformation(RD)->VBPtrPaths;
37215f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov}
37225f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov
3723651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesconst VPtrInfoVector &
37245f0db587078b5af32fc9ac41fe4276b80918fd8dTimur IskhodzhanovMicrosoftVTableContext::getVFPtrOffsets(const CXXRecordDecl *RD) {
3725635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  computeVTableRelatedInformation(RD);
3726635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3727635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  assert(VFPtrLocations.count(RD) && "Couldn't find vfptr locations");
3728651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return *VFPtrLocations[RD];
3729635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3730635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3731635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanovconst VTableLayout &
37325f0db587078b5af32fc9ac41fe4276b80918fd8dTimur IskhodzhanovMicrosoftVTableContext::getVFTableLayout(const CXXRecordDecl *RD,
37335f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanov                                         CharUnits VFPtrOffset) {
3734635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  computeVTableRelatedInformation(RD);
3735635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3736635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  VFTableIdTy id(RD, VFPtrOffset);
3737635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  assert(VFTableLayouts.count(id) && "Couldn't find a VFTable at this offset");
3738635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  return *VFTableLayouts[id];
3739635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3740635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
37415f0db587078b5af32fc9ac41fe4276b80918fd8dTimur Iskhodzhanovconst MicrosoftVTableContext::MethodVFTableLocation &
37425f0db587078b5af32fc9ac41fe4276b80918fd8dTimur IskhodzhanovMicrosoftVTableContext::getMethodVFTableLocation(GlobalDecl GD) {
3743635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  assert(cast<CXXMethodDecl>(GD.getDecl())->isVirtual() &&
3744635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov         "Only use this method for virtual methods or dtors");
3745635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  if (isa<CXXDestructorDecl>(GD.getDecl()))
3746635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    assert(GD.getDtorType() == Dtor_Deleting);
3747635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3748635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  MethodVFTableLocationsTy::iterator I = MethodVFTableLocations.find(GD);
3749635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  if (I != MethodVFTableLocations.end())
3750635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov    return I->second;
3751635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3752635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
3753635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3754635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  computeVTableRelatedInformation(RD);
3755635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov
3756635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  I = MethodVFTableLocations.find(GD);
3757635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  assert(I != MethodVFTableLocations.end() && "Did not find index!");
3758635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov  return I->second;
3759635de28950ef84ae26308ff734e778bad1ddde92Timur Iskhodzhanov}
3760