blob: 70c9c6c8eeda3682e5684fcafcacd0f1249b948c [file] [log] [blame]
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001//===--- CGVtable.cpp - Emit LLVM Code for C++ vtables --------------------===//
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 C++ code generation of virtual tables.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CodeGenModule.h"
15#include "CodeGenFunction.h"
Anders Carlssonf942ee02009-11-27 20:47:55 +000016#include "clang/AST/CXXInheritance.h"
Anders Carlsson2bb27f52009-10-11 22:13:54 +000017#include "clang/AST/RecordLayout.h"
Anders Carlssond420a312009-11-26 19:32:45 +000018#include "llvm/ADT/DenseSet.h"
Anders Carlsson5d40c6f2010-02-11 08:02:13 +000019#include "llvm/Support/Format.h"
Zhongxing Xu1721ef72009-11-13 05:46:16 +000020#include <cstdio>
Anders Carlsson2bb27f52009-10-11 22:13:54 +000021
22using namespace clang;
23using namespace CodeGen;
24
Anders Carlsson727ffb12010-02-11 19:39:49 +000025/// TypeConversionRequiresAdjustment - Returns whether conversion from a
26/// derived type to a base type requires adjustment.
27static bool
28TypeConversionRequiresAdjustment(ASTContext &Ctx,
29 const CXXRecordDecl *DerivedDecl,
30 const CXXRecordDecl *BaseDecl) {
31 CXXBasePaths Paths(/*FindAmbiguities=*/false,
32 /*RecordPaths=*/true, /*DetectVirtual=*/true);
33 if (!const_cast<CXXRecordDecl *>(DerivedDecl)->
34 isDerivedFrom(const_cast<CXXRecordDecl *>(BaseDecl), Paths)) {
35 assert(false && "Class must be derived from the passed in base class!");
36 return false;
37 }
38
39 // If we found a virtual base we always want to require adjustment.
40 if (Paths.getDetectedVirtual())
41 return true;
42
43 const CXXBasePath &Path = Paths.front();
44
45 for (size_t Start = 0, End = Path.size(); Start != End; ++Start) {
46 const CXXBasePathElement &Element = Path[Start];
47
48 // Check the base class offset.
49 const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Element.Class);
50
51 const RecordType *BaseType = Element.Base->getType()->getAs<RecordType>();
52 const CXXRecordDecl *Base = cast<CXXRecordDecl>(BaseType->getDecl());
53
54 if (Layout.getBaseClassOffset(Base) != 0) {
55 // This requires an adjustment.
56 return true;
57 }
58 }
59
60 return false;
61}
62
63static bool
64TypeConversionRequiresAdjustment(ASTContext &Ctx,
65 QualType DerivedType, QualType BaseType) {
66 // Canonicalize the types.
67 QualType CanDerivedType = Ctx.getCanonicalType(DerivedType);
68 QualType CanBaseType = Ctx.getCanonicalType(BaseType);
69
70 assert(CanDerivedType->getTypeClass() == CanBaseType->getTypeClass() &&
71 "Types must have same type class!");
72
73 if (CanDerivedType == CanBaseType) {
74 // No adjustment needed.
75 return false;
76 }
77
Anders Carlssondd27b5d2010-02-11 19:45:15 +000078 if (const ReferenceType *RT = CanDerivedType->getAs<ReferenceType>()) {
Anders Carlsson727ffb12010-02-11 19:39:49 +000079 CanDerivedType = RT->getPointeeType();
Anders Carlssondd27b5d2010-02-11 19:45:15 +000080 CanBaseType = CanBaseType->getAs<ReferenceType>()->getPointeeType();
81 } else if (const PointerType *PT = CanDerivedType->getAs<PointerType>()) {
Anders Carlsson727ffb12010-02-11 19:39:49 +000082 CanDerivedType = PT->getPointeeType();
Anders Carlssondd27b5d2010-02-11 19:45:15 +000083 CanBaseType = CanBaseType->getAs<PointerType>()->getPointeeType();
Anders Carlsson727ffb12010-02-11 19:39:49 +000084 } else {
85 assert(false && "Unexpected return type!");
86 }
87
88 if (CanDerivedType == CanBaseType) {
89 // No adjustment needed.
90 return false;
91 }
92
93 const CXXRecordDecl *DerivedDecl =
Anders Carlssondd27b5d2010-02-11 19:45:15 +000094 cast<CXXRecordDecl>(CanDerivedType->getAs<RecordType>()->getDecl());
Anders Carlsson727ffb12010-02-11 19:39:49 +000095
96 const CXXRecordDecl *BaseDecl =
Anders Carlssondd27b5d2010-02-11 19:45:15 +000097 cast<CXXRecordDecl>(CanBaseType->getAs<RecordType>()->getDecl());
Anders Carlsson727ffb12010-02-11 19:39:49 +000098
99 return TypeConversionRequiresAdjustment(Ctx, DerivedDecl, BaseDecl);
100}
101
Anders Carlssond59885022009-11-27 22:21:51 +0000102namespace {
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000103
104/// VtableComponent - Represents a single component in a vtable.
105class VtableComponent {
106public:
107 enum Kind {
108 CK_VCallOffset,
109 CK_VBaseOffset,
110 CK_OffsetToTop,
111 CK_RTTI,
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000112 CK_FunctionPointer,
113
114 /// CK_CompleteDtorPointer - A pointer to the complete destructor.
115 CK_CompleteDtorPointer,
116
117 /// CK_DeletingDtorPointer - A pointer to the deleting destructor.
118 CK_DeletingDtorPointer
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000119 };
120
121 /// dump - Dump the contents of this component to the given stream.
122 void dump(llvm::raw_ostream &Out);
123
124 static VtableComponent MakeOffsetToTop(int64_t Offset) {
125 return VtableComponent(CK_OffsetToTop, Offset);
126 }
127
128 static VtableComponent MakeRTTI(const CXXRecordDecl *RD) {
129 return VtableComponent(CK_RTTI, reinterpret_cast<uintptr_t>(RD));
130 }
131
132 static VtableComponent MakeFunction(const CXXMethodDecl *MD) {
133 assert(!isa<CXXDestructorDecl>(MD) &&
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000134 "Don't use MakeFunction with destructors!");
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000135
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000136 return VtableComponent(CK_FunctionPointer,
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000137 reinterpret_cast<uintptr_t>(MD));
138 }
139
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000140 static VtableComponent MakeCompleteDtor(const CXXDestructorDecl *DD) {
141 return VtableComponent(CK_CompleteDtorPointer,
142 reinterpret_cast<uintptr_t>(DD));
143 }
144
145 static VtableComponent MakeDeletingDtor(const CXXDestructorDecl *DD) {
146 return VtableComponent(CK_DeletingDtorPointer,
147 reinterpret_cast<uintptr_t>(DD));
148 }
149
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000150 /// getKind - Get the kind of this vtable component.
151 Kind getKind() const {
152 return (Kind)(Value & 0x7);
153 }
154
155 int64_t getOffsetToTop() const {
156 assert(getKind() == CK_OffsetToTop && "Invalid component kind!");
157
158 return getOffset();
159 }
160
161 const CXXRecordDecl *getRTTIDecl() const {
162 assert(getKind() == CK_RTTI && "Invalid component kind!");
163
164 return reinterpret_cast<CXXRecordDecl *>(getPointer());
165 }
166
167 const CXXMethodDecl *getFunctionDecl() const {
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000168 assert(getKind() == CK_FunctionPointer);
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000169
170 return reinterpret_cast<CXXMethodDecl *>(getPointer());
171 }
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000172
173 const CXXDestructorDecl *getDestructorDecl() const {
174 assert((getKind() == CK_CompleteDtorPointer ||
175 getKind() == CK_DeletingDtorPointer) && "Invalid component kind!");
176
177 return reinterpret_cast<CXXDestructorDecl *>(getPointer());
178 }
179
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000180private:
181 VtableComponent(Kind ComponentKind, int64_t Offset) {
182 assert((ComponentKind == CK_VCallOffset ||
183 ComponentKind == CK_VBaseOffset ||
184 ComponentKind == CK_OffsetToTop) && "Invalid component kind!");
185 assert(Offset <= ((1LL << 56) - 1) && "Offset is too big!");
186
187 Value = ((Offset << 3) | ComponentKind);
188 }
189
190 VtableComponent(Kind ComponentKind, uintptr_t Ptr) {
191 assert((ComponentKind == CK_RTTI ||
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000192 ComponentKind == CK_FunctionPointer ||
193 ComponentKind == CK_CompleteDtorPointer ||
194 ComponentKind == CK_DeletingDtorPointer) &&
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000195 "Invalid component kind!");
196
197 assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!");
198
199 Value = Ptr | ComponentKind;
200 }
201
202 int64_t getOffset() const {
203 assert((getKind() == CK_VCallOffset || getKind() == CK_VBaseOffset ||
204 getKind() == CK_OffsetToTop) && "Invalid component kind!");
205
206 return Value >> 3;
207 }
208
209 uintptr_t getPointer() const {
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000210 assert((getKind() == CK_RTTI ||
211 getKind() == CK_FunctionPointer ||
212 getKind() == CK_CompleteDtorPointer ||
213 getKind() == CK_DeletingDtorPointer) &&
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000214 "Invalid component kind!");
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000215
216 return static_cast<uintptr_t>(Value & ~7ULL);
217 }
218
219 /// The kind is stored in the lower 3 bits of the value. For offsets, we
220 /// make use of the facts that classes can't be larger than 2^55 bytes,
221 /// so we store the offset in the lower part of the 61 bytes that remain.
222 /// (The reason that we're not simply using a PointerIntPair here is that we
223 /// need the offsets to be 64-bit, even when on a 32-bit machine).
224 int64_t Value;
225};
226
227/// VtableBuilder - Class for building vtable layout information.
Benjamin Kramer337e3a52009-11-28 19:45:26 +0000228class VtableBuilder {
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000229 /// MostDerivedClass - The most derived class for which we're building this
230 /// vtable.
231 const CXXRecordDecl *MostDerivedClass;
232
233 /// Context - The ASTContext which we will use for layout information.
234 const ASTContext &Context;
235
236 /// Components - The components of the vtable being built.
237 llvm::SmallVector<VtableComponent, 64> Components;
238
Anders Carlsson932c2f22010-02-11 17:18:51 +0000239 /// AddressPoints - Address points for the vtable being built.
240 CGVtableInfo::AddressPointsMapTy AddressPoints;
241
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000242 /// layoutSimpleVtable - A test function that will layout very simple vtables
243 /// without any bases. Just used for testing for now.
244 void layoutSimpleVtable(const CXXRecordDecl *RD);
245
246public:
247 VtableBuilder(const CXXRecordDecl *MostDerivedClass)
248 : MostDerivedClass(MostDerivedClass),
249 Context(MostDerivedClass->getASTContext()) {
250
251 layoutSimpleVtable(MostDerivedClass);
252 }
253
254 /// dumpLayout - Dump the vtable layout.
255 void dumpLayout(llvm::raw_ostream&);
256
257};
258
259void VtableBuilder::layoutSimpleVtable(const CXXRecordDecl *RD) {
260 assert(!RD->getNumBases() &&
261 "We don't support layout for vtables with bases right now!");
262
263 // First, add the offset to top.
264 Components.push_back(VtableComponent::MakeOffsetToTop(0));
265
266 // Next, add the RTTI.
267 Components.push_back(VtableComponent::MakeRTTI(RD));
268
Anders Carlsson932c2f22010-02-11 17:18:51 +0000269 // Record the address point.
270 AddressPoints.insert(std::make_pair(BaseSubobject(RD, 0), Components.size()));
271
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000272 // Now go through all virtual member functions and add them.
273 for (CXXRecordDecl::method_iterator I = RD->method_begin(),
274 E = RD->method_end(); I != E; ++I) {
275 const CXXMethodDecl *MD = *I;
276
277 if (!MD->isVirtual())
278 continue;
279
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000280 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
281 // Add both the complete destructor and the deleting destructor.
282 Components.push_back(VtableComponent::MakeCompleteDtor(DD));
283 Components.push_back(VtableComponent::MakeDeletingDtor(DD));
284 } else {
285 // Add the function.
286 Components.push_back(VtableComponent::MakeFunction(MD));
287 }
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000288 }
289}
290
291/// dumpLayout - Dump the vtable layout.
292void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
293
294 Out << "Vtable for '" << MostDerivedClass->getQualifiedNameAsString();
295 Out << "' (" << Components.size() << " entries).\n";
296
Anders Carlsson932c2f22010-02-11 17:18:51 +0000297 // Iterate through the address points and insert them into a new map where
298 // they are keyed by the index and not the base object.
299 // Since an address point can be shared by multiple subobjects, we use an
300 // STL multimap.
301 std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
302 for (CGVtableInfo::AddressPointsMapTy::const_iterator I =
303 AddressPoints.begin(), E = AddressPoints.end(); I != E; ++I) {
304 const BaseSubobject& Base = I->first;
305 uint64_t Index = I->second;
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000306
Anders Carlsson932c2f22010-02-11 17:18:51 +0000307 AddressPointsByIndex.insert(std::make_pair(Index, Base));
308 }
309
310 for (unsigned I = 0, E = Components.size(); I != E; ++I) {
311 if (AddressPointsByIndex.count(I)) {
312 assert(AddressPointsByIndex.count(I) == 1 &&
313 "FIXME: Handle dumping multiple base subobjects for a single "
314 "address point!");
315
316 const BaseSubobject &Base = AddressPointsByIndex.find(I)->second;
317 Out << " -- (" << Base.getBase()->getQualifiedNameAsString();
318
319 // FIXME: Instead of dividing by 8, we should be using CharUnits.
320 Out << ", " << Base.getBaseOffset() / 8 << ") vtable address --\n";
321 }
322
323 Out << llvm::format("%4d | ", I);
324
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000325 const VtableComponent &Component = Components[I];
326
327 // Dump the component.
328 switch (Component.getKind()) {
329 // FIXME: Remove this default case.
330 default:
331 assert(false && "Unhandled component kind!");
332 break;
333
334 case VtableComponent::CK_OffsetToTop:
335 Out << "offset_to_top (" << Component.getOffsetToTop() << ")";
336 break;
337
338 case VtableComponent::CK_RTTI:
339 Out << Component.getRTTIDecl()->getQualifiedNameAsString() << " RTTI";
340 break;
341
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000342 case VtableComponent::CK_FunctionPointer: {
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000343 const CXXMethodDecl *MD = Component.getFunctionDecl();
344
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000345 std::string Str =
346 PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
347 MD);
348 Out << Str;
349 break;
350 }
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000351
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000352 case VtableComponent::CK_CompleteDtorPointer: {
353 const CXXDestructorDecl *DD = Component.getDestructorDecl();
354
355 Out << DD->getQualifiedNameAsString() << "() [complete]";
356 break;
357 }
358
359 case VtableComponent::CK_DeletingDtorPointer: {
360 const CXXDestructorDecl *DD = Component.getDestructorDecl();
361
362 Out << DD->getQualifiedNameAsString() << "() [deleting]";
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000363 break;
364 }
365
366 }
Anders Carlsson932c2f22010-02-11 17:18:51 +0000367
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000368 Out << '\n';
369 }
370
371}
372
373}
374
375namespace {
376class OldVtableBuilder {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000377public:
378 /// Index_t - Vtable index type.
379 typedef uint64_t Index_t;
Eli Friedman31bc3ad2009-12-07 23:56:34 +0000380 typedef std::vector<std::pair<GlobalDecl,
381 std::pair<GlobalDecl, ThunkAdjustment> > >
382 SavedAdjustmentsVectorTy;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000383private:
Anders Carlsson472404f2009-12-04 16:19:30 +0000384
Anders Carlssonfe5f7d92009-12-06 01:09:21 +0000385 // VtableComponents - The components of the vtable being built.
386 typedef llvm::SmallVector<llvm::Constant *, 64> VtableComponentsVectorTy;
387 VtableComponentsVectorTy VtableComponents;
388
Eli Friedman6c08ce72009-12-05 01:05:03 +0000389 const bool BuildVtable;
390
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000391 llvm::Type *Ptr8Ty;
Anders Carlssonbad80eb2009-12-04 18:36:22 +0000392
393 /// MostDerivedClass - The most derived class that this vtable is being
394 /// built for.
395 const CXXRecordDecl *MostDerivedClass;
396
Mike Stump83066c82009-11-13 01:54:23 +0000397 /// LayoutClass - The most derived class used for virtual base layout
398 /// information.
399 const CXXRecordDecl *LayoutClass;
Mike Stump653d0b92009-11-13 02:13:54 +0000400 /// LayoutOffset - The offset for Class in LayoutClass.
401 uint64_t LayoutOffset;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000402 /// BLayout - Layout for the most derived class that this vtable is being
403 /// built for.
404 const ASTRecordLayout &BLayout;
405 llvm::SmallSet<const CXXRecordDecl *, 32> IndirectPrimary;
406 llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase;
407 llvm::Constant *rtti;
408 llvm::LLVMContext &VMContext;
409 CodeGenModule &CGM; // Per-module state.
Anders Carlssonf2f31f42009-12-04 03:46:21 +0000410
Mike Stump90181eb2010-01-26 00:05:04 +0000411 llvm::DenseMap<const CXXMethodDecl *, Index_t> VCall;
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000412 llvm::DenseMap<GlobalDecl, Index_t> VCallOffset;
Mike Stump77537b12010-01-26 03:42:22 +0000413 llvm::DenseMap<GlobalDecl, Index_t> VCallOffsetForVCall;
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000414 // This is the offset to the nearest virtual base
Mike Stump90181eb2010-01-26 00:05:04 +0000415 llvm::DenseMap<const CXXMethodDecl *, Index_t> NonVirtualOffset;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000416 llvm::DenseMap<const CXXRecordDecl *, Index_t> VBIndex;
Mike Stumpbb9ff052009-10-27 23:46:47 +0000417
Anders Carlsson323bb042009-11-26 19:54:33 +0000418 /// PureVirtualFunction - Points to __cxa_pure_virtual.
419 llvm::Constant *PureVirtualFn;
420
Anders Carlssona84b6e82009-12-04 02:01:07 +0000421 /// VtableMethods - A data structure for keeping track of methods in a vtable.
422 /// Can add methods, override methods and iterate in vtable order.
423 class VtableMethods {
424 // MethodToIndexMap - Maps from a global decl to the index it has in the
425 // Methods vector.
426 llvm::DenseMap<GlobalDecl, uint64_t> MethodToIndexMap;
427
428 /// Methods - The methods, in vtable order.
429 typedef llvm::SmallVector<GlobalDecl, 16> MethodsVectorTy;
430 MethodsVectorTy Methods;
Eli Friedman8174f2c2009-12-06 22:01:30 +0000431 MethodsVectorTy OrigMethods;
Anders Carlssona84b6e82009-12-04 02:01:07 +0000432
433 public:
434 /// AddMethod - Add a method to the vtable methods.
435 void AddMethod(GlobalDecl GD) {
436 assert(!MethodToIndexMap.count(GD) &&
437 "Method has already been added!");
438
439 MethodToIndexMap[GD] = Methods.size();
440 Methods.push_back(GD);
Eli Friedman8174f2c2009-12-06 22:01:30 +0000441 OrigMethods.push_back(GD);
Anders Carlssona84b6e82009-12-04 02:01:07 +0000442 }
443
444 /// OverrideMethod - Replace a method with another.
445 void OverrideMethod(GlobalDecl OverriddenGD, GlobalDecl GD) {
446 llvm::DenseMap<GlobalDecl, uint64_t>::iterator i
447 = MethodToIndexMap.find(OverriddenGD);
448 assert(i != MethodToIndexMap.end() && "Did not find entry!");
449
450 // Get the index of the old decl.
451 uint64_t Index = i->second;
452
453 // Replace the old decl with the new decl.
454 Methods[Index] = GD;
455
Anders Carlssona84b6e82009-12-04 02:01:07 +0000456 // And add the new.
457 MethodToIndexMap[GD] = Index;
458 }
459
Anders Carlsson7bb70762009-12-04 15:49:02 +0000460 /// getIndex - Gives the index of a passed in GlobalDecl. Returns false if
461 /// the index couldn't be found.
Benjamin Kramer62ab6162009-12-04 22:45:27 +0000462 bool getIndex(GlobalDecl GD, uint64_t &Index) const {
Anders Carlsson7bb70762009-12-04 15:49:02 +0000463 llvm::DenseMap<GlobalDecl, uint64_t>::const_iterator i
464 = MethodToIndexMap.find(GD);
Eli Friedman3d2e9de2009-12-04 08:34:14 +0000465
Anders Carlsson7bb70762009-12-04 15:49:02 +0000466 if (i == MethodToIndexMap.end())
467 return false;
Anders Carlssone6096362009-12-04 03:41:37 +0000468
Anders Carlsson7bb70762009-12-04 15:49:02 +0000469 Index = i->second;
470 return true;
Anders Carlssone6096362009-12-04 03:41:37 +0000471 }
472
Eli Friedman8174f2c2009-12-06 22:01:30 +0000473 GlobalDecl getOrigMethod(uint64_t Index) const {
474 return OrigMethods[Index];
475 }
476
Anders Carlssona84b6e82009-12-04 02:01:07 +0000477 MethodsVectorTy::size_type size() const {
478 return Methods.size();
479 }
480
481 void clear() {
482 MethodToIndexMap.clear();
483 Methods.clear();
Eli Friedman8174f2c2009-12-06 22:01:30 +0000484 OrigMethods.clear();
Anders Carlssona84b6e82009-12-04 02:01:07 +0000485 }
486
Anders Carlssone6096362009-12-04 03:41:37 +0000487 GlobalDecl operator[](uint64_t Index) const {
Anders Carlssona84b6e82009-12-04 02:01:07 +0000488 return Methods[Index];
489 }
490 };
491
492 /// Methods - The vtable methods we're currently building.
493 VtableMethods Methods;
494
Anders Carlsson4c837d22009-12-04 02:26:15 +0000495 /// ThisAdjustments - For a given index in the vtable, contains the 'this'
496 /// pointer adjustment needed for a method.
497 typedef llvm::DenseMap<uint64_t, ThunkAdjustment> ThisAdjustmentsMapTy;
498 ThisAdjustmentsMapTy ThisAdjustments;
Anders Carlssond420a312009-11-26 19:32:45 +0000499
Eli Friedman31bc3ad2009-12-07 23:56:34 +0000500 SavedAdjustmentsVectorTy SavedAdjustments;
Eli Friedman8174f2c2009-12-06 22:01:30 +0000501
Anders Carlssonc521f952009-12-04 02:22:02 +0000502 /// BaseReturnTypes - Contains the base return types of methods who have been
503 /// overridden with methods whose return types require adjustment. Used for
504 /// generating covariant thunk information.
505 typedef llvm::DenseMap<uint64_t, CanQualType> BaseReturnTypesMapTy;
506 BaseReturnTypesMapTy BaseReturnTypes;
Anders Carlssond420a312009-11-26 19:32:45 +0000507
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000508 std::vector<Index_t> VCalls;
Mike Stump2cefe382009-11-12 20:47:57 +0000509
510 typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
Mike Stumpcd2b8212009-11-19 20:52:19 +0000511 // subAddressPoints - Used to hold the AddressPoints (offsets) into the built
512 // vtable for use in computing the initializers for the VTT.
513 llvm::DenseMap<CtorVtable_t, int64_t> &subAddressPoints;
Mike Stump2cefe382009-11-12 20:47:57 +0000514
Anders Carlsson5f9a8812010-01-14 02:29:07 +0000515 /// AddressPoints - Address points for this vtable.
516 CGVtableInfo::AddressPointsMapTy& AddressPoints;
517
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000518 typedef CXXRecordDecl::method_iterator method_iter;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000519 const uint32_t LLVMPointerWidth;
520 Index_t extra;
Mike Stump37dbe962009-10-15 02:04:03 +0000521 typedef std::vector<std::pair<const CXXRecordDecl *, int64_t> > Path_t;
Mike Stumpcd2b8212009-11-19 20:52:19 +0000522 static llvm::DenseMap<CtorVtable_t, int64_t>&
523 AllocAddressPoint(CodeGenModule &cgm, const CXXRecordDecl *l,
524 const CXXRecordDecl *c) {
Anders Carlsson93a18842010-01-02 18:02:32 +0000525 CGVtableInfo::AddrMap_t *&oref = cgm.getVtableInfo().AddressPoints[l];
Mike Stumpcd2b8212009-11-19 20:52:19 +0000526 if (oref == 0)
Anders Carlsson93a18842010-01-02 18:02:32 +0000527 oref = new CGVtableInfo::AddrMap_t;
Mike Stumpcd2b8212009-11-19 20:52:19 +0000528
529 llvm::DenseMap<CtorVtable_t, int64_t> *&ref = (*oref)[c];
530 if (ref == 0)
531 ref = new llvm::DenseMap<CtorVtable_t, int64_t>;
532 return *ref;
533 }
Anders Carlsson323bb042009-11-26 19:54:33 +0000534
Mike Stump90181eb2010-01-26 00:05:04 +0000535 bool DclIsSame(const FunctionDecl *New, const FunctionDecl *Old) {
536 FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
537 FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
538
539 // C++ [temp.fct]p2:
540 // A function template can be overloaded with other function templates
541 // and with normal (non-template) functions.
542 if ((OldTemplate == 0) != (NewTemplate == 0))
543 return false;
544
545 // Is the function New an overload of the function Old?
546 QualType OldQType = CGM.getContext().getCanonicalType(Old->getType());
547 QualType NewQType = CGM.getContext().getCanonicalType(New->getType());
548
549 // Compare the signatures (C++ 1.3.10) of the two functions to
550 // determine whether they are overloads. If we find any mismatch
551 // in the signature, they are overloads.
552
553 // If either of these functions is a K&R-style function (no
554 // prototype), then we consider them to have matching signatures.
555 if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) ||
556 isa<FunctionNoProtoType>(NewQType.getTypePtr()))
557 return true;
558
559 FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
560 FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
561
562 // The signature of a function includes the types of its
563 // parameters (C++ 1.3.10), which includes the presence or absence
564 // of the ellipsis; see C++ DR 357).
565 if (OldQType != NewQType &&
566 (OldType->getNumArgs() != NewType->getNumArgs() ||
567 OldType->isVariadic() != NewType->isVariadic() ||
568 !std::equal(OldType->arg_type_begin(), OldType->arg_type_end(),
569 NewType->arg_type_begin())))
570 return false;
571
572#if 0
573 // C++ [temp.over.link]p4:
574 // The signature of a function template consists of its function
575 // signature, its return type and its template parameter list. The names
576 // of the template parameters are significant only for establishing the
577 // relationship between the template parameters and the rest of the
578 // signature.
579 //
580 // We check the return type and template parameter lists for function
581 // templates first; the remaining checks follow.
582 if (NewTemplate &&
583 (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
584 OldTemplate->getTemplateParameters(),
585 TPL_TemplateMatch) ||
586 OldType->getResultType() != NewType->getResultType()))
587 return false;
588#endif
589
590 // If the function is a class member, its signature includes the
591 // cv-qualifiers (if any) on the function itself.
592 //
593 // As part of this, also check whether one of the member functions
594 // is static, in which case they are not overloads (C++
595 // 13.1p2). While not part of the definition of the signature,
596 // this check is important to determine whether these functions
597 // can be overloaded.
598 const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
599 const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
600 if (OldMethod && NewMethod &&
601 !OldMethod->isStatic() && !NewMethod->isStatic() &&
602 OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers())
603 return false;
604
605 // The signatures match; this is not an overload.
606 return true;
607 }
608
609 typedef llvm::DenseMap<const CXXMethodDecl *, const CXXMethodDecl*>
610 ForwardUnique_t;
611 ForwardUnique_t ForwardUnique;
612 llvm::DenseMap<const CXXMethodDecl*, const CXXMethodDecl*> UniqueOverrider;
613
614 void BuildUniqueOverrider(const CXXMethodDecl *U, const CXXMethodDecl *MD) {
615 const CXXMethodDecl *PrevU = UniqueOverrider[MD];
616 assert(U && "no unique overrider");
617 if (PrevU == U)
618 return;
619 if (PrevU != U && PrevU != 0) {
620 // If already set, note the two sets as the same
621 if (0)
622 printf("%s::%s same as %s::%s\n",
623 PrevU->getParent()->getNameAsCString(),
624 PrevU->getNameAsCString(),
625 U->getParent()->getNameAsCString(),
626 U->getNameAsCString());
627 ForwardUnique[PrevU] = U;
628 return;
629 }
630
631 // Not set, set it now
632 if (0)
633 printf("marking %s::%s %p override as %s::%s\n",
634 MD->getParent()->getNameAsCString(),
635 MD->getNameAsCString(),
636 (void*)MD,
637 U->getParent()->getNameAsCString(),
638 U->getNameAsCString());
639 UniqueOverrider[MD] = U;
640
641 for (CXXMethodDecl::method_iterator mi = MD->begin_overridden_methods(),
642 me = MD->end_overridden_methods(); mi != me; ++mi) {
643 BuildUniqueOverrider(U, *mi);
644 }
645 }
646
647 void BuildUniqueOverriders(const CXXRecordDecl *RD) {
648 if (0) printf("walking %s\n", RD->getNameAsCString());
649 for (CXXRecordDecl::method_iterator i = RD->method_begin(),
650 e = RD->method_end(); i != e; ++i) {
651 const CXXMethodDecl *MD = *i;
652 if (!MD->isVirtual())
653 continue;
654
655 if (UniqueOverrider[MD] == 0) {
656 // Only set this, if it hasn't been set yet.
657 BuildUniqueOverrider(MD, MD);
658 if (0)
659 printf("top set is %s::%s %p\n",
660 MD->getParent()->getNameAsCString(),
661 MD->getNameAsCString(),
662 (void*)MD);
663 ForwardUnique[MD] = MD;
664 }
665 }
666 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
667 e = RD->bases_end(); i != e; ++i) {
668 const CXXRecordDecl *Base =
669 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
670 BuildUniqueOverriders(Base);
671 }
672 }
673
674 static int DclCmp(const void *p1, const void *p2) {
675 const CXXMethodDecl *MD1 = (const CXXMethodDecl *)p1;
676 const CXXMethodDecl *MD2 = (const CXXMethodDecl *)p2;
677 return (MD1->getIdentifier() - MD2->getIdentifier());
678 }
679
680 void MergeForwarding() {
681 typedef llvm::SmallVector<const CXXMethodDecl *, 100> A_t;
682 A_t A;
683 for (ForwardUnique_t::iterator I = ForwardUnique.begin(),
684 E = ForwardUnique.end(); I != E; ++I) {
685 if (I->first == I->second)
686 // Only add the roots of all trees
687 A.push_back(I->first);
688 }
689 llvm::array_pod_sort(A.begin(), A.end(), DclCmp);
690 for (A_t::iterator I = A.begin(),
691 E = A.end(); I != E; ++I) {
692 A_t::iterator J = I;
693 while (++J != E && DclCmp(*I, *J) == 0)
694 if (DclIsSame(*I, *J)) {
695 printf("connecting %s\n", (*I)->getNameAsCString());
696 ForwardUnique[*J] = *I;
697 }
698 }
699 }
700
701 const CXXMethodDecl *getUnique(const CXXMethodDecl *MD) {
702 const CXXMethodDecl *U = UniqueOverrider[MD];
703 assert(U && "unique overrider not found");
704 while (ForwardUnique.count(U)) {
705 const CXXMethodDecl *NU = ForwardUnique[U];
706 if (NU == U) break;
707 U = NU;
708 }
709 return U;
710 }
Anders Carlsson72281172010-01-26 17:36:47 +0000711
712 GlobalDecl getUnique(GlobalDecl GD) {
713 const CXXMethodDecl *Unique = getUnique(cast<CXXMethodDecl>(GD.getDecl()));
714
715 if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(Unique))
716 return GlobalDecl(CD, GD.getCtorType());
717
718 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(Unique))
719 return GlobalDecl(DD, GD.getDtorType());
720
721 return Unique;
Mike Stump90181eb2010-01-26 00:05:04 +0000722 }
723
Anders Carlsson323bb042009-11-26 19:54:33 +0000724 /// getPureVirtualFn - Return the __cxa_pure_virtual function.
725 llvm::Constant* getPureVirtualFn() {
726 if (!PureVirtualFn) {
727 const llvm::FunctionType *Ty =
728 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
729 /*isVarArg=*/false);
730 PureVirtualFn = wrap(CGM.CreateRuntimeFunction(Ty, "__cxa_pure_virtual"));
731 }
732
733 return PureVirtualFn;
734 }
735
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000736public:
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000737 OldVtableBuilder(const CXXRecordDecl *MostDerivedClass,
Eli Friedman6c08ce72009-12-05 01:05:03 +0000738 const CXXRecordDecl *l, uint64_t lo, CodeGenModule &cgm,
Anders Carlsson5f9a8812010-01-14 02:29:07 +0000739 bool build, CGVtableInfo::AddressPointsMapTy& AddressPoints)
Eli Friedman6c08ce72009-12-05 01:05:03 +0000740 : BuildVtable(build), MostDerivedClass(MostDerivedClass), LayoutClass(l),
741 LayoutOffset(lo), BLayout(cgm.getContext().getASTRecordLayout(l)),
742 rtti(0), VMContext(cgm.getModule().getContext()),CGM(cgm),
743 PureVirtualFn(0),
Anders Carlssonbad80eb2009-12-04 18:36:22 +0000744 subAddressPoints(AllocAddressPoint(cgm, l, MostDerivedClass)),
Anders Carlsson5f9a8812010-01-14 02:29:07 +0000745 AddressPoints(AddressPoints),
746 LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0))
747 {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000748 Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
Anders Carlsson3f4336c2009-12-17 07:09:17 +0000749 if (BuildVtable) {
750 QualType ClassType = CGM.getContext().getTagDeclType(MostDerivedClass);
751 rtti = CGM.GetAddrOfRTTIDescriptor(ClassType);
752 }
Mike Stump90181eb2010-01-26 00:05:04 +0000753 BuildUniqueOverriders(MostDerivedClass);
754 MergeForwarding();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000755 }
756
Anders Carlssonfe5f7d92009-12-06 01:09:21 +0000757 // getVtableComponents - Returns a reference to the vtable components.
758 const VtableComponentsVectorTy &getVtableComponents() const {
759 return VtableComponents;
Anders Carlsson472404f2009-12-04 16:19:30 +0000760 }
761
Anders Carlssone36a6b32010-01-02 01:01:18 +0000762 llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getVBIndex()
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000763 { return VBIndex; }
764
Eli Friedman31bc3ad2009-12-07 23:56:34 +0000765 SavedAdjustmentsVectorTy &getSavedAdjustments()
766 { return SavedAdjustments; }
Eli Friedman8174f2c2009-12-06 22:01:30 +0000767
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000768 llvm::Constant *wrap(Index_t i) {
769 llvm::Constant *m;
770 m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), i);
771 return llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty);
772 }
773
774 llvm::Constant *wrap(llvm::Constant *m) {
775 return llvm::ConstantExpr::getBitCast(m, Ptr8Ty);
776 }
777
Mike Stumpd2808442010-01-22 02:51:26 +0000778//#define D1(x)
779#define D1(X) do { if (getenv("DEBUG")) { X; } } while (0)
Mike Stump75ce5732009-10-31 20:06:59 +0000780
781 void GenerateVBaseOffsets(const CXXRecordDecl *RD, uint64_t Offset,
Mike Stump28431212009-10-13 22:54:56 +0000782 bool updateVBIndex, Index_t current_vbindex) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000783 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
784 e = RD->bases_end(); i != e; ++i) {
785 const CXXRecordDecl *Base =
786 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
Mike Stump28431212009-10-13 22:54:56 +0000787 Index_t next_vbindex = current_vbindex;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000788 if (i->isVirtual() && !SeenVBase.count(Base)) {
789 SeenVBase.insert(Base);
Mike Stump28431212009-10-13 22:54:56 +0000790 if (updateVBIndex) {
Mike Stump75ce5732009-10-31 20:06:59 +0000791 next_vbindex = (ssize_t)(-(VCalls.size()*LLVMPointerWidth/8)
Mike Stump28431212009-10-13 22:54:56 +0000792 - 3*LLVMPointerWidth/8);
793 VBIndex[Base] = next_vbindex;
794 }
Mike Stump75ce5732009-10-31 20:06:59 +0000795 int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8;
796 VCalls.push_back((0?700:0) + BaseOffset);
797 D1(printf(" vbase for %s at %d delta %d most derived %s\n",
798 Base->getNameAsCString(),
799 (int)-VCalls.size()-3, (int)BaseOffset,
Mike Stumpd2808442010-01-22 02:51:26 +0000800 MostDerivedClass->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000801 }
Mike Stump28431212009-10-13 22:54:56 +0000802 // We also record offsets for non-virtual bases to closest enclosing
803 // virtual base. We do this so that we don't have to search
804 // for the nearst virtual base class when generating thunks.
805 if (updateVBIndex && VBIndex.count(Base) == 0)
806 VBIndex[Base] = next_vbindex;
Mike Stump75ce5732009-10-31 20:06:59 +0000807 GenerateVBaseOffsets(Base, Offset, updateVBIndex, next_vbindex);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000808 }
809 }
810
811 void StartNewTable() {
812 SeenVBase.clear();
813 }
814
Mike Stump8bccbfd2009-10-15 09:30:16 +0000815 Index_t getNVOffset_1(const CXXRecordDecl *D, const CXXRecordDecl *B,
816 Index_t Offset = 0) {
817
818 if (B == D)
819 return Offset;
820
821 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(D);
822 for (CXXRecordDecl::base_class_const_iterator i = D->bases_begin(),
823 e = D->bases_end(); i != e; ++i) {
824 const CXXRecordDecl *Base =
825 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
826 int64_t BaseOffset = 0;
827 if (!i->isVirtual())
828 BaseOffset = Offset + Layout.getBaseClassOffset(Base);
829 int64_t o = getNVOffset_1(Base, B, BaseOffset);
830 if (o >= 0)
831 return o;
832 }
833
834 return -1;
835 }
836
837 /// getNVOffset - Returns the non-virtual offset for the given (B) base of the
838 /// derived class D.
839 Index_t getNVOffset(QualType qB, QualType qD) {
Mike Stump46271322009-11-03 19:03:17 +0000840 qD = qD->getPointeeType();
841 qB = qB->getPointeeType();
Mike Stump8bccbfd2009-10-15 09:30:16 +0000842 CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
843 CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
844 int64_t o = getNVOffset_1(D, B);
845 if (o >= 0)
846 return o;
847
848 assert(false && "FIXME: non-virtual base not found");
849 return 0;
850 }
851
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000852 /// getVbaseOffset - Returns the index into the vtable for the virtual base
853 /// offset for the given (B) virtual base of the derived class D.
854 Index_t getVbaseOffset(QualType qB, QualType qD) {
Mike Stump46271322009-11-03 19:03:17 +0000855 qD = qD->getPointeeType();
856 qB = qB->getPointeeType();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000857 CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
858 CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
Anders Carlssonbad80eb2009-12-04 18:36:22 +0000859 if (D != MostDerivedClass)
Eli Friedman03aa2f12009-11-30 01:19:33 +0000860 return CGM.getVtableInfo().getVirtualBaseOffsetIndex(D, B);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000861 llvm::DenseMap<const CXXRecordDecl *, Index_t>::iterator i;
862 i = VBIndex.find(B);
863 if (i != VBIndex.end())
864 return i->second;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000865
Mike Stump28431212009-10-13 22:54:56 +0000866 assert(false && "FIXME: Base not found");
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000867 return 0;
868 }
869
Eli Friedman81fb0d22009-12-04 08:40:51 +0000870 bool OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
871 Index_t OverrideOffset, Index_t Offset,
872 int64_t CurrentVBaseOffset);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000873
Anders Carlsson495634e2009-12-04 02:39:04 +0000874 /// AppendMethods - Append the current methods to the vtable.
Anders Carlssonddf42c82009-12-04 02:56:03 +0000875 void AppendMethodsToVtable();
Anders Carlsson495634e2009-12-04 02:39:04 +0000876
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000877 llvm::Constant *WrapAddrOf(GlobalDecl GD) {
878 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
879
Anders Carlsson64457732009-11-24 05:08:52 +0000880 const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVtable(MD);
Mike Stump18e8b472009-10-27 23:36:26 +0000881
Mike Stumpcdeb8002009-12-03 16:55:20 +0000882 return wrap(CGM.GetAddrOfFunction(GD, Ty));
Mike Stump18e8b472009-10-27 23:36:26 +0000883 }
884
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000885 void OverrideMethods(Path_t *Path, bool MorallyVirtual, int64_t Offset,
886 int64_t CurrentVBaseOffset) {
Mike Stump37dbe962009-10-15 02:04:03 +0000887 for (Path_t::reverse_iterator i = Path->rbegin(),
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000888 e = Path->rend(); i != e; ++i) {
889 const CXXRecordDecl *RD = i->first;
Mike Stump8bccbfd2009-10-15 09:30:16 +0000890 int64_t OverrideOffset = i->second;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000891 for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
892 ++mi) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000893 const CXXMethodDecl *MD = *mi;
894
895 if (!MD->isVirtual())
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000896 continue;
897
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000898 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
899 // Override both the complete and the deleting destructor.
900 GlobalDecl CompDtor(DD, Dtor_Complete);
Eli Friedman81fb0d22009-12-04 08:40:51 +0000901 OverrideMethod(CompDtor, MorallyVirtual, OverrideOffset, Offset,
902 CurrentVBaseOffset);
903
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000904 GlobalDecl DeletingDtor(DD, Dtor_Deleting);
Eli Friedman81fb0d22009-12-04 08:40:51 +0000905 OverrideMethod(DeletingDtor, MorallyVirtual, OverrideOffset, Offset,
906 CurrentVBaseOffset);
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000907 } else {
Eli Friedman81fb0d22009-12-04 08:40:51 +0000908 OverrideMethod(MD, MorallyVirtual, OverrideOffset, Offset,
909 CurrentVBaseOffset);
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000910 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000911 }
912 }
913 }
914
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000915 void AddMethod(const GlobalDecl GD, bool MorallyVirtual, Index_t Offset,
Eli Friedman03aa2f12009-11-30 01:19:33 +0000916 int64_t CurrentVBaseOffset) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000917 // If we can find a previously allocated slot for this, reuse it.
Eli Friedman81fb0d22009-12-04 08:40:51 +0000918 if (OverrideMethod(GD, MorallyVirtual, Offset, Offset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000919 CurrentVBaseOffset))
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000920 return;
921
Mike Stump1f49d652010-01-22 18:48:47 +0000922 D1(printf(" vfn for %s at %d\n",
923 dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsCString(),
924 (int)Methods.size()));
925
Anders Carlssoncdf18982009-12-04 02:08:24 +0000926 // We didn't find an entry in the vtable that we could use, add a new
927 // entry.
928 Methods.AddMethod(GD);
929
Mike Stumpa04ecfb2010-01-26 21:35:27 +0000930 VCallOffset[GD] = Offset/8 - CurrentVBaseOffset/8;
931
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000932 if (MorallyVirtual) {
Anders Carlsson72281172010-01-26 17:36:47 +0000933 GlobalDecl UGD = getUnique(GD);
934 const CXXMethodDecl *UMD = cast<CXXMethodDecl>(UGD.getDecl());
935
Mike Stump90181eb2010-01-26 00:05:04 +0000936 assert(UMD && "final overrider not found");
937
938 Index_t &idx = VCall[UMD];
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000939 // Allocate the first one, after that, we reuse the previous one.
940 if (idx == 0) {
Anders Carlsson72281172010-01-26 17:36:47 +0000941 VCallOffsetForVCall[UGD] = Offset/8;
Mike Stumpa04ecfb2010-01-26 21:35:27 +0000942 NonVirtualOffset[UMD] = Offset/8 - CurrentVBaseOffset/8;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000943 idx = VCalls.size()+1;
Mike Stump90181eb2010-01-26 00:05:04 +0000944 VCalls.push_back(Offset/8 - CurrentVBaseOffset/8);
Mike Stump75ce5732009-10-31 20:06:59 +0000945 D1(printf(" vcall for %s at %d with delta %d\n",
Mike Stumpd2808442010-01-22 02:51:26 +0000946 dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsCString(),
Mike Stump90181eb2010-01-26 00:05:04 +0000947 (int)-VCalls.size()-3, (int)VCalls[idx-1]));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000948 }
949 }
950 }
951
952 void AddMethods(const CXXRecordDecl *RD, bool MorallyVirtual,
Eli Friedman03aa2f12009-11-30 01:19:33 +0000953 Index_t Offset, int64_t CurrentVBaseOffset) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000954 for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000955 ++mi) {
956 const CXXMethodDecl *MD = *mi;
957 if (!MD->isVirtual())
958 continue;
959
960 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
961 // For destructors, add both the complete and the deleting destructor
962 // to the vtable.
963 AddMethod(GlobalDecl(DD, Dtor_Complete), MorallyVirtual, Offset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000964 CurrentVBaseOffset);
Eli Friedman03aa2f12009-11-30 01:19:33 +0000965 AddMethod(GlobalDecl(DD, Dtor_Deleting), MorallyVirtual, Offset,
966 CurrentVBaseOffset);
967 } else
968 AddMethod(MD, MorallyVirtual, Offset, CurrentVBaseOffset);
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000969 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000970 }
971
972 void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
973 const CXXRecordDecl *PrimaryBase,
974 bool PrimaryBaseWasVirtual, bool MorallyVirtual,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000975 int64_t Offset, int64_t CurrentVBaseOffset,
976 Path_t *Path) {
Mike Stump37dbe962009-10-15 02:04:03 +0000977 Path->push_back(std::make_pair(RD, Offset));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000978 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
979 e = RD->bases_end(); i != e; ++i) {
980 if (i->isVirtual())
981 continue;
982 const CXXRecordDecl *Base =
983 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
Mike Stump9eb76d42010-01-22 06:45:05 +0000984 uint64_t o = Offset + Layout.getBaseClassOffset(Base);
985 StartNewTable();
986 GenerateVtableForBase(Base, o, MorallyVirtual, false,
987 true, Base == PrimaryBase && !PrimaryBaseWasVirtual,
988 CurrentVBaseOffset, Path);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000989 }
Mike Stump37dbe962009-10-15 02:04:03 +0000990 Path->pop_back();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000991 }
992
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000993// #define D(X) do { X; } while (0)
994#define D(X)
995
996 void insertVCalls(int InsertionPoint) {
Mike Stump75ce5732009-10-31 20:06:59 +0000997 D1(printf("============= combining vbase/vcall\n"));
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000998 D(VCalls.insert(VCalls.begin(), 673));
999 D(VCalls.push_back(672));
Eli Friedman6c08ce72009-12-05 01:05:03 +00001000
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001001 VtableComponents.insert(VtableComponents.begin() + InsertionPoint,
1002 VCalls.size(), 0);
Eli Friedman6c08ce72009-12-05 01:05:03 +00001003 if (BuildVtable) {
1004 // The vcalls come first...
1005 for (std::vector<Index_t>::reverse_iterator i = VCalls.rbegin(),
1006 e = VCalls.rend();
1007 i != e; ++i)
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001008 VtableComponents[InsertionPoint++] = wrap((0?600:0) + *i);
Eli Friedman6c08ce72009-12-05 01:05:03 +00001009 }
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001010 VCalls.clear();
Mike Stump9f23a142009-11-10 02:30:51 +00001011 VCall.clear();
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001012 VCallOffsetForVCall.clear();
1013 VCallOffset.clear();
1014 NonVirtualOffset.clear();
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001015 }
1016
Mike Stump559387f2009-11-13 23:13:20 +00001017 void AddAddressPoints(const CXXRecordDecl *RD, uint64_t Offset,
1018 Index_t AddressPoint) {
1019 D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001020 RD->getNameAsCString(), MostDerivedClass->getNameAsCString(),
Mike Stump559387f2009-11-13 23:13:20 +00001021 LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
Mike Stumpcd2b8212009-11-19 20:52:19 +00001022 subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
Anders Carlsson5f9a8812010-01-14 02:29:07 +00001023 AddressPoints[BaseSubobject(RD, Offset)] = AddressPoint;
Mike Stump559387f2009-11-13 23:13:20 +00001024
1025 // Now also add the address point for all our primary bases.
1026 while (1) {
1027 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1028 RD = Layout.getPrimaryBase();
1029 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
1030 // FIXME: Double check this.
1031 if (RD == 0)
1032 break;
1033 if (PrimaryBaseWasVirtual &&
1034 BLayout.getVBaseClassOffset(RD) != Offset)
1035 break;
1036 D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001037 RD->getNameAsCString(), MostDerivedClass->getNameAsCString(),
Mike Stump559387f2009-11-13 23:13:20 +00001038 LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
Mike Stumpcd2b8212009-11-19 20:52:19 +00001039 subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
Anders Carlsson5f9a8812010-01-14 02:29:07 +00001040 AddressPoints[BaseSubobject(RD, Offset)] = AddressPoint;
Mike Stump559387f2009-11-13 23:13:20 +00001041 }
1042 }
1043
1044
Mike Stumpd538a6d2009-12-24 07:29:41 +00001045 void FinishGenerateVtable(const CXXRecordDecl *RD,
1046 const ASTRecordLayout &Layout,
1047 const CXXRecordDecl *PrimaryBase,
Mike Stump9eb76d42010-01-22 06:45:05 +00001048 bool ForNPNVBases, bool WasPrimaryBase,
Mike Stumpd538a6d2009-12-24 07:29:41 +00001049 bool PrimaryBaseWasVirtual,
1050 bool MorallyVirtual, int64_t Offset,
1051 bool ForVirtualBase, int64_t CurrentVBaseOffset,
1052 Path_t *Path) {
Mike Stump37dbe962009-10-15 02:04:03 +00001053 bool alloc = false;
1054 if (Path == 0) {
1055 alloc = true;
1056 Path = new Path_t;
1057 }
1058
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001059 StartNewTable();
1060 extra = 0;
Mike Stump9eb76d42010-01-22 06:45:05 +00001061 Index_t AddressPoint = 0;
1062 int VCallInsertionPoint = 0;
1063 if (!ForNPNVBases || !WasPrimaryBase) {
1064 bool DeferVCalls = MorallyVirtual || ForVirtualBase;
1065 VCallInsertionPoint = VtableComponents.size();
1066 if (!DeferVCalls) {
1067 insertVCalls(VCallInsertionPoint);
1068 } else
1069 // FIXME: just for extra, or for all uses of VCalls.size post this?
1070 extra = -VCalls.size();
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001071
Mike Stump9eb76d42010-01-22 06:45:05 +00001072 // Add the offset to top.
1073 VtableComponents.push_back(BuildVtable ? wrap(-((Offset-LayoutOffset)/8)) : 0);
Anders Carlsson472404f2009-12-04 16:19:30 +00001074
Mike Stump9eb76d42010-01-22 06:45:05 +00001075 // Add the RTTI information.
1076 VtableComponents.push_back(rtti);
Anders Carlsson472404f2009-12-04 16:19:30 +00001077
Mike Stump9eb76d42010-01-22 06:45:05 +00001078 AddressPoint = VtableComponents.size();
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001079
Mike Stump9eb76d42010-01-22 06:45:05 +00001080 AppendMethodsToVtable();
1081 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001082
1083 // and then the non-virtual bases.
1084 NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001085 MorallyVirtual, Offset, CurrentVBaseOffset, Path);
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001086
1087 if (ForVirtualBase) {
Mike Stump2cefe382009-11-12 20:47:57 +00001088 // FIXME: We're adding to VCalls in callers, we need to do the overrides
1089 // in the inner part, so that we know the complete set of vcalls during
1090 // the build and don't have to insert into methods. Saving out the
1091 // AddressPoint here, would need to be fixed, if we didn't do that. Also
1092 // retroactively adding vcalls for overrides later wind up in the wrong
1093 // place, the vcall slot has to be alloted during the walk of the base
1094 // when the function is first introduces.
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001095 AddressPoint += VCalls.size();
Mike Stump2cefe382009-11-12 20:47:57 +00001096 insertVCalls(VCallInsertionPoint);
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001097 }
1098
Mike Stump9eb76d42010-01-22 06:45:05 +00001099 if (!ForNPNVBases || !WasPrimaryBase)
1100 AddAddressPoints(RD, Offset, AddressPoint);
Mike Stump2cefe382009-11-12 20:47:57 +00001101
Mike Stump37dbe962009-10-15 02:04:03 +00001102 if (alloc) {
1103 delete Path;
1104 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001105 }
1106
Mike Stump75ce5732009-10-31 20:06:59 +00001107 void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
1108 bool updateVBIndex, Index_t current_vbindex,
Eli Friedman03aa2f12009-11-30 01:19:33 +00001109 int64_t CurrentVBaseOffset) {
Mike Stump75ce5732009-10-31 20:06:59 +00001110 if (!RD->isDynamicClass())
1111 return;
1112
1113 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1114 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1115 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
1116
1117 // vtables are composed from the chain of primaries.
Eli Friedman65d87222009-12-04 08:52:11 +00001118 if (PrimaryBase && !PrimaryBaseWasVirtual) {
Mike Stump75ce5732009-10-31 20:06:59 +00001119 D1(printf(" doing primaries for %s most derived %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001120 RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
Eli Friedman65d87222009-12-04 08:52:11 +00001121 Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
1122 updateVBIndex, current_vbindex, CurrentVBaseOffset);
Mike Stump75ce5732009-10-31 20:06:59 +00001123 }
1124
1125 D1(printf(" doing vcall entries for %s most derived %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001126 RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
Mike Stump75ce5732009-10-31 20:06:59 +00001127
1128 // And add the virtuals for the class to the primary vtable.
Eli Friedman03aa2f12009-11-30 01:19:33 +00001129 AddMethods(RD, MorallyVirtual, Offset, CurrentVBaseOffset);
Mike Stump75ce5732009-10-31 20:06:59 +00001130 }
1131
1132 void VBPrimaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
1133 bool updateVBIndex, Index_t current_vbindex,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001134 bool RDisVirtualBase, int64_t CurrentVBaseOffset,
Eli Friedman03aa2f12009-11-30 01:19:33 +00001135 bool bottom) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001136 if (!RD->isDynamicClass())
1137 return;
1138
1139 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1140 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1141 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
1142
1143 // vtables are composed from the chain of primaries.
1144 if (PrimaryBase) {
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001145 int BaseCurrentVBaseOffset = CurrentVBaseOffset;
1146 if (PrimaryBaseWasVirtual) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001147 IndirectPrimary.insert(PrimaryBase);
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001148 BaseCurrentVBaseOffset = BLayout.getVBaseClassOffset(PrimaryBase);
1149 }
Mike Stump75ce5732009-10-31 20:06:59 +00001150
1151 D1(printf(" doing primaries for %s most derived %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001152 RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
Mike Stump75ce5732009-10-31 20:06:59 +00001153
1154 VBPrimaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001155 updateVBIndex, current_vbindex, PrimaryBaseWasVirtual,
Eli Friedman03aa2f12009-11-30 01:19:33 +00001156 BaseCurrentVBaseOffset, false);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001157 }
1158
Mike Stump75ce5732009-10-31 20:06:59 +00001159 D1(printf(" doing vbase entries for %s most derived %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001160 RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
Mike Stump75ce5732009-10-31 20:06:59 +00001161 GenerateVBaseOffsets(RD, Offset, updateVBIndex, current_vbindex);
1162
1163 if (RDisVirtualBase || bottom) {
1164 Primaries(RD, MorallyVirtual, Offset, updateVBIndex, current_vbindex,
Eli Friedman03aa2f12009-11-30 01:19:33 +00001165 CurrentVBaseOffset);
Mike Stump75ce5732009-10-31 20:06:59 +00001166 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001167 }
1168
Mike Stumpd538a6d2009-12-24 07:29:41 +00001169 void GenerateVtableForBase(const CXXRecordDecl *RD, int64_t Offset = 0,
1170 bool MorallyVirtual = false,
1171 bool ForVirtualBase = false,
Mike Stump9eb76d42010-01-22 06:45:05 +00001172 bool ForNPNVBases = false,
1173 bool WasPrimaryBase = true,
Mike Stumpd538a6d2009-12-24 07:29:41 +00001174 int CurrentVBaseOffset = 0,
1175 Path_t *Path = 0) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001176 if (!RD->isDynamicClass())
Mike Stumpd538a6d2009-12-24 07:29:41 +00001177 return;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001178
Mike Stumpfa818082009-11-13 02:35:38 +00001179 // Construction vtable don't need parts that have no virtual bases and
1180 // aren't morally virtual.
Anders Carlssonbad80eb2009-12-04 18:36:22 +00001181 if ((LayoutClass != MostDerivedClass) &&
1182 RD->getNumVBases() == 0 && !MorallyVirtual)
Mike Stumpd538a6d2009-12-24 07:29:41 +00001183 return;
Mike Stumpfa818082009-11-13 02:35:38 +00001184
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001185 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1186 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1187 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
1188
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001189 extra = 0;
Mike Stump75ce5732009-10-31 20:06:59 +00001190 D1(printf("building entries for base %s most derived %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001191 RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001192
Mike Stump75ce5732009-10-31 20:06:59 +00001193 if (ForVirtualBase)
1194 extra = VCalls.size();
1195
Mike Stump9eb76d42010-01-22 06:45:05 +00001196 if (!ForNPNVBases || !WasPrimaryBase) {
1197 VBPrimaries(RD, MorallyVirtual, Offset, !ForVirtualBase, 0,
1198 ForVirtualBase, CurrentVBaseOffset, true);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001199
Mike Stump9eb76d42010-01-22 06:45:05 +00001200 if (Path)
1201 OverrideMethods(Path, MorallyVirtual, Offset, CurrentVBaseOffset);
1202 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001203
Mike Stump9eb76d42010-01-22 06:45:05 +00001204 FinishGenerateVtable(RD, Layout, PrimaryBase, ForNPNVBases, WasPrimaryBase,
1205 PrimaryBaseWasVirtual, MorallyVirtual, Offset,
1206 ForVirtualBase, CurrentVBaseOffset, Path);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001207 }
1208
1209 void GenerateVtableForVBases(const CXXRecordDecl *RD,
1210 int64_t Offset = 0,
Mike Stump37dbe962009-10-15 02:04:03 +00001211 Path_t *Path = 0) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001212 bool alloc = false;
1213 if (Path == 0) {
1214 alloc = true;
Mike Stump37dbe962009-10-15 02:04:03 +00001215 Path = new Path_t;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001216 }
1217 // FIXME: We also need to override using all paths to a virtual base,
1218 // right now, we just process the first path
1219 Path->push_back(std::make_pair(RD, Offset));
1220 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
1221 e = RD->bases_end(); i != e; ++i) {
1222 const CXXRecordDecl *Base =
1223 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
1224 if (i->isVirtual() && !IndirectPrimary.count(Base)) {
1225 // Mark it so we don't output it twice.
1226 IndirectPrimary.insert(Base);
1227 StartNewTable();
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001228 VCall.clear();
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001229 int64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001230 int64_t CurrentVBaseOffset = BaseOffset;
Mike Stump75ce5732009-10-31 20:06:59 +00001231 D1(printf("vtable %s virtual base %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001232 MostDerivedClass->getNameAsCString(), Base->getNameAsCString()));
Mike Stump9eb76d42010-01-22 06:45:05 +00001233 GenerateVtableForBase(Base, BaseOffset, true, true, false,
1234 true, CurrentVBaseOffset, Path);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001235 }
Mike Stump2cefe382009-11-12 20:47:57 +00001236 int64_t BaseOffset;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001237 if (i->isVirtual())
1238 BaseOffset = BLayout.getVBaseClassOffset(Base);
Mike Stump2cefe382009-11-12 20:47:57 +00001239 else {
1240 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1241 BaseOffset = Offset + Layout.getBaseClassOffset(Base);
1242 }
1243
Mike Stump37dbe962009-10-15 02:04:03 +00001244 if (Base->getNumVBases()) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001245 GenerateVtableForVBases(Base, BaseOffset, Path);
Mike Stump37dbe962009-10-15 02:04:03 +00001246 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001247 }
1248 Path->pop_back();
1249 if (alloc)
1250 delete Path;
1251 }
1252};
Anders Carlssonca1bf682009-12-03 01:54:02 +00001253} // end anonymous namespace
1254
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00001255bool OldVtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
Eli Friedman81fb0d22009-12-04 08:40:51 +00001256 Index_t OverrideOffset, Index_t Offset,
1257 int64_t CurrentVBaseOffset) {
Anders Carlssonca1bf682009-12-03 01:54:02 +00001258 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
1259
1260 const bool isPure = MD->isPure();
Anders Carlsson21bbc1e2009-12-05 17:04:47 +00001261
Anders Carlssonca1bf682009-12-03 01:54:02 +00001262 // FIXME: Should OverrideOffset's be Offset?
1263
Anders Carlsson21bbc1e2009-12-05 17:04:47 +00001264 for (CXXMethodDecl::method_iterator mi = MD->begin_overridden_methods(),
1265 e = MD->end_overridden_methods(); mi != e; ++mi) {
Anders Carlssonca1bf682009-12-03 01:54:02 +00001266 GlobalDecl OGD;
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001267 GlobalDecl OGD2;
Anders Carlssonca1bf682009-12-03 01:54:02 +00001268
Anders Carlssonf3935b42009-12-04 05:51:56 +00001269 const CXXMethodDecl *OMD = *mi;
Anders Carlssonca1bf682009-12-03 01:54:02 +00001270 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(OMD))
1271 OGD = GlobalDecl(DD, GD.getDtorType());
1272 else
1273 OGD = OMD;
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001274
Eli Friedman8174f2c2009-12-06 22:01:30 +00001275 // Check whether this is the method being overridden in this section of
1276 // the vtable.
Anders Carlsson7bb70762009-12-04 15:49:02 +00001277 uint64_t Index;
1278 if (!Methods.getIndex(OGD, Index))
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001279 continue;
1280
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001281 OGD2 = OGD;
1282
Eli Friedman8174f2c2009-12-06 22:01:30 +00001283 // Get the original method, which we should be computing thunks, etc,
1284 // against.
1285 OGD = Methods.getOrigMethod(Index);
1286 OMD = cast<CXXMethodDecl>(OGD.getDecl());
1287
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001288 QualType ReturnType =
1289 MD->getType()->getAs<FunctionType>()->getResultType();
1290 QualType OverriddenReturnType =
1291 OMD->getType()->getAs<FunctionType>()->getResultType();
Anders Carlssonca1bf682009-12-03 01:54:02 +00001292
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001293 // Check if we need a return type adjustment.
1294 if (TypeConversionRequiresAdjustment(CGM.getContext(), ReturnType,
1295 OverriddenReturnType)) {
1296 CanQualType &BaseReturnType = BaseReturnTypes[Index];
Anders Carlssonca1bf682009-12-03 01:54:02 +00001297
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001298 // Insert the base return type.
1299 if (BaseReturnType.isNull())
1300 BaseReturnType =
1301 CGM.getContext().getCanonicalType(OverriddenReturnType);
1302 }
Anders Carlssona93e9802009-12-04 03:52:52 +00001303
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001304 Methods.OverrideMethod(OGD, GD);
1305
Anders Carlsson72281172010-01-26 17:36:47 +00001306 GlobalDecl UGD = getUnique(GD);
1307 const CXXMethodDecl *UMD = cast<CXXMethodDecl>(UGD.getDecl());
1308 assert(UGD.getDecl() && "unique overrider not found");
1309 assert(UGD == getUnique(OGD) && "unique overrider not unique");
Mike Stump90181eb2010-01-26 00:05:04 +00001310
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001311 ThisAdjustments.erase(Index);
Mike Stump90181eb2010-01-26 00:05:04 +00001312 if (MorallyVirtual || VCall.count(UMD)) {
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001313
Mike Stump90181eb2010-01-26 00:05:04 +00001314 Index_t &idx = VCall[UMD];
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001315 if (idx == 0) {
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001316 VCallOffset[GD] = VCallOffset[OGD];
1317 // NonVirtualOffset[UMD] = CurrentVBaseOffset/8 - OverrideOffset/8;
1318 NonVirtualOffset[UMD] = VCallOffset[OGD];
Mike Stump77537b12010-01-26 03:42:22 +00001319 VCallOffsetForVCall[UMD] = OverrideOffset/8;
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001320 idx = VCalls.size()+1;
Mike Stump77537b12010-01-26 03:42:22 +00001321 VCalls.push_back(OverrideOffset/8 - CurrentVBaseOffset/8);
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001322 D1(printf(" vcall for %s at %d with delta %d most derived %s\n",
1323 MD->getNameAsString().c_str(), (int)-idx-3,
Mike Stumpd2808442010-01-22 02:51:26 +00001324 (int)VCalls[idx-1], MostDerivedClass->getNameAsCString()));
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001325 } else {
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001326 VCallOffset[GD] = NonVirtualOffset[UMD];
Anders Carlsson72281172010-01-26 17:36:47 +00001327 VCalls[idx-1] = -VCallOffsetForVCall[UGD] + OverrideOffset/8;
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001328 D1(printf(" vcall patch for %s at %d with delta %d most derived %s\n",
1329 MD->getNameAsString().c_str(), (int)-idx-3,
Mike Stumpd2808442010-01-22 02:51:26 +00001330 (int)VCalls[idx-1], MostDerivedClass->getNameAsCString()));
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001331 }
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001332 int64_t NonVirtualAdjustment = -VCallOffset[OGD];
Mike Stumpded0a402010-01-26 22:44:01 +00001333 QualType DerivedType = MD->getThisType(CGM.getContext());
1334 QualType BaseType = cast<const CXXMethodDecl>(OGD.getDecl())->getThisType(CGM.getContext());
1335 int64_t NonVirtualAdjustment2 = -(getNVOffset(BaseType, DerivedType)/8);
1336 if (NonVirtualAdjustment2 != NonVirtualAdjustment) {
1337 NonVirtualAdjustment = NonVirtualAdjustment2;
1338 }
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001339 int64_t VirtualAdjustment =
1340 -((idx + extra + 2) * LLVMPointerWidth / 8);
Anders Carlsson657f1392009-12-03 02:32:59 +00001341
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001342 // Optimize out virtual adjustments of 0.
1343 if (VCalls[idx-1] == 0)
1344 VirtualAdjustment = 0;
Anders Carlsson657f1392009-12-03 02:32:59 +00001345
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001346 ThunkAdjustment ThisAdjustment(NonVirtualAdjustment,
1347 VirtualAdjustment);
Anders Carlsson2ca285f2009-12-03 02:22:59 +00001348
Eli Friedman8174f2c2009-12-06 22:01:30 +00001349 if (!isPure && !ThisAdjustment.isEmpty()) {
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001350 ThisAdjustments[Index] = ThisAdjustment;
Eli Friedman31bc3ad2009-12-07 23:56:34 +00001351 SavedAdjustments.push_back(
1352 std::make_pair(GD, std::make_pair(OGD, ThisAdjustment)));
Eli Friedman8174f2c2009-12-06 22:01:30 +00001353 }
Anders Carlssonca1bf682009-12-03 01:54:02 +00001354 return true;
1355 }
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001356
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001357 VCallOffset[GD] = VCallOffset[OGD2] - OverrideOffset/8;
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001358
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001359 int64_t NonVirtualAdjustment = -VCallOffset[GD];
1360 QualType DerivedType = MD->getThisType(CGM.getContext());
1361 QualType BaseType = cast<const CXXMethodDecl>(OGD.getDecl())->getThisType(CGM.getContext());
1362 int64_t NonVirtualAdjustment2 = -(getNVOffset(BaseType, DerivedType)/8);
1363 if (NonVirtualAdjustment2 != NonVirtualAdjustment) {
1364 NonVirtualAdjustment = NonVirtualAdjustment2;
1365 }
1366
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001367 if (NonVirtualAdjustment) {
1368 ThunkAdjustment ThisAdjustment(NonVirtualAdjustment, 0);
1369
Eli Friedmanf2eda5e2009-12-06 22:33:51 +00001370 if (!isPure) {
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001371 ThisAdjustments[Index] = ThisAdjustment;
Eli Friedman31bc3ad2009-12-07 23:56:34 +00001372 SavedAdjustments.push_back(
1373 std::make_pair(GD, std::make_pair(OGD, ThisAdjustment)));
Eli Friedmanf2eda5e2009-12-06 22:33:51 +00001374 }
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001375 }
1376 return true;
Anders Carlssonca1bf682009-12-03 01:54:02 +00001377 }
1378
1379 return false;
Anders Carlssond59885022009-11-27 22:21:51 +00001380}
1381
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00001382void OldVtableBuilder::AppendMethodsToVtable() {
Eli Friedman6c08ce72009-12-05 01:05:03 +00001383 if (!BuildVtable) {
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001384 VtableComponents.insert(VtableComponents.end(), Methods.size(),
1385 (llvm::Constant *)0);
Eli Friedman6c08ce72009-12-05 01:05:03 +00001386 ThisAdjustments.clear();
1387 BaseReturnTypes.clear();
1388 Methods.clear();
1389 return;
1390 }
1391
Anders Carlsson472404f2009-12-04 16:19:30 +00001392 // Reserve room in the vtable for our new methods.
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001393 VtableComponents.reserve(VtableComponents.size() + Methods.size());
Anders Carlssonb07567c2009-12-04 03:07:26 +00001394
Anders Carlsson86809cd2009-12-04 02:43:50 +00001395 for (unsigned i = 0, e = Methods.size(); i != e; ++i) {
1396 GlobalDecl GD = Methods[i];
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00001397 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
1398
1399 // Get the 'this' pointer adjustment.
Anders Carlsson86809cd2009-12-04 02:43:50 +00001400 ThunkAdjustment ThisAdjustment = ThisAdjustments.lookup(i);
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00001401
1402 // Construct the return type adjustment.
1403 ThunkAdjustment ReturnAdjustment;
1404
1405 QualType BaseReturnType = BaseReturnTypes.lookup(i);
1406 if (!BaseReturnType.isNull() && !MD->isPure()) {
1407 QualType DerivedType =
1408 MD->getType()->getAs<FunctionType>()->getResultType();
1409
1410 int64_t NonVirtualAdjustment =
1411 getNVOffset(BaseReturnType, DerivedType) / 8;
1412
1413 int64_t VirtualAdjustment =
1414 getVbaseOffset(BaseReturnType, DerivedType);
1415
1416 ReturnAdjustment = ThunkAdjustment(NonVirtualAdjustment,
1417 VirtualAdjustment);
1418 }
1419
Anders Carlsson50f14742009-12-04 03:06:03 +00001420 llvm::Constant *Method = 0;
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00001421 if (!ReturnAdjustment.isEmpty()) {
1422 // Build a covariant thunk.
1423 CovariantThunkAdjustment Adjustment(ThisAdjustment, ReturnAdjustment);
Eli Friedman8174f2c2009-12-06 22:01:30 +00001424 Method = wrap(CGM.GetAddrOfCovariantThunk(GD, Adjustment));
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00001425 } else if (!ThisAdjustment.isEmpty()) {
1426 // Build a "regular" thunk.
Eli Friedman8174f2c2009-12-06 22:01:30 +00001427 Method = wrap(CGM.GetAddrOfThunk(GD, ThisAdjustment));
Anders Carlssonddf42c82009-12-04 02:56:03 +00001428 } else if (MD->isPure()) {
1429 // We have a pure virtual method.
Anders Carlsson50f14742009-12-04 03:06:03 +00001430 Method = getPureVirtualFn();
1431 } else {
1432 // We have a good old regular method.
1433 Method = WrapAddrOf(GD);
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00001434 }
Anders Carlsson50f14742009-12-04 03:06:03 +00001435
1436 // Add the method to the vtable.
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001437 VtableComponents.push_back(Method);
Anders Carlsson86809cd2009-12-04 02:43:50 +00001438 }
1439
Anders Carlsson50f14742009-12-04 03:06:03 +00001440
Anders Carlsson86809cd2009-12-04 02:43:50 +00001441 ThisAdjustments.clear();
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00001442 BaseReturnTypes.clear();
Anders Carlsson86809cd2009-12-04 02:43:50 +00001443
Anders Carlsson495634e2009-12-04 02:39:04 +00001444 Methods.clear();
Anders Carlsson495634e2009-12-04 02:39:04 +00001445}
1446
Anders Carlssonf942ee02009-11-27 20:47:55 +00001447void CGVtableInfo::ComputeMethodVtableIndices(const CXXRecordDecl *RD) {
1448
1449 // Itanium C++ ABI 2.5.2:
Anders Carlsson259688c2010-02-02 03:37:46 +00001450 // The order of the virtual function pointers in a virtual table is the
1451 // order of declaration of the corresponding member functions in the class.
Anders Carlssonf942ee02009-11-27 20:47:55 +00001452 //
Anders Carlsson259688c2010-02-02 03:37:46 +00001453 // There is an entry for any virtual function declared in a class,
1454 // whether it is a new function or overrides a base class function,
1455 // unless it overrides a function from the primary base, and conversion
1456 // between their return types does not require an adjustment.
Anders Carlssonf942ee02009-11-27 20:47:55 +00001457
1458 int64_t CurrentIndex = 0;
1459
1460 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1461 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1462
1463 if (PrimaryBase) {
Anders Carlssonc920fa22009-11-30 19:43:26 +00001464 assert(PrimaryBase->isDefinition() &&
1465 "Should have the definition decl of the primary base!");
Anders Carlssonf942ee02009-11-27 20:47:55 +00001466
1467 // Since the record decl shares its vtable pointer with the primary base
1468 // we need to start counting at the end of the primary base's vtable.
1469 CurrentIndex = getNumVirtualFunctionPointers(PrimaryBase);
1470 }
Eli Friedman21517252009-12-15 03:31:17 +00001471
1472 // Collect all the primary bases, so we can check whether methods override
1473 // a method from the base.
1474 llvm::SmallPtrSet<const CXXRecordDecl *, 5> PrimaryBases;
1475 for (ASTRecordLayout::primary_base_info_iterator
1476 I = Layout.primary_base_begin(), E = Layout.primary_base_end();
1477 I != E; ++I)
1478 PrimaryBases.insert((*I).getBase());
1479
Anders Carlssonf942ee02009-11-27 20:47:55 +00001480 const CXXDestructorDecl *ImplicitVirtualDtor = 0;
1481
1482 for (CXXRecordDecl::method_iterator i = RD->method_begin(),
1483 e = RD->method_end(); i != e; ++i) {
1484 const CXXMethodDecl *MD = *i;
1485
1486 // We only want virtual methods.
1487 if (!MD->isVirtual())
1488 continue;
1489
1490 bool ShouldAddEntryForMethod = true;
1491
1492 // Check if this method overrides a method in the primary base.
1493 for (CXXMethodDecl::method_iterator i = MD->begin_overridden_methods(),
1494 e = MD->end_overridden_methods(); i != e; ++i) {
Anders Carlssonf3935b42009-12-04 05:51:56 +00001495 const CXXMethodDecl *OverriddenMD = *i;
Anders Carlssonf942ee02009-11-27 20:47:55 +00001496 const CXXRecordDecl *OverriddenRD = OverriddenMD->getParent();
1497 assert(OverriddenMD->isCanonicalDecl() &&
1498 "Should have the canonical decl of the overridden RD!");
1499
Eli Friedman21517252009-12-15 03:31:17 +00001500 if (PrimaryBases.count(OverriddenRD)) {
Anders Carlssonf942ee02009-11-27 20:47:55 +00001501 // Check if converting from the return type of the method to the
1502 // return type of the overridden method requires conversion.
1503 QualType ReturnType =
1504 MD->getType()->getAs<FunctionType>()->getResultType();
1505 QualType OverriddenReturnType =
1506 OverriddenMD->getType()->getAs<FunctionType>()->getResultType();
1507
1508 if (!TypeConversionRequiresAdjustment(CGM.getContext(),
1509 ReturnType, OverriddenReturnType)) {
1510 // This index is shared between the index in the vtable of the primary
1511 // base class.
1512 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1513 const CXXDestructorDecl *OverriddenDD =
1514 cast<CXXDestructorDecl>(OverriddenMD);
1515
1516 // Add both the complete and deleting entries.
1517 MethodVtableIndices[GlobalDecl(DD, Dtor_Complete)] =
1518 getMethodVtableIndex(GlobalDecl(OverriddenDD, Dtor_Complete));
1519 MethodVtableIndices[GlobalDecl(DD, Dtor_Deleting)] =
1520 getMethodVtableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting));
1521 } else {
1522 MethodVtableIndices[MD] = getMethodVtableIndex(OverriddenMD);
1523 }
1524
1525 // We don't need to add an entry for this method.
1526 ShouldAddEntryForMethod = false;
1527 break;
1528 }
1529 }
1530 }
1531
1532 if (!ShouldAddEntryForMethod)
1533 continue;
1534
1535 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1536 if (MD->isImplicit()) {
1537 assert(!ImplicitVirtualDtor &&
1538 "Did already see an implicit virtual dtor!");
1539 ImplicitVirtualDtor = DD;
1540 continue;
1541 }
1542
1543 // Add the complete dtor.
1544 MethodVtableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++;
1545
1546 // Add the deleting dtor.
1547 MethodVtableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++;
1548 } else {
1549 // Add the entry.
1550 MethodVtableIndices[MD] = CurrentIndex++;
1551 }
1552 }
1553
1554 if (ImplicitVirtualDtor) {
1555 // Itanium C++ ABI 2.5.2:
1556 // If a class has an implicitly-defined virtual destructor,
1557 // its entries come after the declared virtual function pointers.
1558
1559 // Add the complete dtor.
1560 MethodVtableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Complete)] =
1561 CurrentIndex++;
1562
1563 // Add the deleting dtor.
1564 MethodVtableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Deleting)] =
1565 CurrentIndex++;
1566 }
1567
1568 NumVirtualFunctionPointers[RD] = CurrentIndex;
1569}
1570
1571uint64_t CGVtableInfo::getNumVirtualFunctionPointers(const CXXRecordDecl *RD) {
1572 llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
1573 NumVirtualFunctionPointers.find(RD);
1574 if (I != NumVirtualFunctionPointers.end())
1575 return I->second;
1576
1577 ComputeMethodVtableIndices(RD);
1578
1579 I = NumVirtualFunctionPointers.find(RD);
1580 assert(I != NumVirtualFunctionPointers.end() && "Did not find entry!");
1581 return I->second;
1582}
1583
1584uint64_t CGVtableInfo::getMethodVtableIndex(GlobalDecl GD) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001585 MethodVtableIndicesTy::iterator I = MethodVtableIndices.find(GD);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001586 if (I != MethodVtableIndices.end())
1587 return I->second;
1588
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001589 const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
Anders Carlssonf942ee02009-11-27 20:47:55 +00001590
1591 ComputeMethodVtableIndices(RD);
1592
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001593 I = MethodVtableIndices.find(GD);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001594 assert(I != MethodVtableIndices.end() && "Did not find index!");
1595 return I->second;
1596}
1597
Eli Friedman31bc3ad2009-12-07 23:56:34 +00001598CGVtableInfo::AdjustmentVectorTy*
1599CGVtableInfo::getAdjustments(GlobalDecl GD) {
1600 SavedAdjustmentsTy::iterator I = SavedAdjustments.find(GD);
1601 if (I != SavedAdjustments.end())
1602 return &I->second;
Eli Friedman8174f2c2009-12-06 22:01:30 +00001603
1604 const CXXRecordDecl *RD = cast<CXXRecordDecl>(GD.getDecl()->getDeclContext());
Eli Friedman31bc3ad2009-12-07 23:56:34 +00001605 if (!SavedAdjustmentRecords.insert(RD).second)
1606 return 0;
Eli Friedman8174f2c2009-12-06 22:01:30 +00001607
Anders Carlsson5f9a8812010-01-14 02:29:07 +00001608 AddressPointsMapTy AddressPoints;
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00001609 OldVtableBuilder b(RD, RD, 0, CGM, false, AddressPoints);
Eli Friedman8174f2c2009-12-06 22:01:30 +00001610 D1(printf("vtable %s\n", RD->getNameAsCString()));
1611 b.GenerateVtableForBase(RD);
1612 b.GenerateVtableForVBases(RD);
Eli Friedman8174f2c2009-12-06 22:01:30 +00001613
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00001614 for (OldVtableBuilder::SavedAdjustmentsVectorTy::iterator
Eli Friedman31bc3ad2009-12-07 23:56:34 +00001615 i = b.getSavedAdjustments().begin(),
1616 e = b.getSavedAdjustments().end(); i != e; i++)
1617 SavedAdjustments[i->first].push_back(i->second);
Eli Friedman8174f2c2009-12-06 22:01:30 +00001618
Eli Friedman31bc3ad2009-12-07 23:56:34 +00001619 I = SavedAdjustments.find(GD);
1620 if (I != SavedAdjustments.end())
1621 return &I->second;
1622
1623 return 0;
Eli Friedman8174f2c2009-12-06 22:01:30 +00001624}
1625
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001626int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
1627 const CXXRecordDecl *VBase) {
1628 ClassPairTy ClassPair(RD, VBase);
1629
1630 VirtualBaseClassIndiciesTy::iterator I =
1631 VirtualBaseClassIndicies.find(ClassPair);
1632 if (I != VirtualBaseClassIndicies.end())
1633 return I->second;
1634
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001635 // FIXME: This seems expensive. Can we do a partial job to get
1636 // just this data.
Anders Carlsson5f9a8812010-01-14 02:29:07 +00001637 AddressPointsMapTy AddressPoints;
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00001638 OldVtableBuilder b(RD, RD, 0, CGM, false, AddressPoints);
Mike Stump75ce5732009-10-31 20:06:59 +00001639 D1(printf("vtable %s\n", RD->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001640 b.GenerateVtableForBase(RD);
1641 b.GenerateVtableForVBases(RD);
1642
1643 for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
1644 b.getVBIndex().begin(), E = b.getVBIndex().end(); I != E; ++I) {
1645 // Insert all types.
1646 ClassPairTy ClassPair(RD, I->first);
1647
1648 VirtualBaseClassIndicies.insert(std::make_pair(ClassPair, I->second));
1649 }
1650
1651 I = VirtualBaseClassIndicies.find(ClassPair);
1652 assert(I != VirtualBaseClassIndicies.end() && "Did not find index!");
1653
1654 return I->second;
1655}
1656
Anders Carlssonc8e39ec2009-12-05 21:03:56 +00001657uint64_t CGVtableInfo::getVtableAddressPoint(const CXXRecordDecl *RD) {
1658 uint64_t AddressPoint =
Anders Carlsson93a18842010-01-02 18:02:32 +00001659 (*(*(CGM.getVtableInfo().AddressPoints[RD]))[RD])[std::make_pair(RD, 0)];
Anders Carlssonc8e39ec2009-12-05 21:03:56 +00001660
1661 return AddressPoint;
1662}
1663
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00001664llvm::GlobalVariable *
Anders Carlsson0911ae82009-12-06 00:23:49 +00001665CGVtableInfo::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
Anders Carlsson232324c2009-12-06 00:53:22 +00001666 bool GenerateDefinition,
Anders Carlsson0911ae82009-12-06 00:23:49 +00001667 const CXXRecordDecl *LayoutClass,
Anders Carlsson5f9a8812010-01-14 02:29:07 +00001668 const CXXRecordDecl *RD, uint64_t Offset,
1669 AddressPointsMapTy& AddressPoints) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001670 llvm::SmallString<256> OutName;
Mike Stump2cefe382009-11-12 20:47:57 +00001671 if (LayoutClass != RD)
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00001672 CGM.getMangleContext().mangleCXXCtorVtable(LayoutClass, Offset / 8,
1673 RD, OutName);
Mike Stumpeac45592009-11-11 20:26:26 +00001674 else
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00001675 CGM.getMangleContext().mangleCXXVtable(RD, OutName);
Daniel Dunbare128dd12009-11-21 09:06:22 +00001676 llvm::StringRef Name = OutName.str();
Benjamin Kramerbb0a07b2009-10-11 22:57:54 +00001677
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00001678 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
Anders Carlsson93a18842010-01-02 18:02:32 +00001679 if (GV == 0 || CGM.getVtableInfo().AddressPoints[LayoutClass] == 0 ||
1680 GV->isDeclaration()) {
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00001681 OldVtableBuilder b(RD, LayoutClass, Offset, CGM, GenerateDefinition,
1682 AddressPoints);
Eli Friedman6c08ce72009-12-05 01:05:03 +00001683
1684 D1(printf("vtable %s\n", RD->getNameAsCString()));
1685 // First comes the vtables for all the non-virtual bases...
Mike Stumpd538a6d2009-12-24 07:29:41 +00001686 b.GenerateVtableForBase(RD, Offset);
Eli Friedman6c08ce72009-12-05 01:05:03 +00001687
1688 // then the vtables for all the virtual bases.
1689 b.GenerateVtableForVBases(RD, Offset);
1690
Anders Carlsson58b271d2009-12-05 22:19:10 +00001691 llvm::Constant *Init = 0;
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00001692 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
Anders Carlsson58b271d2009-12-05 22:19:10 +00001693 llvm::ArrayType *ArrayType =
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001694 llvm::ArrayType::get(Int8PtrTy, b.getVtableComponents().size());
Anders Carlssona95d4c52009-12-05 21:09:05 +00001695
Anders Carlsson232324c2009-12-06 00:53:22 +00001696 if (GenerateDefinition)
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001697 Init = llvm::ConstantArray::get(ArrayType, &b.getVtableComponents()[0],
1698 b.getVtableComponents().size());
Anders Carlsson232324c2009-12-06 00:53:22 +00001699
Mike Stumpaa51ad62009-11-19 04:04:36 +00001700 llvm::GlobalVariable *OGV = GV;
Anders Carlsson232324c2009-12-06 00:53:22 +00001701
1702 GV = new llvm::GlobalVariable(CGM.getModule(), ArrayType,
1703 /*isConstant=*/true, Linkage, Init, Name);
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001704 CGM.setGlobalVisibility(GV, RD);
1705
Mike Stumpaa51ad62009-11-19 04:04:36 +00001706 if (OGV) {
1707 GV->takeName(OGV);
Anders Carlsson58b271d2009-12-05 22:19:10 +00001708 llvm::Constant *NewPtr =
1709 llvm::ConstantExpr::getBitCast(GV, OGV->getType());
Mike Stumpaa51ad62009-11-19 04:04:36 +00001710 OGV->replaceAllUsesWith(NewPtr);
1711 OGV->eraseFromParent();
1712 }
Mike Stumpaa51ad62009-11-19 04:04:36 +00001713 }
Anders Carlssonb3f54b72009-12-05 21:28:12 +00001714
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00001715 if (GenerateDefinition && CGM.getLangOptions().DumpVtableLayouts) {
1716 VtableBuilder Builder(RD);
1717
1718 Builder.dumpLayout(llvm::errs());
1719 }
1720
Anders Carlssonb3f54b72009-12-05 21:28:12 +00001721 return GV;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001722}
Mike Stump9f23a142009-11-10 02:30:51 +00001723
Anders Carlsson232324c2009-12-06 00:53:22 +00001724void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
1725 const CXXRecordDecl *RD) {
Anders Carlssone1b3e622009-12-07 07:59:52 +00001726 llvm::GlobalVariable *&Vtable = Vtables[RD];
1727 if (Vtable) {
1728 assert(Vtable->getInitializer() && "Vtable doesn't have a definition!");
1729 return;
1730 }
1731
Anders Carlsson5f9a8812010-01-14 02:29:07 +00001732 AddressPointsMapTy AddressPoints;
1733 Vtable = GenerateVtable(Linkage, /*GenerateDefinition=*/true, RD, RD, 0,
1734 AddressPoints);
Anders Carlssone36a6b32010-01-02 01:01:18 +00001735 GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD);
Mike Stump1a139f82009-11-19 01:08:19 +00001736}
1737
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00001738llvm::GlobalVariable *CGVtableInfo::getVtable(const CXXRecordDecl *RD) {
Anders Carlsson232324c2009-12-06 00:53:22 +00001739 llvm::GlobalVariable *Vtable = Vtables.lookup(RD);
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00001740
Anders Carlsson5f9a8812010-01-14 02:29:07 +00001741 if (!Vtable) {
1742 AddressPointsMapTy AddressPoints;
Anders Carlsson232324c2009-12-06 00:53:22 +00001743 Vtable = GenerateVtable(llvm::GlobalValue::ExternalLinkage,
Anders Carlsson5f9a8812010-01-14 02:29:07 +00001744 /*GenerateDefinition=*/false, RD, RD, 0,
1745 AddressPoints);
1746 }
Mike Stumpaa51ad62009-11-19 04:04:36 +00001747
Anders Carlsson4ed44eb2009-12-05 22:42:54 +00001748 return Vtable;
Mike Stumpd846d082009-11-10 07:44:33 +00001749}
Mike Stumpeac45592009-11-11 20:26:26 +00001750
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00001751void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
1752 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
1753 const CXXRecordDecl *RD = MD->getParent();
1754
Anders Carlsson4ed44eb2009-12-05 22:42:54 +00001755 // If the class doesn't have a vtable we don't need to emit one.
1756 if (!RD->isDynamicClass())
1757 return;
1758
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00001759 // Get the key function.
Anders Carlsson5ebf8b42009-12-07 04:35:11 +00001760 const CXXMethodDecl *KeyFunction = CGM.getContext().getKeyFunction(RD);
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00001761
Anders Carlsson4ed44eb2009-12-05 22:42:54 +00001762 if (KeyFunction) {
1763 // We don't have the right key function.
1764 if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl())
1765 return;
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00001766 }
1767
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00001768 // Emit the data.
Douglas Gregorccecc1b2010-01-06 20:27:16 +00001769 GenerateClassData(CGM.getVtableLinkage(RD), RD);
Eli Friedman8174f2c2009-12-06 22:01:30 +00001770
1771 for (CXXRecordDecl::method_iterator i = RD->method_begin(),
1772 e = RD->method_end(); i != e; ++i) {
Eli Friedman31bc3ad2009-12-07 23:56:34 +00001773 if ((*i)->isVirtual() && ((*i)->hasInlineBody() || (*i)->isImplicit())) {
Eli Friedman8174f2c2009-12-06 22:01:30 +00001774 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(*i)) {
1775 CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Complete));
1776 CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Deleting));
1777 } else {
1778 CGM.BuildThunksForVirtual(GlobalDecl(*i));
1779 }
1780 }
1781 }
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00001782}
1783