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