VTableBuilder.h revision 6bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===--- VTableBuilder.h - C++ vtable layout builder --------------*- C++ -*-=// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details. 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This contains code dealing with generation of the layout of virtual tables. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===// 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#ifndef LLVM_CLANG_AST_VTABLEBUILDER_H 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LLVM_CLANG_AST_VTABLEBUILDER_H 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/AST/BaseSubobject.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/AST/CXXInheritance.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/AST/GlobalDecl.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/AST/RecordLayout.h" 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "clang/Basic/ABI.h" 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "llvm/ADT/DenseMap.h" 23a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "llvm/ADT/SetVector.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <memory> 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility> 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace clang { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class CXXRecordDecl; 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/// \brief Represents a single component in a vtable. 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class VTableComponent { 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)public: 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) enum Kind { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CK_VCallOffset, 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CK_VBaseOffset, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CK_OffsetToTop, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CK_RTTI, 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CK_FunctionPointer, 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// \brief A pointer to the complete destructor. 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CK_CompleteDtorPointer, 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /// \brief A pointer to the deleting destructor. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CK_DeletingDtorPointer, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /// \brief An entry that is never used. 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /// 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) /// In some cases, a vtable function pointer will end up never being 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /// called. Such vtable function pointers are represented as a 50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) /// CK_UnusedFunctionPointer. 51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) CK_UnusedFunctionPointer 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VTableComponent() { } 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static VTableComponent MakeVCallOffset(CharUnits Offset) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return VTableComponent(CK_VCallOffset, Offset); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static VTableComponent MakeVBaseOffset(CharUnits Offset) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return VTableComponent(CK_VBaseOffset, Offset); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static VTableComponent MakeOffsetToTop(CharUnits Offset) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return VTableComponent(CK_OffsetToTop, Offset); 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) static VTableComponent MakeRTTI(const CXXRecordDecl *RD) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return VTableComponent(CK_RTTI, reinterpret_cast<uintptr_t>(RD)); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static VTableComponent MakeFunction(const CXXMethodDecl *MD) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(!isa<CXXDestructorDecl>(MD) && 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Don't use MakeFunction with destructors!"); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return VTableComponent(CK_FunctionPointer, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<uintptr_t>(MD)); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static VTableComponent MakeCompleteDtor(const CXXDestructorDecl *DD) { 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return VTableComponent(CK_CompleteDtorPointer, 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reinterpret_cast<uintptr_t>(DD)); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return VTableComponent(CK_DeletingDtorPointer, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<uintptr_t>(DD)); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static VTableComponent MakeUnusedFunction(const CXXMethodDecl *MD) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(!isa<CXXDestructorDecl>(MD) && 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Don't use MakeUnusedFunction with destructors!"); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return VTableComponent(CK_UnusedFunctionPointer, 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<uintptr_t>(MD)); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static VTableComponent getFromOpaqueInteger(uint64_t I) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return VTableComponent(I); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// \brief Get the kind of this vtable component. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Kind getKind() const { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (Kind)(Value & 0x7); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CharUnits getVCallOffset() const { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(getKind() == CK_VCallOffset && "Invalid component kind!"); 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return getOffset(); 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CharUnits getVBaseOffset() const { 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert(getKind() == CK_VBaseOffset && "Invalid component kind!"); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return getOffset(); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CharUnits getOffsetToTop() const { 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert(getKind() == CK_OffsetToTop && "Invalid component kind!"); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return getOffset(); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CXXRecordDecl *getRTTIDecl() const { 125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) assert(getKind() == CK_RTTI && "Invalid component kind!"); 126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<CXXRecordDecl *>(getPointer()); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CXXMethodDecl *getFunctionDecl() const { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(getKind() == CK_FunctionPointer); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<CXXMethodDecl *>(getPointer()); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CXXDestructorDecl *getDestructorDecl() const { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert((getKind() == CK_CompleteDtorPointer || 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getKind() == CK_DeletingDtorPointer) && "Invalid component kind!"); 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return reinterpret_cast<CXXDestructorDecl *>(getPointer()); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CXXMethodDecl *getUnusedFunctionDecl() const { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(getKind() == CK_UnusedFunctionPointer); 145a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<CXXMethodDecl *>(getPointer()); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)private: 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VTableComponent(Kind ComponentKind, CharUnits Offset) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert((ComponentKind == CK_VCallOffset || 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ComponentKind == CK_VBaseOffset || 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ComponentKind == CK_OffsetToTop) && "Invalid component kind!"); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(Offset.getQuantity() < (1LL << 56) && "Offset is too big!"); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(Offset.getQuantity() >= -(1LL << 56) && "Offset is too small!"); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Value = (uint64_t(Offset.getQuantity()) << 3) | ComponentKind; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VTableComponent(Kind ComponentKind, uintptr_t Ptr) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert((ComponentKind == CK_RTTI || 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ComponentKind == CK_FunctionPointer || 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ComponentKind == CK_CompleteDtorPointer || 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ComponentKind == CK_DeletingDtorPointer || 165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ComponentKind == CK_UnusedFunctionPointer) && 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Invalid component kind!"); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!"); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Value = Ptr | ComponentKind; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CharUnits getOffset() const { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert((getKind() == CK_VCallOffset || getKind() == CK_VBaseOffset || 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getKind() == CK_OffsetToTop) && "Invalid component kind!"); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CharUnits::fromQuantity(Value >> 3); 178 } 179 180 uintptr_t getPointer() const { 181 assert((getKind() == CK_RTTI || 182 getKind() == CK_FunctionPointer || 183 getKind() == CK_CompleteDtorPointer || 184 getKind() == CK_DeletingDtorPointer || 185 getKind() == CK_UnusedFunctionPointer) && 186 "Invalid component kind!"); 187 188 return static_cast<uintptr_t>(Value & ~7ULL); 189 } 190 191 explicit VTableComponent(uint64_t Value) 192 : Value(Value) { } 193 194 /// The kind is stored in the lower 3 bits of the value. For offsets, we 195 /// make use of the facts that classes can't be larger than 2^55 bytes, 196 /// so we store the offset in the lower part of the 61 bits that remain. 197 /// (The reason that we're not simply using a PointerIntPair here is that we 198 /// need the offsets to be 64-bit, even when on a 32-bit machine). 199 int64_t Value; 200}; 201 202class VTableLayout { 203public: 204 typedef std::pair<uint64_t, ThunkInfo> VTableThunkTy; 205 206 typedef const VTableComponent *vtable_component_iterator; 207 typedef const VTableThunkTy *vtable_thunk_iterator; 208 209 typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy; 210private: 211 uint64_t NumVTableComponents; 212 std::unique_ptr<VTableComponent[]> VTableComponents; 213 214 /// \brief Contains thunks needed by vtables, sorted by indices. 215 uint64_t NumVTableThunks; 216 std::unique_ptr<VTableThunkTy[]> VTableThunks; 217 218 /// \brief Address points for all vtables. 219 AddressPointsMapTy AddressPoints; 220 221 bool IsMicrosoftABI; 222 223public: 224 VTableLayout(uint64_t NumVTableComponents, 225 const VTableComponent *VTableComponents, 226 uint64_t NumVTableThunks, 227 const VTableThunkTy *VTableThunks, 228 const AddressPointsMapTy &AddressPoints, 229 bool IsMicrosoftABI); 230 ~VTableLayout(); 231 232 uint64_t getNumVTableComponents() const { 233 return NumVTableComponents; 234 } 235 236 vtable_component_iterator vtable_component_begin() const { 237 return VTableComponents.get(); 238 } 239 240 vtable_component_iterator vtable_component_end() const { 241 return VTableComponents.get() + NumVTableComponents; 242 } 243 244 uint64_t getNumVTableThunks() const { return NumVTableThunks; } 245 246 vtable_thunk_iterator vtable_thunk_begin() const { 247 return VTableThunks.get(); 248 } 249 250 vtable_thunk_iterator vtable_thunk_end() const { 251 return VTableThunks.get() + NumVTableThunks; 252 } 253 254 uint64_t getAddressPoint(BaseSubobject Base) const { 255 assert(AddressPoints.count(Base) && 256 "Did not find address point!"); 257 258 uint64_t AddressPoint = AddressPoints.lookup(Base); 259 assert(AddressPoint != 0 || IsMicrosoftABI); 260 (void)IsMicrosoftABI; 261 262 return AddressPoint; 263 } 264 265 const AddressPointsMapTy &getAddressPoints() const { 266 return AddressPoints; 267 } 268}; 269 270class VTableContextBase { 271public: 272 typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy; 273 274 bool isMicrosoft() const { return IsMicrosoftABI; } 275 276 virtual ~VTableContextBase() {} 277 278protected: 279 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy; 280 281 /// \brief Contains all thunks that a given method decl will need. 282 ThunksMapTy Thunks; 283 284 /// Compute and store all vtable related information (vtable layout, vbase 285 /// offset offsets, thunks etc) for the given record decl. 286 virtual void computeVTableRelatedInformation(const CXXRecordDecl *RD) = 0; 287 288 VTableContextBase(bool MS) : IsMicrosoftABI(MS) {} 289 290public: 291 virtual const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) { 292 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()->getCanonicalDecl()); 293 computeVTableRelatedInformation(MD->getParent()); 294 295 // This assumes that all the destructors present in the vtable 296 // use exactly the same set of thunks. 297 ThunksMapTy::const_iterator I = Thunks.find(MD); 298 if (I == Thunks.end()) { 299 // We did not find a thunk for this method. 300 return nullptr; 301 } 302 303 return &I->second; 304 } 305 306 bool IsMicrosoftABI; 307}; 308 309class ItaniumVTableContext : public VTableContextBase { 310private: 311 312 /// \brief Contains the index (relative to the vtable address point) 313 /// where the function pointer for a virtual function is stored. 314 typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy; 315 MethodVTableIndicesTy MethodVTableIndices; 316 317 typedef llvm::DenseMap<const CXXRecordDecl *, const VTableLayout *> 318 VTableLayoutMapTy; 319 VTableLayoutMapTy VTableLayouts; 320 321 typedef std::pair<const CXXRecordDecl *, 322 const CXXRecordDecl *> ClassPairTy; 323 324 /// \brief vtable offsets for offsets of virtual bases of a class. 325 /// 326 /// Contains the vtable offset (relative to the address point) in chars 327 /// where the offsets for virtual bases of a class are stored. 328 typedef llvm::DenseMap<ClassPairTy, CharUnits> 329 VirtualBaseClassOffsetOffsetsMapTy; 330 VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets; 331 332 void computeVTableRelatedInformation(const CXXRecordDecl *RD) override; 333 334public: 335 ItaniumVTableContext(ASTContext &Context); 336 ~ItaniumVTableContext(); 337 338 const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) { 339 computeVTableRelatedInformation(RD); 340 assert(VTableLayouts.count(RD) && "No layout for this record decl!"); 341 342 return *VTableLayouts[RD]; 343 } 344 345 VTableLayout * 346 createConstructionVTableLayout(const CXXRecordDecl *MostDerivedClass, 347 CharUnits MostDerivedClassOffset, 348 bool MostDerivedClassIsVirtual, 349 const CXXRecordDecl *LayoutClass); 350 351 /// \brief Locate a virtual function in the vtable. 352 /// 353 /// Return the index (relative to the vtable address point) where the 354 /// function pointer for the given virtual function is stored. 355 uint64_t getMethodVTableIndex(GlobalDecl GD); 356 357 /// Return the offset in chars (relative to the vtable address point) where 358 /// the offset of the virtual base that contains the given base is stored, 359 /// otherwise, if no virtual base contains the given class, return 0. 360 /// 361 /// Base must be a virtual base class or an unambiguous base. 362 CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, 363 const CXXRecordDecl *VBase); 364 365 static bool classof(const VTableContextBase *VT) { 366 return !VT->isMicrosoft(); 367 } 368}; 369 370/// Holds information about the inheritance path to a virtual base or function 371/// table pointer. A record may contain as many vfptrs or vbptrs as there are 372/// base subobjects. 373struct VPtrInfo { 374 typedef SmallVector<const CXXRecordDecl *, 1> BasePath; 375 376 VPtrInfo(const CXXRecordDecl *RD) 377 : ReusingBase(RD), BaseWithVPtr(RD), NextBaseToMangle(RD) {} 378 379 // Copy constructor. 380 // FIXME: Uncomment when we've moved to C++11. 381 // VPtrInfo(const VPtrInfo &) = default; 382 383 /// The vtable will hold all of the virtual bases or virtual methods of 384 /// ReusingBase. This may or may not be the same class as VPtrSubobject.Base. 385 /// A derived class will reuse the vptr of the first non-virtual base 386 /// subobject that has one. 387 const CXXRecordDecl *ReusingBase; 388 389 /// BaseWithVPtr is at this offset from its containing complete object or 390 /// virtual base. 391 CharUnits NonVirtualOffset; 392 393 /// The vptr is stored inside this subobject. 394 const CXXRecordDecl *BaseWithVPtr; 395 396 /// The bases from the inheritance path that got used to mangle the vbtable 397 /// name. This is not really a full path like a CXXBasePath. It holds the 398 /// subset of records that need to be mangled into the vbtable symbol name in 399 /// order to get a unique name. 400 BasePath MangledPath; 401 402 /// The next base to push onto the mangled path if this path is ambiguous in a 403 /// derived class. If it's null, then it's already been pushed onto the path. 404 const CXXRecordDecl *NextBaseToMangle; 405 406 /// The set of possibly indirect vbases that contain this vbtable. When a 407 /// derived class indirectly inherits from the same vbase twice, we only keep 408 /// vtables and their paths from the first instance. 409 BasePath ContainingVBases; 410 411 /// This holds the base classes path from the complete type to the first base 412 /// with the given vfptr offset, in the base-to-derived order. Only used for 413 /// vftables. 414 BasePath PathToBaseWithVPtr; 415 416 /// Static offset from the top of the most derived class to this vfptr, 417 /// including any virtual base offset. Only used for vftables. 418 CharUnits FullOffsetInMDC; 419 420 /// The vptr is stored inside the non-virtual component of this virtual base. 421 const CXXRecordDecl *getVBaseWithVPtr() const { 422 return ContainingVBases.empty() ? nullptr : ContainingVBases.front(); 423 } 424}; 425 426typedef SmallVector<VPtrInfo *, 2> VPtrInfoVector; 427 428/// All virtual base related information about a given record decl. Includes 429/// information on all virtual base tables and the path components that are used 430/// to mangle them. 431struct VirtualBaseInfo { 432 ~VirtualBaseInfo() { llvm::DeleteContainerPointers(VBPtrPaths); } 433 434 /// A map from virtual base to vbtable index for doing a conversion from the 435 /// the derived class to the a base. 436 llvm::DenseMap<const CXXRecordDecl *, unsigned> VBTableIndices; 437 438 /// Information on all virtual base tables used when this record is the most 439 /// derived class. 440 VPtrInfoVector VBPtrPaths; 441}; 442 443class MicrosoftVTableContext : public VTableContextBase { 444public: 445 struct MethodVFTableLocation { 446 /// If nonzero, holds the vbtable index of the virtual base with the vfptr. 447 uint64_t VBTableIndex; 448 449 /// If nonnull, holds the last vbase which contains the vfptr that the 450 /// method definition is adjusted to. 451 const CXXRecordDecl *VBase; 452 453 /// This is the offset of the vfptr from the start of the last vbase, or the 454 /// complete type if there are no virtual bases. 455 CharUnits VFPtrOffset; 456 457 /// Method's index in the vftable. 458 uint64_t Index; 459 460 MethodVFTableLocation() 461 : VBTableIndex(0), VBase(nullptr), VFPtrOffset(CharUnits::Zero()), 462 Index(0) {} 463 464 MethodVFTableLocation(uint64_t VBTableIndex, const CXXRecordDecl *VBase, 465 CharUnits VFPtrOffset, uint64_t Index) 466 : VBTableIndex(VBTableIndex), VBase(VBase), 467 VFPtrOffset(VFPtrOffset), Index(Index) {} 468 469 bool operator<(const MethodVFTableLocation &other) const { 470 if (VBTableIndex != other.VBTableIndex) { 471 assert(VBase != other.VBase); 472 return VBTableIndex < other.VBTableIndex; 473 } 474 return std::tie(VFPtrOffset, Index) < 475 std::tie(other.VFPtrOffset, other.Index); 476 } 477 }; 478 479private: 480 ASTContext &Context; 481 482 typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation> 483 MethodVFTableLocationsTy; 484 MethodVFTableLocationsTy MethodVFTableLocations; 485 486 typedef llvm::DenseMap<const CXXRecordDecl *, VPtrInfoVector *> 487 VFPtrLocationsMapTy; 488 VFPtrLocationsMapTy VFPtrLocations; 489 490 typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy; 491 typedef llvm::DenseMap<VFTableIdTy, const VTableLayout *> VFTableLayoutMapTy; 492 VFTableLayoutMapTy VFTableLayouts; 493 494 llvm::DenseMap<const CXXRecordDecl *, VirtualBaseInfo *> VBaseInfo; 495 496 void enumerateVFPtrs(const CXXRecordDecl *ForClass, VPtrInfoVector &Result); 497 498 void computeVTableRelatedInformation(const CXXRecordDecl *RD) override; 499 500 void dumpMethodLocations(const CXXRecordDecl *RD, 501 const MethodVFTableLocationsTy &NewMethods, 502 raw_ostream &); 503 504 const VirtualBaseInfo * 505 computeVBTableRelatedInformation(const CXXRecordDecl *RD); 506 507 void computeVTablePaths(bool ForVBTables, const CXXRecordDecl *RD, 508 VPtrInfoVector &Paths); 509 510public: 511 MicrosoftVTableContext(ASTContext &Context) 512 : VTableContextBase(/*MS=*/true), Context(Context) {} 513 514 ~MicrosoftVTableContext(); 515 516 const VPtrInfoVector &getVFPtrOffsets(const CXXRecordDecl *RD); 517 518 const VTableLayout &getVFTableLayout(const CXXRecordDecl *RD, 519 CharUnits VFPtrOffset); 520 521 const MethodVFTableLocation &getMethodVFTableLocation(GlobalDecl GD); 522 523 const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) override { 524 // Complete destructors don't have a slot in a vftable, so no thunks needed. 525 if (isa<CXXDestructorDecl>(GD.getDecl()) && 526 GD.getDtorType() == Dtor_Complete) 527 return nullptr; 528 return VTableContextBase::getThunkInfo(GD); 529 } 530 531 /// \brief Returns the index of VBase in the vbtable of Derived. 532 /// VBase must be a morally virtual base of Derived. 533 /// The vbtable is an array of i32 offsets. The first entry is a self entry, 534 /// and the rest are offsets from the vbptr to virtual bases. 535 unsigned getVBTableIndex(const CXXRecordDecl *Derived, 536 const CXXRecordDecl *VBase); 537 538 const VPtrInfoVector &enumerateVBTables(const CXXRecordDecl *RD); 539 540 static bool classof(const VTableContextBase *VT) { return VT->isMicrosoft(); } 541}; 542 543} // namespace clang 544 545#endif 546