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