clang  3.7.0
VTableBuilder.h
Go to the documentation of this file.
1 //===--- VTableBuilder.h - C++ vtable layout builder --------------*- C++ -*-=//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This contains code dealing with generation of the layout of virtual tables.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_AST_VTABLEBUILDER_H
15 #define LLVM_CLANG_AST_VTABLEBUILDER_H
16 
19 #include "clang/AST/GlobalDecl.h"
20 #include "clang/AST/RecordLayout.h"
21 #include "clang/Basic/ABI.h"
22 #include "llvm/ADT/DenseMap.h"
23 #include "llvm/ADT/SetVector.h"
24 #include <memory>
25 #include <utility>
26 
27 namespace clang {
28  class CXXRecordDecl;
29 
30 /// \brief Represents a single component in a vtable.
32 public:
33  enum Kind {
39 
40  /// \brief A pointer to the complete destructor.
42 
43  /// \brief A pointer to the deleting destructor.
45 
46  /// \brief An entry that is never used.
47  ///
48  /// In some cases, a vtable function pointer will end up never being
49  /// called. Such vtable function pointers are represented as a
50  /// CK_UnusedFunctionPointer.
52  };
53 
55 
57  return VTableComponent(CK_VCallOffset, Offset);
58  }
59 
61  return VTableComponent(CK_VBaseOffset, Offset);
62  }
63 
65  return VTableComponent(CK_OffsetToTop, Offset);
66  }
67 
69  return VTableComponent(CK_RTTI, reinterpret_cast<uintptr_t>(RD));
70  }
71 
73  assert(!isa<CXXDestructorDecl>(MD) &&
74  "Don't use MakeFunction with destructors!");
75 
77  reinterpret_cast<uintptr_t>(MD));
78  }
79 
82  reinterpret_cast<uintptr_t>(DD));
83  }
84 
87  reinterpret_cast<uintptr_t>(DD));
88  }
89 
91  assert(!isa<CXXDestructorDecl>(MD) &&
92  "Don't use MakeUnusedFunction with destructors!");
94  reinterpret_cast<uintptr_t>(MD));
95  }
96 
98  return VTableComponent(I);
99  }
100 
101  /// \brief Get the kind of this vtable component.
102  Kind getKind() const {
103  return (Kind)(Value & 0x7);
104  }
105 
107  assert(getKind() == CK_VCallOffset && "Invalid component kind!");
108 
109  return getOffset();
110  }
111 
113  assert(getKind() == CK_VBaseOffset && "Invalid component kind!");
114 
115  return getOffset();
116  }
117 
119  assert(getKind() == CK_OffsetToTop && "Invalid component kind!");
120 
121  return getOffset();
122  }
123 
124  const CXXRecordDecl *getRTTIDecl() const {
125  assert(getKind() == CK_RTTI && "Invalid component kind!");
126 
127  return reinterpret_cast<CXXRecordDecl *>(getPointer());
128  }
129 
131  assert(getKind() == CK_FunctionPointer);
132 
133  return reinterpret_cast<CXXMethodDecl *>(getPointer());
134  }
135 
137  assert((getKind() == CK_CompleteDtorPointer ||
138  getKind() == CK_DeletingDtorPointer) && "Invalid component kind!");
139 
140  return reinterpret_cast<CXXDestructorDecl *>(getPointer());
141  }
142 
144  assert(getKind() == CK_UnusedFunctionPointer);
145 
146  return reinterpret_cast<CXXMethodDecl *>(getPointer());
147  }
148 
149 private:
150  VTableComponent(Kind ComponentKind, CharUnits Offset) {
151  assert((ComponentKind == CK_VCallOffset ||
152  ComponentKind == CK_VBaseOffset ||
153  ComponentKind == CK_OffsetToTop) && "Invalid component kind!");
154  assert(Offset.getQuantity() < (1LL << 56) && "Offset is too big!");
155  assert(Offset.getQuantity() >= -(1LL << 56) && "Offset is too small!");
156 
157  Value = (uint64_t(Offset.getQuantity()) << 3) | ComponentKind;
158  }
159 
160  VTableComponent(Kind ComponentKind, uintptr_t Ptr) {
161  assert((ComponentKind == CK_RTTI ||
162  ComponentKind == CK_FunctionPointer ||
163  ComponentKind == CK_CompleteDtorPointer ||
164  ComponentKind == CK_DeletingDtorPointer ||
165  ComponentKind == CK_UnusedFunctionPointer) &&
166  "Invalid component kind!");
167 
168  assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!");
169 
170  Value = Ptr | ComponentKind;
171  }
172 
173  CharUnits getOffset() const {
174  assert((getKind() == CK_VCallOffset || getKind() == CK_VBaseOffset ||
175  getKind() == CK_OffsetToTop) && "Invalid component kind!");
176 
177  return CharUnits::fromQuantity(Value >> 3);
178  }
179 
180  uintptr_t getPointer() const {
181  assert((getKind() == CK_RTTI ||
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 
203 public:
204  typedef std::pair<uint64_t, ThunkInfo> VTableThunkTy;
205 
208 
209  typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
210 private:
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 
223 public:
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 
237  return VTableComponents.get();
238  }
239 
241  return VTableComponents.get() + NumVTableComponents;
242  }
243 
244  uint64_t getNumVTableThunks() const { return NumVTableThunks; }
245 
247  return VTableThunks.get();
248  }
249 
251  return VTableThunks.get() + NumVTableThunks;
252  }
253 
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 
266  return AddressPoints;
267  }
268 };
269 
271 public:
273 
274  bool isMicrosoft() const { return IsMicrosoftABI; }
275 
276  virtual ~VTableContextBase() {}
277 
278 protected:
279  typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
280 
281  /// \brief Contains all thunks that a given method decl will need.
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 
289 
290 public:
292  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()->getCanonicalDecl());
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 
307 };
308 
310 private:
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 
334 public:
336  ~ItaniumVTableContext() override;
337 
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.
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.
373 struct VPtrInfo {
375 
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.
388 
389  /// BaseWithVPtr is at this offset from its containing complete object or
390  /// virtual base.
392 
393  /// The vptr is stored inside this subobject.
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.
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.
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.
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.
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.
419 
420  /// The vptr is stored inside the non-virtual component of this virtual base.
422  return ContainingVBases.empty() ? nullptr : ContainingVBases.front();
423  }
424 };
425 
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.
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.
441 };
442 
444 public:
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.
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.
456 
457  /// Method's index in the vftable.
458  uint64_t Index;
459 
461  : VBTableIndex(0), VBase(nullptr), VFPtrOffset(CharUnits::Zero()),
462  Index(0) {}
463 
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 
479 private:
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 
510 public:
512  : VTableContextBase(/*MS=*/true), Context(Context) {}
513 
514  ~MicrosoftVTableContext() override;
515 
516  const VPtrInfoVector &getVFPtrOffsets(const CXXRecordDecl *RD);
517 
519  CharUnits VFPtrOffset);
520 
521  const MethodVFTableLocation &getMethodVFTableLocation(GlobalDecl GD);
522 
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;
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 
539 
540  static bool classof(const VTableContextBase *VT) { return VT->isMicrosoft(); }
541 };
542 
543 } // namespace clang
544 
545 #endif
CharUnits getOffsetToTop() const
VTableLayout * createConstructionVTableLayout(const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset, bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass)
ItaniumVTableContext(ASTContext &Context)
static VTableComponent MakeRTTI(const CXXRecordDecl *RD)
Definition: VTableBuilder.h:68
VPtrInfoVector VBPtrPaths
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition: CharUnits.h:163
virtual const ThunkInfoVectorTy * getThunkInfo(GlobalDecl GD)
vtable_component_iterator vtable_component_begin() const
const VTableThunkTy * vtable_thunk_iterator
vtable_component_iterator vtable_component_end() const
BasePath MangledPath
static VTableComponent MakeUnusedFunction(const CXXMethodDecl *MD)
Definition: VTableBuilder.h:90
static VTableComponent getFromOpaqueInteger(uint64_t I)
Definition: VTableBuilder.h:97
static VTableComponent MakeVCallOffset(CharUnits Offset)
Definition: VTableBuilder.h:56
const CXXRecordDecl * getVBaseWithVPtr() const
The vptr is stored inside the non-virtual component of this virtual base.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:89
BasePath PathToBaseWithVPtr
uint64_t getNumVTableComponents() const
VTableLayout(uint64_t NumVTableComponents, const VTableComponent *VTableComponents, uint64_t NumVTableThunks, const VTableThunkTy *VTableThunks, const AddressPointsMapTy &AddressPoints, bool IsMicrosoftABI)
static VTableComponent MakeCompleteDtor(const CXXDestructorDecl *DD)
Definition: VTableBuilder.h:80
llvm::DenseMap< const CXXRecordDecl *, unsigned > VBTableIndices
const VTableComponent * vtable_component_iterator
const Decl * getDecl() const
Definition: GlobalDecl.h:60
const CXXRecordDecl * NextBaseToMangle
uint64_t getAddressPoint(BaseSubobject Base) const
const CXXMethodDecl * getFunctionDecl() const
llvm::DenseMap< const CXXMethodDecl *, ThunkInfoVectorTy > ThunksMapTy
uint32_t Offset
Definition: CacheTokens.cpp:43
CharUnits getVCallOffset() const
const CXXRecordDecl * getParent() const
Definition: DeclCXX.h:1817
const VPtrInfoVector & getVFPtrOffsets(const CXXRecordDecl *RD)
Enums/classes describing ABI related information about constructors, destructors and thunks...
uint64_t getMethodVTableIndex(GlobalDecl GD)
Locate a virtual function in the vtable.
CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, const CXXRecordDecl *VBase)
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:733
static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD)
Definition: VTableBuilder.h:85
uint64_t VBTableIndex
If nonzero, holds the vbtable index of the virtual base with the vfptr.
BasePath ContainingVBases
ASTContext * Context
CXXDtorType getDtorType() const
Definition: GlobalDecl.h:67
SmallVector< ThunkInfo, 1 > ThunkInfoVectorTy
static bool classof(const VTableContextBase *VT)
bool operator<(const MethodVFTableLocation &other) const
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2358
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition: CharUnits.h:63
vtable_thunk_iterator vtable_thunk_end() const
llvm::DenseMap< BaseSubobject, uint64_t > AddressPointsMapTy
MethodVFTableLocation(uint64_t VBTableIndex, const CXXRecordDecl *VBase, CharUnits VFPtrOffset, uint64_t Index)
SmallVector< VPtrInfo *, 2 > VPtrInfoVector
The result type of a method or function.
SmallVector< const CXXRecordDecl *, 1 > BasePath
const CXXRecordDecl * ReusingBase
const ThunkInfoVectorTy * getThunkInfo(GlobalDecl GD) override
unsigned getVBTableIndex(const CXXRecordDecl *Derived, const CXXRecordDecl *VBase)
Returns the index of VBase in the vbtable of Derived. VBase must be a morally virtual base of Derived...
const CXXRecordDecl * getRTTIDecl() const
uint64_t getNumVTableThunks() const
Kind
Represents a single component in a vtable.
Definition: VTableBuilder.h:31
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:1717
const VTableLayout & getVFTableLayout(const CXXRecordDecl *RD, CharUnits VFPtrOffset)
const CXXDestructorDecl * getDestructorDecl() const
const CXXRecordDecl * BaseWithVPtr
The vptr is stored inside this subobject.
Complete object dtor.
Definition: ABI.h:36
MicrosoftVTableContext(ASTContext &Context)
static VTableComponent MakeVBaseOffset(CharUnits Offset)
Definition: VTableBuilder.h:60
const VPtrInfoVector & enumerateVBTables(const CXXRecordDecl *RD)
ThunksMapTy Thunks
Contains all thunks that a given method decl will need.
CharUnits getVBaseOffset() const
VPtrInfo(const CXXRecordDecl *RD)
CharUnits NonVirtualOffset
vtable_thunk_iterator vtable_thunk_begin() const
const VTableLayout & getVTableLayout(const CXXRecordDecl *RD)
Represents a C++ struct/union/class.
Definition: DeclCXX.h:285
std::pair< uint64_t, ThunkInfo > VTableThunkTy
CharUnits FullOffsetInMDC
uint64_t Index
Method's index in the vftable.
A pointer to the deleting destructor.
Definition: VTableBuilder.h:44
static VTableComponent MakeFunction(const CXXMethodDecl *MD)
Definition: VTableBuilder.h:72
Kind getKind() const
Get the kind of this vtable component.
const AddressPointsMapTy & getAddressPoints() const
#define true
Definition: stdbool.h:32
const CXXMethodDecl * getUnusedFunctionDecl() const
A pointer to the complete destructor.
Definition: VTableBuilder.h:41
const MethodVFTableLocation & getMethodVFTableLocation(GlobalDecl GD)
virtual void computeVTableRelatedInformation(const CXXRecordDecl *RD)=0
static bool classof(const VTableContextBase *VT)
static VTableComponent MakeOffsetToTop(CharUnits Offset)
Definition: VTableBuilder.h:64