1 //===- VTTBuilder.h - C++ VTT 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 table
11 // tables (VTT).
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_AST_VTTBUILDER_H
16 #define LLVM_CLANG_AST_VTTBUILDER_H
17 
18 #include "clang/AST/BaseSubobject.h"
19 #include "clang/AST/CharUnits.h"
20 #include "clang/Basic/LLVM.h"
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/ADT/PointerIntPair.h"
23 #include "llvm/ADT/SmallPtrSet.h"
24 #include "llvm/ADT/SmallVector.h"
25 #include <cstdint>
26 
27 namespace clang {
28 
29 class ASTContext;
30 class ASTRecordLayout;
31 class CXXRecordDecl;
32 
33 class VTTVTable {
34   llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> BaseAndIsVirtual;
35   CharUnits BaseOffset;
36 
37 public:
38   VTTVTable() = default;
VTTVTable(const CXXRecordDecl * Base,CharUnits BaseOffset,bool BaseIsVirtual)39   VTTVTable(const CXXRecordDecl *Base, CharUnits BaseOffset, bool BaseIsVirtual)
40       : BaseAndIsVirtual(Base, BaseIsVirtual), BaseOffset(BaseOffset) {}
VTTVTable(BaseSubobject Base,bool BaseIsVirtual)41   VTTVTable(BaseSubobject Base, bool BaseIsVirtual)
42       : BaseAndIsVirtual(Base.getBase(), BaseIsVirtual),
43         BaseOffset(Base.getBaseOffset()) {}
44 
getBase()45   const CXXRecordDecl *getBase() const {
46     return BaseAndIsVirtual.getPointer();
47   }
48 
getBaseOffset()49   CharUnits getBaseOffset() const {
50     return BaseOffset;
51   }
52 
isVirtual()53   bool isVirtual() const {
54     return BaseAndIsVirtual.getInt();
55   }
56 
getBaseSubobject()57   BaseSubobject getBaseSubobject() const {
58     return BaseSubobject(getBase(), getBaseOffset());
59   }
60 };
61 
62 struct VTTComponent {
63   uint64_t VTableIndex;
64   BaseSubobject VTableBase;
65 
66   VTTComponent() = default;
VTTComponentVTTComponent67   VTTComponent(uint64_t VTableIndex, BaseSubobject VTableBase)
68      : VTableIndex(VTableIndex), VTableBase(VTableBase) {}
69 };
70 
71 /// Class for building VTT layout information.
72 class VTTBuilder {
73   ASTContext &Ctx;
74 
75   /// The most derived class for which we're building this vtable.
76   const CXXRecordDecl *MostDerivedClass;
77 
78   using VTTVTablesVectorTy = SmallVector<VTTVTable, 64>;
79 
80   /// The VTT vtables.
81   VTTVTablesVectorTy VTTVTables;
82 
83   using VTTComponentsVectorTy = SmallVector<VTTComponent, 64>;
84 
85   /// The VTT components.
86   VTTComponentsVectorTy VTTComponents;
87 
88   /// The AST record layout of the most derived class.
89   const ASTRecordLayout &MostDerivedClassLayout;
90 
91   using VisitedVirtualBasesSetTy = llvm::SmallPtrSet<const CXXRecordDecl *, 4>;
92 
93   using AddressPointsMapTy = llvm::DenseMap<BaseSubobject, uint64_t>;
94 
95   /// The sub-VTT indices for the bases of the most derived class.
96   llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndicies;
97 
98   /// The secondary virtual pointer indices of all subobjects of
99   /// the most derived class.
100   llvm::DenseMap<BaseSubobject, uint64_t> SecondaryVirtualPointerIndices;
101 
102   /// Whether the VTT builder should generate LLVM IR for the VTT.
103   bool GenerateDefinition;
104 
105   /// Add a vtable pointer to the VTT currently being built.
106   void AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex,
107                         const CXXRecordDecl *VTableClass);
108 
109   /// Lay out the secondary VTTs of the given base subobject.
110   void LayoutSecondaryVTTs(BaseSubobject Base);
111 
112   /// Lay out the secondary virtual pointers for the given base
113   /// subobject.
114   ///
115   /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
116   /// or a direct or indirect base of a virtual base.
117   void LayoutSecondaryVirtualPointers(BaseSubobject Base,
118                                       bool BaseIsMorallyVirtual,
119                                       uint64_t VTableIndex,
120                                       const CXXRecordDecl *VTableClass,
121                                       VisitedVirtualBasesSetTy &VBases);
122 
123   /// Lay out the secondary virtual pointers for the given base
124   /// subobject.
125   void LayoutSecondaryVirtualPointers(BaseSubobject Base,
126                                       uint64_t VTableIndex);
127 
128   /// Lay out the VTTs for the virtual base classes of the given
129   /// record declaration.
130   void LayoutVirtualVTTs(const CXXRecordDecl *RD,
131                          VisitedVirtualBasesSetTy &VBases);
132 
133   /// Lay out the VTT for the given subobject, including any
134   /// secondary VTTs, secondary virtual pointers and virtual VTTs.
135   void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual);
136 
137 public:
138   VTTBuilder(ASTContext &Ctx, const CXXRecordDecl *MostDerivedClass,
139              bool GenerateDefinition);
140 
141   // Returns a reference to the VTT components.
getVTTComponents()142   const VTTComponentsVectorTy &getVTTComponents() const {
143     return VTTComponents;
144   }
145 
146   // Returns a reference to the VTT vtables.
getVTTVTables()147   const VTTVTablesVectorTy &getVTTVTables() const {
148     return VTTVTables;
149   }
150 
151   /// Returns a reference to the sub-VTT indices.
getSubVTTIndicies()152   const llvm::DenseMap<BaseSubobject, uint64_t> &getSubVTTIndicies() const {
153     return SubVTTIndicies;
154   }
155 
156   /// Returns a reference to the secondary virtual pointer indices.
157   const llvm::DenseMap<BaseSubobject, uint64_t> &
getSecondaryVirtualPointerIndices()158   getSecondaryVirtualPointerIndices() const {
159     return SecondaryVirtualPointerIndices;
160   }
161 };
162 
163 } // namespace clang
164 
165 #endif // LLVM_CLANG_AST_VTTBUILDER_H
166