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