1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #ifndef LLVM_CLANG_AST_VTABLEBUILDER_H |
14 | #define LLVM_CLANG_AST_VTABLEBUILDER_H |
15 | |
16 | #include "clang/AST/BaseSubobject.h" |
17 | #include "clang/AST/CXXInheritance.h" |
18 | #include "clang/AST/GlobalDecl.h" |
19 | #include "clang/AST/RecordLayout.h" |
20 | #include "clang/Basic/ABI.h" |
21 | #include "llvm/ADT/DenseMap.h" |
22 | #include <memory> |
23 | #include <utility> |
24 | |
25 | namespace clang { |
26 | class CXXRecordDecl; |
27 | |
28 | |
29 | class VTableComponent { |
30 | public: |
31 | enum Kind { |
32 | CK_VCallOffset, |
33 | CK_VBaseOffset, |
34 | CK_OffsetToTop, |
35 | CK_RTTI, |
36 | CK_FunctionPointer, |
37 | |
38 | |
39 | CK_CompleteDtorPointer, |
40 | |
41 | |
42 | CK_DeletingDtorPointer, |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | CK_UnusedFunctionPointer |
50 | }; |
51 | |
52 | VTableComponent() = default; |
53 | |
54 | static VTableComponent MakeVCallOffset(CharUnits Offset) { |
55 | return VTableComponent(CK_VCallOffset, Offset); |
56 | } |
57 | |
58 | static VTableComponent MakeVBaseOffset(CharUnits Offset) { |
59 | return VTableComponent(CK_VBaseOffset, Offset); |
60 | } |
61 | |
62 | static VTableComponent MakeOffsetToTop(CharUnits Offset) { |
63 | return VTableComponent(CK_OffsetToTop, Offset); |
64 | } |
65 | |
66 | static VTableComponent MakeRTTI(const CXXRecordDecl *RD) { |
67 | return VTableComponent(CK_RTTI, reinterpret_cast<uintptr_t>(RD)); |
68 | } |
69 | |
70 | static VTableComponent MakeFunction(const CXXMethodDecl *MD) { |
71 | (0) . __assert_fail ("!isa(MD) && \"Don't use MakeFunction with destructors!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 72, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!isa<CXXDestructorDecl>(MD) && |
72 | (0) . __assert_fail ("!isa(MD) && \"Don't use MakeFunction with destructors!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 72, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "Don't use MakeFunction with destructors!"); |
73 | |
74 | return VTableComponent(CK_FunctionPointer, |
75 | reinterpret_cast<uintptr_t>(MD)); |
76 | } |
77 | |
78 | static VTableComponent MakeCompleteDtor(const CXXDestructorDecl *DD) { |
79 | return VTableComponent(CK_CompleteDtorPointer, |
80 | reinterpret_cast<uintptr_t>(DD)); |
81 | } |
82 | |
83 | static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD) { |
84 | return VTableComponent(CK_DeletingDtorPointer, |
85 | reinterpret_cast<uintptr_t>(DD)); |
86 | } |
87 | |
88 | static VTableComponent MakeUnusedFunction(const CXXMethodDecl *MD) { |
89 | (0) . __assert_fail ("!isa(MD) && \"Don't use MakeUnusedFunction with destructors!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 90, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!isa<CXXDestructorDecl>(MD) && |
90 | (0) . __assert_fail ("!isa(MD) && \"Don't use MakeUnusedFunction with destructors!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 90, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "Don't use MakeUnusedFunction with destructors!"); |
91 | return VTableComponent(CK_UnusedFunctionPointer, |
92 | reinterpret_cast<uintptr_t>(MD)); |
93 | } |
94 | |
95 | |
96 | Kind getKind() const { |
97 | return (Kind)(Value & 0x7); |
98 | } |
99 | |
100 | CharUnits getVCallOffset() const { |
101 | (0) . __assert_fail ("getKind() == CK_VCallOffset && \"Invalid component kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 101, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(getKind() == CK_VCallOffset && "Invalid component kind!"); |
102 | |
103 | return getOffset(); |
104 | } |
105 | |
106 | CharUnits getVBaseOffset() const { |
107 | (0) . __assert_fail ("getKind() == CK_VBaseOffset && \"Invalid component kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 107, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(getKind() == CK_VBaseOffset && "Invalid component kind!"); |
108 | |
109 | return getOffset(); |
110 | } |
111 | |
112 | CharUnits getOffsetToTop() const { |
113 | (0) . __assert_fail ("getKind() == CK_OffsetToTop && \"Invalid component kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 113, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(getKind() == CK_OffsetToTop && "Invalid component kind!"); |
114 | |
115 | return getOffset(); |
116 | } |
117 | |
118 | const CXXRecordDecl *getRTTIDecl() const { |
119 | (0) . __assert_fail ("isRTTIKind() && \"Invalid component kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 119, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isRTTIKind() && "Invalid component kind!"); |
120 | return reinterpret_cast<CXXRecordDecl *>(getPointer()); |
121 | } |
122 | |
123 | const CXXMethodDecl *getFunctionDecl() const { |
124 | (0) . __assert_fail ("isFunctionPointerKind() && \"Invalid component kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 124, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isFunctionPointerKind() && "Invalid component kind!"); |
125 | if (isDestructorKind()) |
126 | return getDestructorDecl(); |
127 | return reinterpret_cast<CXXMethodDecl *>(getPointer()); |
128 | } |
129 | |
130 | const CXXDestructorDecl *getDestructorDecl() const { |
131 | (0) . __assert_fail ("isDestructorKind() && \"Invalid component kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 131, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isDestructorKind() && "Invalid component kind!"); |
132 | return reinterpret_cast<CXXDestructorDecl *>(getPointer()); |
133 | } |
134 | |
135 | const CXXMethodDecl *getUnusedFunctionDecl() const { |
136 | (0) . __assert_fail ("getKind() == CK_UnusedFunctionPointer && \"Invalid component kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 136, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(getKind() == CK_UnusedFunctionPointer && "Invalid component kind!"); |
137 | return reinterpret_cast<CXXMethodDecl *>(getPointer()); |
138 | } |
139 | |
140 | bool isDestructorKind() const { return isDestructorKind(getKind()); } |
141 | |
142 | bool isUsedFunctionPointerKind() const { |
143 | return isUsedFunctionPointerKind(getKind()); |
144 | } |
145 | |
146 | bool isFunctionPointerKind() const { |
147 | return isFunctionPointerKind(getKind()); |
148 | } |
149 | |
150 | bool isRTTIKind() const { return isRTTIKind(getKind()); } |
151 | |
152 | GlobalDecl getGlobalDecl() const { |
153 | (0) . __assert_fail ("isUsedFunctionPointerKind() && \"GlobalDecl can be created only from virtual function\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 154, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isUsedFunctionPointerKind() && |
154 | (0) . __assert_fail ("isUsedFunctionPointerKind() && \"GlobalDecl can be created only from virtual function\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 154, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "GlobalDecl can be created only from virtual function"); |
155 | |
156 | auto *DtorDecl = dyn_cast<CXXDestructorDecl>(getFunctionDecl()); |
157 | switch (getKind()) { |
158 | case CK_FunctionPointer: |
159 | return GlobalDecl(getFunctionDecl()); |
160 | case CK_CompleteDtorPointer: |
161 | return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Complete); |
162 | case CK_DeletingDtorPointer: |
163 | return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Deleting); |
164 | case CK_VCallOffset: |
165 | case CK_VBaseOffset: |
166 | case CK_OffsetToTop: |
167 | case CK_RTTI: |
168 | case CK_UnusedFunctionPointer: |
169 | llvm_unreachable("Only function pointers kinds"); |
170 | } |
171 | llvm_unreachable("Should already return"); |
172 | } |
173 | |
174 | private: |
175 | static bool isFunctionPointerKind(Kind ComponentKind) { |
176 | return isUsedFunctionPointerKind(ComponentKind) || |
177 | ComponentKind == CK_UnusedFunctionPointer; |
178 | } |
179 | static bool isUsedFunctionPointerKind(Kind ComponentKind) { |
180 | return ComponentKind == CK_FunctionPointer || |
181 | isDestructorKind(ComponentKind); |
182 | } |
183 | static bool isDestructorKind(Kind ComponentKind) { |
184 | return ComponentKind == CK_CompleteDtorPointer || |
185 | ComponentKind == CK_DeletingDtorPointer; |
186 | } |
187 | static bool isRTTIKind(Kind ComponentKind) { |
188 | return ComponentKind == CK_RTTI; |
189 | } |
190 | |
191 | VTableComponent(Kind ComponentKind, CharUnits Offset) { |
192 | (0) . __assert_fail ("(ComponentKind == CK_VCallOffset || ComponentKind == CK_VBaseOffset || ComponentKind == CK_OffsetToTop) && \"Invalid component kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 194, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert((ComponentKind == CK_VCallOffset || |
193 | (0) . __assert_fail ("(ComponentKind == CK_VCallOffset || ComponentKind == CK_VBaseOffset || ComponentKind == CK_OffsetToTop) && \"Invalid component kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 194, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> ComponentKind == CK_VBaseOffset || |
194 | (0) . __assert_fail ("(ComponentKind == CK_VCallOffset || ComponentKind == CK_VBaseOffset || ComponentKind == CK_OffsetToTop) && \"Invalid component kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 194, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> ComponentKind == CK_OffsetToTop) && "Invalid component kind!"); |
195 | (0) . __assert_fail ("Offset.getQuantity() < (1LL << 56) && \"Offset is too big!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 195, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Offset.getQuantity() < (1LL << 56) && "Offset is too big!"); |
196 | (0) . __assert_fail ("Offset.getQuantity() >= -(1LL << 56) && \"Offset is too small!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 196, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Offset.getQuantity() >= -(1LL << 56) && "Offset is too small!"); |
197 | |
198 | Value = (uint64_t(Offset.getQuantity()) << 3) | ComponentKind; |
199 | } |
200 | |
201 | VTableComponent(Kind ComponentKind, uintptr_t Ptr) { |
202 | (0) . __assert_fail ("(isRTTIKind(ComponentKind) || isFunctionPointerKind(ComponentKind)) && \"Invalid component kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 203, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert((isRTTIKind(ComponentKind) || isFunctionPointerKind(ComponentKind)) && |
203 | (0) . __assert_fail ("(isRTTIKind(ComponentKind) || isFunctionPointerKind(ComponentKind)) && \"Invalid component kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 203, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "Invalid component kind!"); |
204 | |
205 | (0) . __assert_fail ("(Ptr & 7) == 0 && \"Pointer not sufficiently aligned!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 205, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!"); |
206 | |
207 | Value = Ptr | ComponentKind; |
208 | } |
209 | |
210 | CharUnits getOffset() const { |
211 | (0) . __assert_fail ("(getKind() == CK_VCallOffset || getKind() == CK_VBaseOffset || getKind() == CK_OffsetToTop) && \"Invalid component kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 212, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert((getKind() == CK_VCallOffset || getKind() == CK_VBaseOffset || |
212 | (0) . __assert_fail ("(getKind() == CK_VCallOffset || getKind() == CK_VBaseOffset || getKind() == CK_OffsetToTop) && \"Invalid component kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 212, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> getKind() == CK_OffsetToTop) && "Invalid component kind!"); |
213 | |
214 | return CharUnits::fromQuantity(Value >> 3); |
215 | } |
216 | |
217 | uintptr_t getPointer() const { |
218 | (0) . __assert_fail ("(getKind() == CK_RTTI || isFunctionPointerKind()) && \"Invalid component kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 219, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert((getKind() == CK_RTTI || isFunctionPointerKind()) && |
219 | (0) . __assert_fail ("(getKind() == CK_RTTI || isFunctionPointerKind()) && \"Invalid component kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 219, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "Invalid component kind!"); |
220 | |
221 | return static_cast<uintptr_t>(Value & ~7ULL); |
222 | } |
223 | |
224 | |
225 | |
226 | |
227 | |
228 | |
229 | int64_t Value; |
230 | }; |
231 | |
232 | class VTableLayout { |
233 | public: |
234 | typedef std::pair<uint64_t, ThunkInfo> VTableThunkTy; |
235 | struct AddressPointLocation { |
236 | unsigned VTableIndex, AddressPointIndex; |
237 | }; |
238 | typedef llvm::DenseMap<BaseSubobject, AddressPointLocation> |
239 | AddressPointsMapTy; |
240 | |
241 | private: |
242 | |
243 | |
244 | |
245 | |
246 | OwningArrayRef<size_t> VTableIndices; |
247 | |
248 | OwningArrayRef<VTableComponent> VTableComponents; |
249 | |
250 | |
251 | OwningArrayRef<VTableThunkTy> VTableThunks; |
252 | |
253 | |
254 | AddressPointsMapTy AddressPoints; |
255 | |
256 | public: |
257 | VTableLayout(ArrayRef<size_t> VTableIndices, |
258 | ArrayRef<VTableComponent> VTableComponents, |
259 | ArrayRef<VTableThunkTy> VTableThunks, |
260 | const AddressPointsMapTy &AddressPoints); |
261 | ~VTableLayout(); |
262 | |
263 | ArrayRef<VTableComponent> vtable_components() const { |
264 | return VTableComponents; |
265 | } |
266 | |
267 | ArrayRef<VTableThunkTy> vtable_thunks() const { |
268 | return VTableThunks; |
269 | } |
270 | |
271 | AddressPointLocation getAddressPoint(BaseSubobject Base) const { |
272 | (0) . __assert_fail ("AddressPoints.count(Base) && \"Did not find address point!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 272, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(AddressPoints.count(Base) && "Did not find address point!"); |
273 | return AddressPoints.find(Base)->second; |
274 | } |
275 | |
276 | const AddressPointsMapTy &getAddressPoints() const { |
277 | return AddressPoints; |
278 | } |
279 | |
280 | size_t getNumVTables() const { |
281 | if (VTableIndices.empty()) |
282 | return 1; |
283 | return VTableIndices.size(); |
284 | } |
285 | |
286 | size_t getVTableOffset(size_t i) const { |
287 | if (VTableIndices.empty()) { |
288 | assert(i == 0); |
289 | return 0; |
290 | } |
291 | return VTableIndices[i]; |
292 | } |
293 | |
294 | size_t getVTableSize(size_t i) const { |
295 | if (VTableIndices.empty()) { |
296 | assert(i == 0); |
297 | return vtable_components().size(); |
298 | } |
299 | |
300 | size_t thisIndex = VTableIndices[i]; |
301 | size_t nextIndex = (i + 1 == VTableIndices.size()) |
302 | ? vtable_components().size() |
303 | : VTableIndices[i + 1]; |
304 | return nextIndex - thisIndex; |
305 | } |
306 | }; |
307 | |
308 | class VTableContextBase { |
309 | public: |
310 | typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy; |
311 | |
312 | bool isMicrosoft() const { return IsMicrosoftABI; } |
313 | |
314 | virtual ~VTableContextBase() {} |
315 | |
316 | protected: |
317 | typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy; |
318 | |
319 | |
320 | ThunksMapTy Thunks; |
321 | |
322 | |
323 | |
324 | virtual void computeVTableRelatedInformation(const CXXRecordDecl *RD) = 0; |
325 | |
326 | VTableContextBase(bool MS) : IsMicrosoftABI(MS) {} |
327 | |
328 | public: |
329 | virtual const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) { |
330 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()->getCanonicalDecl()); |
331 | computeVTableRelatedInformation(MD->getParent()); |
332 | |
333 | |
334 | |
335 | ThunksMapTy::const_iterator I = Thunks.find(MD); |
336 | if (I == Thunks.end()) { |
337 | |
338 | return nullptr; |
339 | } |
340 | |
341 | return &I->second; |
342 | } |
343 | |
344 | bool IsMicrosoftABI; |
345 | }; |
346 | |
347 | class ItaniumVTableContext : public VTableContextBase { |
348 | private: |
349 | |
350 | |
351 | |
352 | typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy; |
353 | MethodVTableIndicesTy MethodVTableIndices; |
354 | |
355 | typedef llvm::DenseMap<const CXXRecordDecl *, |
356 | std::unique_ptr<const VTableLayout>> |
357 | VTableLayoutMapTy; |
358 | VTableLayoutMapTy VTableLayouts; |
359 | |
360 | typedef std::pair<const CXXRecordDecl *, |
361 | const CXXRecordDecl *> ClassPairTy; |
362 | |
363 | |
364 | |
365 | |
366 | |
367 | typedef llvm::DenseMap<ClassPairTy, CharUnits> |
368 | VirtualBaseClassOffsetOffsetsMapTy; |
369 | VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets; |
370 | |
371 | void computeVTableRelatedInformation(const CXXRecordDecl *RD) override; |
372 | |
373 | public: |
374 | ItaniumVTableContext(ASTContext &Context); |
375 | ~ItaniumVTableContext() override; |
376 | |
377 | const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) { |
378 | computeVTableRelatedInformation(RD); |
379 | (0) . __assert_fail ("VTableLayouts.count(RD) && \"No layout for this record decl!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/VTableBuilder.h", 379, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(VTableLayouts.count(RD) && "No layout for this record decl!"); |
380 | |
381 | return *VTableLayouts[RD]; |
382 | } |
383 | |
384 | std::unique_ptr<VTableLayout> createConstructionVTableLayout( |
385 | const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset, |
386 | bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass); |
387 | |
388 | |
389 | |
390 | |
391 | |
392 | uint64_t getMethodVTableIndex(GlobalDecl GD); |
393 | |
394 | |
395 | |
396 | |
397 | |
398 | |
399 | CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, |
400 | const CXXRecordDecl *VBase); |
401 | |
402 | static bool classof(const VTableContextBase *VT) { |
403 | return !VT->isMicrosoft(); |
404 | } |
405 | }; |
406 | |
407 | |
408 | |
409 | |
410 | struct VPtrInfo { |
411 | typedef SmallVector<const CXXRecordDecl *, 1> BasePath; |
412 | |
413 | VPtrInfo(const CXXRecordDecl *RD) |
414 | : ObjectWithVPtr(RD), IntroducingObject(RD), NextBaseToMangle(RD) {} |
415 | |
416 | |
417 | |
418 | |
419 | const CXXRecordDecl *ObjectWithVPtr; |
420 | |
421 | |
422 | |
423 | const CXXRecordDecl *IntroducingObject; |
424 | |
425 | |
426 | |
427 | CharUnits NonVirtualOffset; |
428 | |
429 | |
430 | |
431 | |
432 | |
433 | BasePath MangledPath; |
434 | |
435 | |
436 | |
437 | const CXXRecordDecl *NextBaseToMangle; |
438 | |
439 | |
440 | |
441 | |
442 | BasePath ContainingVBases; |
443 | |
444 | |
445 | |
446 | |
447 | BasePath PathToIntroducingObject; |
448 | |
449 | |
450 | |
451 | CharUnits FullOffsetInMDC; |
452 | |
453 | |
454 | const CXXRecordDecl *getVBaseWithVPtr() const { |
455 | return ContainingVBases.empty() ? nullptr : ContainingVBases.front(); |
456 | } |
457 | }; |
458 | |
459 | typedef SmallVector<std::unique_ptr<VPtrInfo>, 2> VPtrInfoVector; |
460 | |
461 | |
462 | |
463 | |
464 | struct VirtualBaseInfo { |
465 | |
466 | |
467 | llvm::DenseMap<const CXXRecordDecl *, unsigned> VBTableIndices; |
468 | |
469 | |
470 | |
471 | VPtrInfoVector VBPtrPaths; |
472 | }; |
473 | |
474 | struct MethodVFTableLocation { |
475 | |
476 | uint64_t VBTableIndex; |
477 | |
478 | |
479 | |
480 | const CXXRecordDecl *VBase; |
481 | |
482 | |
483 | |
484 | CharUnits VFPtrOffset; |
485 | |
486 | |
487 | uint64_t Index; |
488 | |
489 | MethodVFTableLocation() |
490 | : VBTableIndex(0), VBase(nullptr), VFPtrOffset(CharUnits::Zero()), |
491 | Index(0) {} |
492 | |
493 | MethodVFTableLocation(uint64_t VBTableIndex, const CXXRecordDecl *VBase, |
494 | CharUnits VFPtrOffset, uint64_t Index) |
495 | : VBTableIndex(VBTableIndex), VBase(VBase), VFPtrOffset(VFPtrOffset), |
496 | Index(Index) {} |
497 | |
498 | bool operator<(const MethodVFTableLocation &other) const { |
499 | if (VBTableIndex != other.VBTableIndex) { |
500 | assert(VBase != other.VBase); |
501 | return VBTableIndex < other.VBTableIndex; |
502 | } |
503 | return std::tie(VFPtrOffset, Index) < |
504 | std::tie(other.VFPtrOffset, other.Index); |
505 | } |
506 | }; |
507 | |
508 | class MicrosoftVTableContext : public VTableContextBase { |
509 | public: |
510 | |
511 | private: |
512 | ASTContext &Context; |
513 | |
514 | typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation> |
515 | MethodVFTableLocationsTy; |
516 | MethodVFTableLocationsTy MethodVFTableLocations; |
517 | |
518 | typedef llvm::DenseMap<const CXXRecordDecl *, std::unique_ptr<VPtrInfoVector>> |
519 | VFPtrLocationsMapTy; |
520 | VFPtrLocationsMapTy VFPtrLocations; |
521 | |
522 | typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy; |
523 | typedef llvm::DenseMap<VFTableIdTy, std::unique_ptr<const VTableLayout>> |
524 | VFTableLayoutMapTy; |
525 | VFTableLayoutMapTy VFTableLayouts; |
526 | |
527 | llvm::DenseMap<const CXXRecordDecl *, std::unique_ptr<VirtualBaseInfo>> |
528 | VBaseInfo; |
529 | |
530 | void enumerateVFPtrs(const CXXRecordDecl *ForClass, VPtrInfoVector &Result); |
531 | |
532 | void computeVTableRelatedInformation(const CXXRecordDecl *RD) override; |
533 | |
534 | void dumpMethodLocations(const CXXRecordDecl *RD, |
535 | const MethodVFTableLocationsTy &NewMethods, |
536 | raw_ostream &); |
537 | |
538 | const VirtualBaseInfo & |
539 | computeVBTableRelatedInformation(const CXXRecordDecl *RD); |
540 | |
541 | void computeVTablePaths(bool ForVBTables, const CXXRecordDecl *RD, |
542 | VPtrInfoVector &Paths); |
543 | |
544 | public: |
545 | MicrosoftVTableContext(ASTContext &Context) |
546 | : VTableContextBase(), Context(Context) {} |
547 | |
548 | ~MicrosoftVTableContext() override; |
549 | |
550 | const VPtrInfoVector &getVFPtrOffsets(const CXXRecordDecl *RD); |
551 | |
552 | const VTableLayout &getVFTableLayout(const CXXRecordDecl *RD, |
553 | CharUnits VFPtrOffset); |
554 | |
555 | MethodVFTableLocation getMethodVFTableLocation(GlobalDecl GD); |
556 | |
557 | const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) override { |
558 | |
559 | if (isa<CXXDestructorDecl>(GD.getDecl()) && |
560 | GD.getDtorType() == Dtor_Complete) |
561 | return nullptr; |
562 | return VTableContextBase::getThunkInfo(GD); |
563 | } |
564 | |
565 | |
566 | |
567 | |
568 | |
569 | unsigned getVBTableIndex(const CXXRecordDecl *Derived, |
570 | const CXXRecordDecl *VBase); |
571 | |
572 | const VPtrInfoVector &enumerateVBTables(const CXXRecordDecl *RD); |
573 | |
574 | static bool classof(const VTableContextBase *VT) { return VT->isMicrosoft(); } |
575 | }; |
576 | |
577 | } |
578 | |
579 | #endif |
580 | |