blob: 0904f28d229c4b6adcdcdd52b8dbbe3f20c9e6a7 [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 Carlssone8a97562010-02-12 07:43:48 +000019#include "llvm/ADT/StringExtras.h"
Anders Carlsson5d40c6f2010-02-11 08:02:13 +000020#include "llvm/Support/Format.h"
Zhongxing Xu1721ef72009-11-13 05:46:16 +000021#include <cstdio>
Anders Carlsson2bb27f52009-10-11 22:13:54 +000022
23using namespace clang;
24using namespace CodeGen;
25
Anders Carlsson727ffb12010-02-11 19:39:49 +000026/// TypeConversionRequiresAdjustment - Returns whether conversion from a
27/// derived type to a base type requires adjustment.
28static bool
29TypeConversionRequiresAdjustment(ASTContext &Ctx,
30 const CXXRecordDecl *DerivedDecl,
31 const CXXRecordDecl *BaseDecl) {
32 CXXBasePaths Paths(/*FindAmbiguities=*/false,
33 /*RecordPaths=*/true, /*DetectVirtual=*/true);
34 if (!const_cast<CXXRecordDecl *>(DerivedDecl)->
35 isDerivedFrom(const_cast<CXXRecordDecl *>(BaseDecl), Paths)) {
36 assert(false && "Class must be derived from the passed in base class!");
37 return false;
38 }
39
40 // If we found a virtual base we always want to require adjustment.
41 if (Paths.getDetectedVirtual())
42 return true;
43
44 const CXXBasePath &Path = Paths.front();
45
46 for (size_t Start = 0, End = Path.size(); Start != End; ++Start) {
47 const CXXBasePathElement &Element = Path[Start];
48
49 // Check the base class offset.
50 const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Element.Class);
51
52 const RecordType *BaseType = Element.Base->getType()->getAs<RecordType>();
53 const CXXRecordDecl *Base = cast<CXXRecordDecl>(BaseType->getDecl());
54
55 if (Layout.getBaseClassOffset(Base) != 0) {
56 // This requires an adjustment.
57 return true;
58 }
59 }
60
61 return false;
62}
63
64static bool
65TypeConversionRequiresAdjustment(ASTContext &Ctx,
66 QualType DerivedType, QualType BaseType) {
67 // Canonicalize the types.
John McCall84c416b92010-02-12 06:15:07 +000068 CanQualType CanDerivedType = Ctx.getCanonicalType(DerivedType);
69 CanQualType CanBaseType = Ctx.getCanonicalType(BaseType);
Anders Carlsson727ffb12010-02-11 19:39:49 +000070
71 assert(CanDerivedType->getTypeClass() == CanBaseType->getTypeClass() &&
72 "Types must have same type class!");
73
74 if (CanDerivedType == CanBaseType) {
75 // No adjustment needed.
76 return false;
77 }
78
John McCall84c416b92010-02-12 06:15:07 +000079 if (isa<ReferenceType>(CanDerivedType)) {
80 CanDerivedType = CanDerivedType->getAs<ReferenceType>()->getPointeeType();
Anders Carlssondd27b5d2010-02-11 19:45:15 +000081 CanBaseType = CanBaseType->getAs<ReferenceType>()->getPointeeType();
John McCall84c416b92010-02-12 06:15:07 +000082 } else if (isa<PointerType>(CanDerivedType)) {
83 CanDerivedType = CanDerivedType->getAs<PointerType>()->getPointeeType();
Anders Carlssondd27b5d2010-02-11 19:45:15 +000084 CanBaseType = CanBaseType->getAs<PointerType>()->getPointeeType();
Anders Carlsson727ffb12010-02-11 19:39:49 +000085 } else {
86 assert(false && "Unexpected return type!");
87 }
88
John McCall84c416b92010-02-12 06:15:07 +000089 // We need to compare unqualified types here; consider
90 // const T *Base::foo();
91 // T *Derived::foo();
92 if (CanDerivedType.getUnqualifiedType() == CanBaseType.getUnqualifiedType()) {
Anders Carlsson727ffb12010-02-11 19:39:49 +000093 // No adjustment needed.
94 return false;
95 }
96
97 const CXXRecordDecl *DerivedDecl =
John McCall84c416b92010-02-12 06:15:07 +000098 cast<CXXRecordDecl>(cast<RecordType>(CanDerivedType)->getDecl());
Anders Carlsson727ffb12010-02-11 19:39:49 +000099
100 const CXXRecordDecl *BaseDecl =
John McCall84c416b92010-02-12 06:15:07 +0000101 cast<CXXRecordDecl>(cast<RecordType>(CanBaseType)->getDecl());
Anders Carlsson727ffb12010-02-11 19:39:49 +0000102
103 return TypeConversionRequiresAdjustment(Ctx, DerivedDecl, BaseDecl);
104}
105
Anders Carlsson65b49782010-02-12 05:25:12 +0000106static bool
107ReturnTypeConversionRequiresAdjustment(ASTContext &Context,
108 const CXXMethodDecl *DerivedMD,
109 const CXXMethodDecl *BaseMD) {
110 const FunctionType *BaseFT = BaseMD->getType()->getAs<FunctionType>();
111 const FunctionType *DerivedFT = DerivedMD->getType()->getAs<FunctionType>();
112
113 return TypeConversionRequiresAdjustment(Context, DerivedFT->getResultType(),
114 BaseFT->getResultType());
115}
116
Anders Carlssond59885022009-11-27 22:21:51 +0000117namespace {
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000118
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000119/// FinalOverriders - Contains the final overrider member functions for all
120/// member functions in the base subobjects of a class.
121class FinalOverriders {
Anders Carlsson136bd192010-02-12 16:55:34 +0000122public:
123 /// OverriderInfo - Information about a final overrider.
124 struct OverriderInfo {
125 /// Method - The method decl of the overrider.
126 const CXXMethodDecl *Method;
127
128 OverriderInfo() : Method(0) { }
129 };
130
131private:
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000132 /// MostDerivedClass - The most derived class for which the final overriders
133 /// are stored.
134 const CXXRecordDecl *MostDerivedClass;
135
136 ASTContext &Context;
137
138 /// MostDerivedClassLayout - the AST record layout of the most derived class.
139 const ASTRecordLayout &MostDerivedClassLayout;
140
141 typedef llvm::DenseMap<std::pair<BaseSubobject, const CXXMethodDecl *>,
Anders Carlsson136bd192010-02-12 16:55:34 +0000142 OverriderInfo> OverridersMapTy;
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000143
144 /// OverridersMap - The final overriders for all virtual member functions of
145 /// all the base subobjects of the most derived class.
146 OverridersMapTy OverridersMap;
147
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000148 typedef llvm::SmallVector<uint64_t, 1> OffsetVectorTy;
149
150 /// SubobjectOffsetsMapTy - This map is used for keeping track of all the
151 /// base subobject offsets that a single class declaration might refer to.
152 ///
153 /// For example, in:
154 ///
155 /// struct A { virtual void f(); };
156 /// struct B1 : A { };
157 /// struct B2 : A { };
158 /// struct C : B1, B2 { virtual void f(); };
159 ///
160 /// when we determine that C::f() overrides A::f(), we need to update the
161 /// overriders map for both A-in-B1 and A-in-B2 and the subobject offsets map
162 /// will have the subobject offsets for both A copies.
163 typedef llvm::DenseMap<const CXXRecordDecl *, OffsetVectorTy>
164 SubobjectOffsetsMapTy;
165
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000166 /// ComputeFinalOverriders - Compute the final overriders for a given base
167 /// subobject (and all its direct and indirect bases).
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000168 void ComputeFinalOverriders(BaseSubobject Base,
169 SubobjectOffsetsMapTy &Offsets);
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000170
171 /// AddOverriders - Add the final overriders for this base subobject to the
172 /// map of final overriders.
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000173 void AddOverriders(BaseSubobject Base, SubobjectOffsetsMapTy &Offsets);
174
175 /// PropagateOverrider - Propagate the NewMD overrider to all the functions
176 /// that OldMD overrides. For example, if we have:
177 ///
178 /// struct A { virtual void f(); };
179 /// struct B : A { virtual void f(); };
180 /// struct C : B { virtual void f(); };
181 ///
182 /// and we want to override B::f with C::f, we also need to override A::f with
183 /// C::f.
184 void PropagateOverrider(const CXXMethodDecl *OldMD,
185 const CXXMethodDecl *NewMD,
186 SubobjectOffsetsMapTy &Offsets);
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000187
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000188 static void MergeSubobjectOffsets(const SubobjectOffsetsMapTy &NewOffsets,
189 SubobjectOffsetsMapTy &Offsets);
190
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000191public:
192 explicit FinalOverriders(const CXXRecordDecl *MostDerivedClass);
193
194 /// getOverrider - Get the final overrider for the given method declaration in
195 /// the given base subobject.
Anders Carlsson136bd192010-02-12 16:55:34 +0000196 const OverriderInfo getOverrider(BaseSubobject Base,
197 const CXXMethodDecl *MD) const {
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000198 assert(OverridersMap.count(std::make_pair(Base, MD)) &&
199 "Did not find overrider!");
200
201 return OverridersMap.lookup(std::make_pair(Base, MD));
202 }
203
204 /// dump - dump the final overriders.
205 void dump() const {
206 dump(llvm::errs(), BaseSubobject(MostDerivedClass, 0));
207 }
208
209 /// dump - dump the final overriders for a base subobject, and all its direct
210 /// and indirect base subobjects.
211 void dump(llvm::raw_ostream &Out, BaseSubobject Base) const;
212};
213
214FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass)
215 : MostDerivedClass(MostDerivedClass),
216 Context(MostDerivedClass->getASTContext()),
217 MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)) {
218
219 // Compute the final overriders.
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000220 SubobjectOffsetsMapTy Offsets;
221 ComputeFinalOverriders(BaseSubobject(MostDerivedClass, 0), Offsets);
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000222
223 // And dump them (for now).
224 dump();
225}
226
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000227void FinalOverriders::AddOverriders(BaseSubobject Base,
228 SubobjectOffsetsMapTy &Offsets) {
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000229 const CXXRecordDecl *RD = Base.getBase();
230
231 for (CXXRecordDecl::method_iterator I = RD->method_begin(),
232 E = RD->method_end(); I != E; ++I) {
233 const CXXMethodDecl *MD = *I;
234
235 if (!MD->isVirtual())
236 continue;
237
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000238 // First, propagate the overrider.
239 PropagateOverrider(MD, MD, Offsets);
240
241 // Add the overrider as the final overrider of itself.
Anders Carlsson136bd192010-02-12 16:55:34 +0000242 OverriderInfo& Overrider = OverridersMap[std::make_pair(Base, MD)];
243 assert(!Overrider.Method && "Overrider should not exist yet!");
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000244
Anders Carlsson136bd192010-02-12 16:55:34 +0000245 Overrider.Method = MD;
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000246 }
247}
248
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000249void FinalOverriders::PropagateOverrider(const CXXMethodDecl *OldMD,
250 const CXXMethodDecl *NewMD,
251 SubobjectOffsetsMapTy &Offsets) {
252 for (CXXMethodDecl::method_iterator I = OldMD->begin_overridden_methods(),
253 E = OldMD->end_overridden_methods(); I != E; ++I) {
254 const CXXMethodDecl *OverriddenMD = *I;
255 const CXXRecordDecl *OverriddenRD = OverriddenMD->getParent();
256
257 // We want to override OverriddenMD in all subobjects, for example:
258 //
259 /// struct A { virtual void f(); };
260 /// struct B1 : A { };
261 /// struct B2 : A { };
262 /// struct C : B1, B2 { virtual void f(); };
263 ///
264 /// When overriding A::f with C::f we need to do so in both A subobjects.
265 const OffsetVectorTy &OffsetVector = Offsets[OverriddenRD];
266
267 // Go through all the subobjects.
268 for (unsigned I = 0, E = OffsetVector.size(); I != E; ++I) {
269 uint64_t Offset = OffsetVector[I];
270
Anders Carlsson136bd192010-02-12 16:55:34 +0000271 OverriderInfo &Overrider =
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000272 OverridersMap[std::make_pair(BaseSubobject(OverriddenRD, Offset),
273 OverriddenMD)];
Anders Carlsson136bd192010-02-12 16:55:34 +0000274 assert(Overrider.Method && "Did not find existing overrider!");
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000275
Anders Carlsson65b49782010-02-12 05:25:12 +0000276 assert(!ReturnTypeConversionRequiresAdjustment(Context, NewMD,
277 OverriddenMD) &&
278 "FIXME: Covariant return types not handled yet!");
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000279 // Set the new overrider.
Anders Carlsson136bd192010-02-12 16:55:34 +0000280 Overrider.Method = NewMD;
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000281
282 // And propagate it further.
283 PropagateOverrider(OverriddenMD, NewMD, Offsets);
284 }
285 }
286}
287
288void
289FinalOverriders::MergeSubobjectOffsets(const SubobjectOffsetsMapTy &NewOffsets,
290 SubobjectOffsetsMapTy &Offsets) {
291 // Iterate over the new offsets.
292 for (SubobjectOffsetsMapTy::const_iterator I = NewOffsets.begin(),
293 E = NewOffsets.end(); I != E; ++I) {
294 const CXXRecordDecl *NewRD = I->first;
295 const OffsetVectorTy& NewOffsetsVector = I->second;
296
297 OffsetVectorTy &OffsetsVector = Offsets[NewRD];
298 if (OffsetsVector.empty()) {
299 // There were no previous offsets in this vector, just insert all entries
300 // from the new offsets vector.
301 OffsetsVector.append(NewOffsetsVector.begin(), NewOffsetsVector.end());
302 continue;
303 }
304
305 assert(false && "FIXME: Handle merging the subobject offsets!");
306 }
307}
308
309void FinalOverriders::ComputeFinalOverriders(BaseSubobject Base,
310 SubobjectOffsetsMapTy &Offsets) {
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000311 const CXXRecordDecl *RD = Base.getBase();
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000312 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000313
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000314 SubobjectOffsetsMapTy NewOffsets;
315
316 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
317 E = RD->bases_end(); I != E; ++I) {
318 const CXXRecordDecl *BaseDecl =
319 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
320
321 assert(!I->isVirtual() && "FIXME: Handle virtual bases!");
322
323 uint64_t BaseOffset = Layout.getBaseClassOffset(BaseDecl) +
324 Base.getBaseOffset();
325
326 // Compute the final overriders for this base.
327 ComputeFinalOverriders(BaseSubobject(BaseDecl, BaseOffset), NewOffsets);
328 }
329
330 /// Now add the overriders for this particular subobject.
331 AddOverriders(Base, NewOffsets);
332
333 // And merge the newly discovered subobject offsets.
334 MergeSubobjectOffsets(NewOffsets, Offsets);
335
336 /// Finally, add the offset for our own subobject.
337 Offsets[RD].push_back(Base.getBaseOffset());
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000338}
339
340void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) const {
341
342 const CXXRecordDecl *RD = Base.getBase();
343 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
344
345 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
346 E = RD->bases_end(); I != E; ++I) {
347 assert(!I->isVirtual() && "FIXME: Handle virtual bases!");
348
349 const CXXRecordDecl *BaseDecl =
350 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
351
352 uint64_t BaseOffset = Layout.getBaseClassOffset(BaseDecl) +
353 Base.getBaseOffset();
354
355 dump(Out, BaseSubobject(BaseDecl, BaseOffset));
356 }
357
358 Out << "Final overriders for (" << RD->getQualifiedNameAsString() << ", ";
359 Out << Base.getBaseOffset() << ")\n";
360
361 // Now dump the overriders for this base subobject.
362 for (CXXRecordDecl::method_iterator I = RD->method_begin(),
363 E = RD->method_end(); I != E; ++I) {
364 const CXXMethodDecl *MD = *I;
365
366 if (!MD->isVirtual())
367 continue;
368
Anders Carlsson136bd192010-02-12 16:55:34 +0000369 OverriderInfo Overrider = getOverrider(Base, MD);
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000370
371 Out << " " << MD->getQualifiedNameAsString() << " - ";
Anders Carlsson136bd192010-02-12 16:55:34 +0000372 Out << Overrider.Method->getQualifiedNameAsString() << "\n";
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000373 }
374}
375
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000376/// VtableComponent - Represents a single component in a vtable.
377class VtableComponent {
378public:
379 enum Kind {
380 CK_VCallOffset,
381 CK_VBaseOffset,
382 CK_OffsetToTop,
383 CK_RTTI,
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000384 CK_FunctionPointer,
385
386 /// CK_CompleteDtorPointer - A pointer to the complete destructor.
387 CK_CompleteDtorPointer,
388
389 /// CK_DeletingDtorPointer - A pointer to the deleting destructor.
390 CK_DeletingDtorPointer
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000391 };
392
393 /// dump - Dump the contents of this component to the given stream.
394 void dump(llvm::raw_ostream &Out);
395
396 static VtableComponent MakeOffsetToTop(int64_t Offset) {
397 return VtableComponent(CK_OffsetToTop, Offset);
398 }
399
400 static VtableComponent MakeRTTI(const CXXRecordDecl *RD) {
401 return VtableComponent(CK_RTTI, reinterpret_cast<uintptr_t>(RD));
402 }
403
404 static VtableComponent MakeFunction(const CXXMethodDecl *MD) {
405 assert(!isa<CXXDestructorDecl>(MD) &&
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000406 "Don't use MakeFunction with destructors!");
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000407
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000408 return VtableComponent(CK_FunctionPointer,
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000409 reinterpret_cast<uintptr_t>(MD));
410 }
411
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000412 static VtableComponent MakeCompleteDtor(const CXXDestructorDecl *DD) {
413 return VtableComponent(CK_CompleteDtorPointer,
414 reinterpret_cast<uintptr_t>(DD));
415 }
416
417 static VtableComponent MakeDeletingDtor(const CXXDestructorDecl *DD) {
418 return VtableComponent(CK_DeletingDtorPointer,
419 reinterpret_cast<uintptr_t>(DD));
420 }
421
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000422 /// getKind - Get the kind of this vtable component.
423 Kind getKind() const {
424 return (Kind)(Value & 0x7);
425 }
426
427 int64_t getOffsetToTop() const {
428 assert(getKind() == CK_OffsetToTop && "Invalid component kind!");
429
430 return getOffset();
431 }
432
433 const CXXRecordDecl *getRTTIDecl() const {
434 assert(getKind() == CK_RTTI && "Invalid component kind!");
435
436 return reinterpret_cast<CXXRecordDecl *>(getPointer());
437 }
438
439 const CXXMethodDecl *getFunctionDecl() const {
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000440 assert(getKind() == CK_FunctionPointer);
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000441
442 return reinterpret_cast<CXXMethodDecl *>(getPointer());
443 }
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000444
445 const CXXDestructorDecl *getDestructorDecl() const {
446 assert((getKind() == CK_CompleteDtorPointer ||
447 getKind() == CK_DeletingDtorPointer) && "Invalid component kind!");
448
449 return reinterpret_cast<CXXDestructorDecl *>(getPointer());
450 }
451
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000452private:
453 VtableComponent(Kind ComponentKind, int64_t Offset) {
454 assert((ComponentKind == CK_VCallOffset ||
455 ComponentKind == CK_VBaseOffset ||
456 ComponentKind == CK_OffsetToTop) && "Invalid component kind!");
457 assert(Offset <= ((1LL << 56) - 1) && "Offset is too big!");
458
459 Value = ((Offset << 3) | ComponentKind);
460 }
461
462 VtableComponent(Kind ComponentKind, uintptr_t Ptr) {
463 assert((ComponentKind == CK_RTTI ||
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000464 ComponentKind == CK_FunctionPointer ||
465 ComponentKind == CK_CompleteDtorPointer ||
466 ComponentKind == CK_DeletingDtorPointer) &&
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000467 "Invalid component kind!");
468
469 assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!");
470
471 Value = Ptr | ComponentKind;
472 }
473
474 int64_t getOffset() const {
475 assert((getKind() == CK_VCallOffset || getKind() == CK_VBaseOffset ||
476 getKind() == CK_OffsetToTop) && "Invalid component kind!");
477
478 return Value >> 3;
479 }
480
481 uintptr_t getPointer() const {
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000482 assert((getKind() == CK_RTTI ||
483 getKind() == CK_FunctionPointer ||
484 getKind() == CK_CompleteDtorPointer ||
485 getKind() == CK_DeletingDtorPointer) &&
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000486 "Invalid component kind!");
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000487
488 return static_cast<uintptr_t>(Value & ~7ULL);
489 }
490
491 /// The kind is stored in the lower 3 bits of the value. For offsets, we
492 /// make use of the facts that classes can't be larger than 2^55 bytes,
493 /// so we store the offset in the lower part of the 61 bytes that remain.
494 /// (The reason that we're not simply using a PointerIntPair here is that we
495 /// need the offsets to be 64-bit, even when on a 32-bit machine).
496 int64_t Value;
497};
498
499/// VtableBuilder - Class for building vtable layout information.
Benjamin Kramer337e3a52009-11-28 19:45:26 +0000500class VtableBuilder {
Anders Carlsson65b49782010-02-12 05:25:12 +0000501public:
502 /// PrimaryBasesSetTy - A set of direct and indirect primary bases.
503 typedef llvm::SmallPtrSet<const CXXRecordDecl *, 8> PrimaryBasesSetTy;
504
505private:
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000506 /// MostDerivedClass - The most derived class for which we're building this
507 /// vtable.
508 const CXXRecordDecl *MostDerivedClass;
509
510 /// Context - The ASTContext which we will use for layout information.
Anders Carlsson65b49782010-02-12 05:25:12 +0000511 ASTContext &Context;
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000512
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000513 /// FinalOverriders - The final overriders of the most derived class.
514 FinalOverriders Overriders;
515
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000516 /// Components - The components of the vtable being built.
517 llvm::SmallVector<VtableComponent, 64> Components;
518
Anders Carlsson932c2f22010-02-11 17:18:51 +0000519 /// AddressPoints - Address points for the vtable being built.
520 CGVtableInfo::AddressPointsMapTy AddressPoints;
521
Anders Carlsson65b49782010-02-12 05:25:12 +0000522 void layoutVirtualMemberFunctions(BaseSubobject Base,
523 PrimaryBasesSetTy &PrimaryBases);
524
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000525 /// layoutSimpleVtable - A test function that will layout very simple vtables
526 /// without any bases. Just used for testing for now.
Anders Carlsson65b49782010-02-12 05:25:12 +0000527 void layoutSimpleVtable(BaseSubobject Base);
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000528
529public:
530 VtableBuilder(const CXXRecordDecl *MostDerivedClass)
531 : MostDerivedClass(MostDerivedClass),
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000532 Context(MostDerivedClass->getASTContext()), Overriders(MostDerivedClass) {
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000533
Anders Carlsson65b49782010-02-12 05:25:12 +0000534 layoutSimpleVtable(BaseSubobject(MostDerivedClass, 0));
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000535 }
536
537 /// dumpLayout - Dump the vtable layout.
538 void dumpLayout(llvm::raw_ostream&);
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000539};
540
Anders Carlsson65b49782010-02-12 05:25:12 +0000541/// OverridesMethodInPrimaryBase - Checks whether whether this virtual member
542/// function overrides a member function in a direct or indirect primary base.
543/// Returns the overridden member function, or null if none was found.
544static const CXXMethodDecl *
545OverridesMethodInPrimaryBase(const CXXMethodDecl *MD,
546 VtableBuilder::PrimaryBasesSetTy &PrimaryBases) {
547 for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
548 E = MD->end_overridden_methods(); I != E; ++I) {
549 const CXXMethodDecl *OverriddenMD = *I;
550 const CXXRecordDecl *OverriddenRD = OverriddenMD->getParent();
551 assert(OverriddenMD->isCanonicalDecl() &&
552 "Should have the canonical decl of the overridden RD!");
553
554 if (PrimaryBases.count(OverriddenRD))
555 return OverriddenMD;
556 }
557
558 return 0;
559}
560
561void
562VtableBuilder::layoutVirtualMemberFunctions(BaseSubobject Base,
563 PrimaryBasesSetTy &PrimaryBases) {
564 const CXXRecordDecl *RD = Base.getBase();
565
566 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
567
568 if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
569 if (Layout.getPrimaryBaseWasVirtual())
570 assert(false && "FIXME: Handle vbases here.");
571 else
572 assert(Layout.getBaseClassOffset(PrimaryBase) == 0 &&
573 "Primary base should have a zero offset!");
574
575 layoutVirtualMemberFunctions(BaseSubobject(PrimaryBase, 0), PrimaryBases);
576
577 if (!PrimaryBases.insert(PrimaryBase))
578 assert(false && "Found a duplicate primary base!");
579 }
Anders Carlsson932c2f22010-02-11 17:18:51 +0000580
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000581 // Now go through all virtual member functions and add them.
582 for (CXXRecordDecl::method_iterator I = RD->method_begin(),
583 E = RD->method_end(); I != E; ++I) {
584 const CXXMethodDecl *MD = *I;
Anders Carlsson65b49782010-02-12 05:25:12 +0000585
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000586 if (!MD->isVirtual())
587 continue;
Anders Carlsson65b49782010-02-12 05:25:12 +0000588
589 // Get the final overrider.
Anders Carlsson136bd192010-02-12 16:55:34 +0000590 FinalOverriders::OverriderInfo Overrider =
591 Overriders.getOverrider(Base, MD);
Anders Carlsson65b49782010-02-12 05:25:12 +0000592
593 // Check if this virtual member function overrides a method in a primary
594 // base. If this is the case, and the return type doesn't require adjustment
595 // then we can just use the member function from the primary base.
596 if (OverridesMethodInPrimaryBase(MD, PrimaryBases)) {
Anders Carlsson136bd192010-02-12 16:55:34 +0000597 assert(!ReturnTypeConversionRequiresAdjustment(Context, Overrider.Method,
598 MD) &&
Anders Carlsson65b49782010-02-12 05:25:12 +0000599 "FIXME: Handle covariant thunks!");
600
601 continue;
602 }
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000603
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000604 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
605 // Add both the complete destructor and the deleting destructor.
606 Components.push_back(VtableComponent::MakeCompleteDtor(DD));
607 Components.push_back(VtableComponent::MakeDeletingDtor(DD));
608 } else {
609 // Add the function.
610 Components.push_back(VtableComponent::MakeFunction(MD));
611 }
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000612 }
613}
614
Anders Carlsson65b49782010-02-12 05:25:12 +0000615void VtableBuilder::layoutSimpleVtable(BaseSubobject Base) {
616 const CXXRecordDecl *RD = Base.getBase();
617
618 // First, add the offset to top.
619 Components.push_back(VtableComponent::MakeOffsetToTop(0));
620
621 // Next, add the RTTI.
622 Components.push_back(VtableComponent::MakeRTTI(RD));
623
Anders Carlssone8a97562010-02-12 07:43:48 +0000624 uint64_t AddressPoint = Components.size();
Anders Carlsson65b49782010-02-12 05:25:12 +0000625
626 // Now go through all virtual member functions and add them.
627 PrimaryBasesSetTy PrimaryBases;
628 layoutVirtualMemberFunctions(Base, PrimaryBases);
629
Anders Carlssone8a97562010-02-12 07:43:48 +0000630 // Record the address point.
631 AddressPoints.insert(std::make_pair(Base, AddressPoint));
632
633 // Record the address points for all primary bases.
634 for (PrimaryBasesSetTy::const_iterator I = PrimaryBases.begin(),
635 E = PrimaryBases.end(); I != E; ++I) {
636 const CXXRecordDecl *BaseDecl = *I;
637
638 // We know that all the primary bases have the same offset as the base
639 // subobject.
640 BaseSubobject PrimaryBase(BaseDecl, Base.getBaseOffset());
641 AddressPoints.insert(std::make_pair(PrimaryBase, AddressPoint));
642 }
643
Anders Carlsson65b49782010-02-12 05:25:12 +0000644 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
645 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
646
647 // Traverse bases.
648 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
649 E = RD->bases_end(); I != E; ++I) {
650 const CXXRecordDecl *BaseDecl =
651 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
652
653 // Ignore the primary base.
654 if (BaseDecl == PrimaryBase)
655 continue;
656
657 assert(!I->isVirtual() && "FIXME: Handle virtual bases");
658
659 assert(false && "FIXME: Handle secondary virtual tables!");
660 }
661}
662
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000663/// dumpLayout - Dump the vtable layout.
664void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
665
666 Out << "Vtable for '" << MostDerivedClass->getQualifiedNameAsString();
667 Out << "' (" << Components.size() << " entries).\n";
668
Anders Carlsson932c2f22010-02-11 17:18:51 +0000669 // Iterate through the address points and insert them into a new map where
670 // they are keyed by the index and not the base object.
671 // Since an address point can be shared by multiple subobjects, we use an
672 // STL multimap.
673 std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
674 for (CGVtableInfo::AddressPointsMapTy::const_iterator I =
675 AddressPoints.begin(), E = AddressPoints.end(); I != E; ++I) {
676 const BaseSubobject& Base = I->first;
677 uint64_t Index = I->second;
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000678
Anders Carlsson932c2f22010-02-11 17:18:51 +0000679 AddressPointsByIndex.insert(std::make_pair(Index, Base));
680 }
681
682 for (unsigned I = 0, E = Components.size(); I != E; ++I) {
Anders Carlssone8a97562010-02-12 07:43:48 +0000683 uint64_t Index = I;
684
Anders Carlsson932c2f22010-02-11 17:18:51 +0000685 if (AddressPointsByIndex.count(I)) {
Anders Carlssone8a97562010-02-12 07:43:48 +0000686 std::string Str;
687
Anders Carlsson932c2f22010-02-11 17:18:51 +0000688
Anders Carlssone8a97562010-02-12 07:43:48 +0000689 if (AddressPointsByIndex.count(Index) == 1) {
690 const BaseSubobject &Base = AddressPointsByIndex.find(Index)->second;
691
692 // FIXME: Instead of dividing by 8, we should be using CharUnits.
693 Out << " -- (" << Base.getBase()->getQualifiedNameAsString();
694 Out << ", " << Base.getBaseOffset() / 8 << ") vtable address --\n";
695 } else {
696 uint64_t BaseOffset =
697 AddressPointsByIndex.lower_bound(Index)->second.getBaseOffset();
698
699 // We store the class names in a set to get a stable order.
700 std::set<std::string> ClassNames;
701 for (std::multimap<uint64_t, BaseSubobject>::const_iterator I =
702 AddressPointsByIndex.lower_bound(Index), E =
703 AddressPointsByIndex.upper_bound(Index); I != E; ++I) {
704 assert(I->second.getBaseOffset() == BaseOffset &&
705 "Invalid base offset!");
706 const CXXRecordDecl *RD = I->second.getBase();
707 ClassNames.insert(RD->getQualifiedNameAsString());
708 }
709
710 for (std::set<std::string>::const_iterator I = ClassNames.begin(),
711 E = ClassNames.end(); I != E; ++I) {
712 // FIXME: Instead of dividing by 8, we should be using CharUnits.
713 Out << " -- (" << *I;
714 Out << ", " << BaseOffset / 8 << ") vtable address --\n";
715 }
716 }
Anders Carlsson932c2f22010-02-11 17:18:51 +0000717 }
718
719 Out << llvm::format("%4d | ", I);
720
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000721 const VtableComponent &Component = Components[I];
722
723 // Dump the component.
724 switch (Component.getKind()) {
725 // FIXME: Remove this default case.
726 default:
727 assert(false && "Unhandled component kind!");
728 break;
729
730 case VtableComponent::CK_OffsetToTop:
731 Out << "offset_to_top (" << Component.getOffsetToTop() << ")";
732 break;
733
734 case VtableComponent::CK_RTTI:
735 Out << Component.getRTTIDecl()->getQualifiedNameAsString() << " RTTI";
736 break;
737
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000738 case VtableComponent::CK_FunctionPointer: {
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000739 const CXXMethodDecl *MD = Component.getFunctionDecl();
740
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000741 std::string Str =
742 PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
743 MD);
744 Out << Str;
Anders Carlsson09da3372010-02-12 02:38:13 +0000745 if (MD->isPure())
746 Out << " [pure]";
747
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000748 break;
749 }
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000750
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000751 case VtableComponent::CK_CompleteDtorPointer: {
752 const CXXDestructorDecl *DD = Component.getDestructorDecl();
753
754 Out << DD->getQualifiedNameAsString() << "() [complete]";
Anders Carlsson09da3372010-02-12 02:38:13 +0000755 if (DD->isPure())
756 Out << " [pure]";
757
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000758 break;
759 }
760
761 case VtableComponent::CK_DeletingDtorPointer: {
762 const CXXDestructorDecl *DD = Component.getDestructorDecl();
763
764 Out << DD->getQualifiedNameAsString() << "() [deleting]";
Anders Carlsson09da3372010-02-12 02:38:13 +0000765 if (DD->isPure())
766 Out << " [pure]";
767
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000768 break;
769 }
770
771 }
Anders Carlsson932c2f22010-02-11 17:18:51 +0000772
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000773 Out << '\n';
774 }
775
776}
777
778}
779
780namespace {
781class OldVtableBuilder {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000782public:
783 /// Index_t - Vtable index type.
784 typedef uint64_t Index_t;
Eli Friedman31bc3ad2009-12-07 23:56:34 +0000785 typedef std::vector<std::pair<GlobalDecl,
786 std::pair<GlobalDecl, ThunkAdjustment> > >
787 SavedAdjustmentsVectorTy;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000788private:
Anders Carlsson472404f2009-12-04 16:19:30 +0000789
Anders Carlssonfe5f7d92009-12-06 01:09:21 +0000790 // VtableComponents - The components of the vtable being built.
791 typedef llvm::SmallVector<llvm::Constant *, 64> VtableComponentsVectorTy;
792 VtableComponentsVectorTy VtableComponents;
793
Eli Friedman6c08ce72009-12-05 01:05:03 +0000794 const bool BuildVtable;
795
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000796 llvm::Type *Ptr8Ty;
Anders Carlssonbad80eb2009-12-04 18:36:22 +0000797
798 /// MostDerivedClass - The most derived class that this vtable is being
799 /// built for.
800 const CXXRecordDecl *MostDerivedClass;
801
Mike Stump83066c82009-11-13 01:54:23 +0000802 /// LayoutClass - The most derived class used for virtual base layout
803 /// information.
804 const CXXRecordDecl *LayoutClass;
Mike Stump653d0b92009-11-13 02:13:54 +0000805 /// LayoutOffset - The offset for Class in LayoutClass.
806 uint64_t LayoutOffset;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000807 /// BLayout - Layout for the most derived class that this vtable is being
808 /// built for.
809 const ASTRecordLayout &BLayout;
810 llvm::SmallSet<const CXXRecordDecl *, 32> IndirectPrimary;
811 llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase;
812 llvm::Constant *rtti;
813 llvm::LLVMContext &VMContext;
814 CodeGenModule &CGM; // Per-module state.
Anders Carlssonf2f31f42009-12-04 03:46:21 +0000815
Mike Stump90181eb2010-01-26 00:05:04 +0000816 llvm::DenseMap<const CXXMethodDecl *, Index_t> VCall;
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000817 llvm::DenseMap<GlobalDecl, Index_t> VCallOffset;
Mike Stump77537b12010-01-26 03:42:22 +0000818 llvm::DenseMap<GlobalDecl, Index_t> VCallOffsetForVCall;
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000819 // This is the offset to the nearest virtual base
Mike Stump90181eb2010-01-26 00:05:04 +0000820 llvm::DenseMap<const CXXMethodDecl *, Index_t> NonVirtualOffset;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000821 llvm::DenseMap<const CXXRecordDecl *, Index_t> VBIndex;
Mike Stumpbb9ff052009-10-27 23:46:47 +0000822
Anders Carlsson323bb042009-11-26 19:54:33 +0000823 /// PureVirtualFunction - Points to __cxa_pure_virtual.
824 llvm::Constant *PureVirtualFn;
825
Anders Carlssona84b6e82009-12-04 02:01:07 +0000826 /// VtableMethods - A data structure for keeping track of methods in a vtable.
827 /// Can add methods, override methods and iterate in vtable order.
828 class VtableMethods {
829 // MethodToIndexMap - Maps from a global decl to the index it has in the
830 // Methods vector.
831 llvm::DenseMap<GlobalDecl, uint64_t> MethodToIndexMap;
832
833 /// Methods - The methods, in vtable order.
834 typedef llvm::SmallVector<GlobalDecl, 16> MethodsVectorTy;
835 MethodsVectorTy Methods;
Eli Friedman8174f2c2009-12-06 22:01:30 +0000836 MethodsVectorTy OrigMethods;
Anders Carlssona84b6e82009-12-04 02:01:07 +0000837
838 public:
839 /// AddMethod - Add a method to the vtable methods.
840 void AddMethod(GlobalDecl GD) {
841 assert(!MethodToIndexMap.count(GD) &&
842 "Method has already been added!");
843
844 MethodToIndexMap[GD] = Methods.size();
845 Methods.push_back(GD);
Eli Friedman8174f2c2009-12-06 22:01:30 +0000846 OrigMethods.push_back(GD);
Anders Carlssona84b6e82009-12-04 02:01:07 +0000847 }
848
849 /// OverrideMethod - Replace a method with another.
850 void OverrideMethod(GlobalDecl OverriddenGD, GlobalDecl GD) {
851 llvm::DenseMap<GlobalDecl, uint64_t>::iterator i
852 = MethodToIndexMap.find(OverriddenGD);
853 assert(i != MethodToIndexMap.end() && "Did not find entry!");
854
855 // Get the index of the old decl.
856 uint64_t Index = i->second;
857
858 // Replace the old decl with the new decl.
859 Methods[Index] = GD;
860
Anders Carlssona84b6e82009-12-04 02:01:07 +0000861 // And add the new.
862 MethodToIndexMap[GD] = Index;
863 }
864
Anders Carlsson7bb70762009-12-04 15:49:02 +0000865 /// getIndex - Gives the index of a passed in GlobalDecl. Returns false if
866 /// the index couldn't be found.
Benjamin Kramer62ab6162009-12-04 22:45:27 +0000867 bool getIndex(GlobalDecl GD, uint64_t &Index) const {
Anders Carlsson7bb70762009-12-04 15:49:02 +0000868 llvm::DenseMap<GlobalDecl, uint64_t>::const_iterator i
869 = MethodToIndexMap.find(GD);
Eli Friedman3d2e9de2009-12-04 08:34:14 +0000870
Anders Carlsson7bb70762009-12-04 15:49:02 +0000871 if (i == MethodToIndexMap.end())
872 return false;
Anders Carlssone6096362009-12-04 03:41:37 +0000873
Anders Carlsson7bb70762009-12-04 15:49:02 +0000874 Index = i->second;
875 return true;
Anders Carlssone6096362009-12-04 03:41:37 +0000876 }
877
Eli Friedman8174f2c2009-12-06 22:01:30 +0000878 GlobalDecl getOrigMethod(uint64_t Index) const {
879 return OrigMethods[Index];
880 }
881
Anders Carlssona84b6e82009-12-04 02:01:07 +0000882 MethodsVectorTy::size_type size() const {
883 return Methods.size();
884 }
885
886 void clear() {
887 MethodToIndexMap.clear();
888 Methods.clear();
Eli Friedman8174f2c2009-12-06 22:01:30 +0000889 OrigMethods.clear();
Anders Carlssona84b6e82009-12-04 02:01:07 +0000890 }
891
Anders Carlssone6096362009-12-04 03:41:37 +0000892 GlobalDecl operator[](uint64_t Index) const {
Anders Carlssona84b6e82009-12-04 02:01:07 +0000893 return Methods[Index];
894 }
895 };
896
897 /// Methods - The vtable methods we're currently building.
898 VtableMethods Methods;
899
Anders Carlsson4c837d22009-12-04 02:26:15 +0000900 /// ThisAdjustments - For a given index in the vtable, contains the 'this'
901 /// pointer adjustment needed for a method.
902 typedef llvm::DenseMap<uint64_t, ThunkAdjustment> ThisAdjustmentsMapTy;
903 ThisAdjustmentsMapTy ThisAdjustments;
Anders Carlssond420a312009-11-26 19:32:45 +0000904
Eli Friedman31bc3ad2009-12-07 23:56:34 +0000905 SavedAdjustmentsVectorTy SavedAdjustments;
Eli Friedman8174f2c2009-12-06 22:01:30 +0000906
Anders Carlssonc521f952009-12-04 02:22:02 +0000907 /// BaseReturnTypes - Contains the base return types of methods who have been
908 /// overridden with methods whose return types require adjustment. Used for
909 /// generating covariant thunk information.
910 typedef llvm::DenseMap<uint64_t, CanQualType> BaseReturnTypesMapTy;
911 BaseReturnTypesMapTy BaseReturnTypes;
Anders Carlssond420a312009-11-26 19:32:45 +0000912
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000913 std::vector<Index_t> VCalls;
Mike Stump2cefe382009-11-12 20:47:57 +0000914
915 typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
Mike Stumpcd2b8212009-11-19 20:52:19 +0000916 // subAddressPoints - Used to hold the AddressPoints (offsets) into the built
917 // vtable for use in computing the initializers for the VTT.
918 llvm::DenseMap<CtorVtable_t, int64_t> &subAddressPoints;
Mike Stump2cefe382009-11-12 20:47:57 +0000919
Anders Carlsson5f9a8812010-01-14 02:29:07 +0000920 /// AddressPoints - Address points for this vtable.
921 CGVtableInfo::AddressPointsMapTy& AddressPoints;
922
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000923 typedef CXXRecordDecl::method_iterator method_iter;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000924 const uint32_t LLVMPointerWidth;
925 Index_t extra;
Mike Stump37dbe962009-10-15 02:04:03 +0000926 typedef std::vector<std::pair<const CXXRecordDecl *, int64_t> > Path_t;
Mike Stumpcd2b8212009-11-19 20:52:19 +0000927 static llvm::DenseMap<CtorVtable_t, int64_t>&
928 AllocAddressPoint(CodeGenModule &cgm, const CXXRecordDecl *l,
929 const CXXRecordDecl *c) {
Anders Carlsson93a18842010-01-02 18:02:32 +0000930 CGVtableInfo::AddrMap_t *&oref = cgm.getVtableInfo().AddressPoints[l];
Mike Stumpcd2b8212009-11-19 20:52:19 +0000931 if (oref == 0)
Anders Carlsson93a18842010-01-02 18:02:32 +0000932 oref = new CGVtableInfo::AddrMap_t;
Mike Stumpcd2b8212009-11-19 20:52:19 +0000933
934 llvm::DenseMap<CtorVtable_t, int64_t> *&ref = (*oref)[c];
935 if (ref == 0)
936 ref = new llvm::DenseMap<CtorVtable_t, int64_t>;
937 return *ref;
938 }
Anders Carlsson323bb042009-11-26 19:54:33 +0000939
Mike Stump90181eb2010-01-26 00:05:04 +0000940 bool DclIsSame(const FunctionDecl *New, const FunctionDecl *Old) {
941 FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
942 FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
943
944 // C++ [temp.fct]p2:
945 // A function template can be overloaded with other function templates
946 // and with normal (non-template) functions.
947 if ((OldTemplate == 0) != (NewTemplate == 0))
948 return false;
949
950 // Is the function New an overload of the function Old?
951 QualType OldQType = CGM.getContext().getCanonicalType(Old->getType());
952 QualType NewQType = CGM.getContext().getCanonicalType(New->getType());
953
954 // Compare the signatures (C++ 1.3.10) of the two functions to
955 // determine whether they are overloads. If we find any mismatch
956 // in the signature, they are overloads.
957
958 // If either of these functions is a K&R-style function (no
959 // prototype), then we consider them to have matching signatures.
960 if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) ||
961 isa<FunctionNoProtoType>(NewQType.getTypePtr()))
962 return true;
963
964 FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
965 FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
966
967 // The signature of a function includes the types of its
968 // parameters (C++ 1.3.10), which includes the presence or absence
969 // of the ellipsis; see C++ DR 357).
970 if (OldQType != NewQType &&
971 (OldType->getNumArgs() != NewType->getNumArgs() ||
972 OldType->isVariadic() != NewType->isVariadic() ||
973 !std::equal(OldType->arg_type_begin(), OldType->arg_type_end(),
974 NewType->arg_type_begin())))
975 return false;
976
977#if 0
978 // C++ [temp.over.link]p4:
979 // The signature of a function template consists of its function
980 // signature, its return type and its template parameter list. The names
981 // of the template parameters are significant only for establishing the
982 // relationship between the template parameters and the rest of the
983 // signature.
984 //
985 // We check the return type and template parameter lists for function
986 // templates first; the remaining checks follow.
987 if (NewTemplate &&
988 (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
989 OldTemplate->getTemplateParameters(),
990 TPL_TemplateMatch) ||
991 OldType->getResultType() != NewType->getResultType()))
992 return false;
993#endif
994
995 // If the function is a class member, its signature includes the
996 // cv-qualifiers (if any) on the function itself.
997 //
998 // As part of this, also check whether one of the member functions
999 // is static, in which case they are not overloads (C++
1000 // 13.1p2). While not part of the definition of the signature,
1001 // this check is important to determine whether these functions
1002 // can be overloaded.
1003 const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
1004 const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
1005 if (OldMethod && NewMethod &&
1006 !OldMethod->isStatic() && !NewMethod->isStatic() &&
1007 OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers())
1008 return false;
1009
1010 // The signatures match; this is not an overload.
1011 return true;
1012 }
1013
1014 typedef llvm::DenseMap<const CXXMethodDecl *, const CXXMethodDecl*>
1015 ForwardUnique_t;
1016 ForwardUnique_t ForwardUnique;
1017 llvm::DenseMap<const CXXMethodDecl*, const CXXMethodDecl*> UniqueOverrider;
1018
1019 void BuildUniqueOverrider(const CXXMethodDecl *U, const CXXMethodDecl *MD) {
1020 const CXXMethodDecl *PrevU = UniqueOverrider[MD];
1021 assert(U && "no unique overrider");
1022 if (PrevU == U)
1023 return;
1024 if (PrevU != U && PrevU != 0) {
1025 // If already set, note the two sets as the same
1026 if (0)
1027 printf("%s::%s same as %s::%s\n",
1028 PrevU->getParent()->getNameAsCString(),
1029 PrevU->getNameAsCString(),
1030 U->getParent()->getNameAsCString(),
1031 U->getNameAsCString());
1032 ForwardUnique[PrevU] = U;
1033 return;
1034 }
1035
1036 // Not set, set it now
1037 if (0)
1038 printf("marking %s::%s %p override as %s::%s\n",
1039 MD->getParent()->getNameAsCString(),
1040 MD->getNameAsCString(),
1041 (void*)MD,
1042 U->getParent()->getNameAsCString(),
1043 U->getNameAsCString());
1044 UniqueOverrider[MD] = U;
1045
1046 for (CXXMethodDecl::method_iterator mi = MD->begin_overridden_methods(),
1047 me = MD->end_overridden_methods(); mi != me; ++mi) {
1048 BuildUniqueOverrider(U, *mi);
1049 }
1050 }
1051
1052 void BuildUniqueOverriders(const CXXRecordDecl *RD) {
1053 if (0) printf("walking %s\n", RD->getNameAsCString());
1054 for (CXXRecordDecl::method_iterator i = RD->method_begin(),
1055 e = RD->method_end(); i != e; ++i) {
1056 const CXXMethodDecl *MD = *i;
1057 if (!MD->isVirtual())
1058 continue;
1059
1060 if (UniqueOverrider[MD] == 0) {
1061 // Only set this, if it hasn't been set yet.
1062 BuildUniqueOverrider(MD, MD);
1063 if (0)
1064 printf("top set is %s::%s %p\n",
1065 MD->getParent()->getNameAsCString(),
1066 MD->getNameAsCString(),
1067 (void*)MD);
1068 ForwardUnique[MD] = MD;
1069 }
1070 }
1071 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
1072 e = RD->bases_end(); i != e; ++i) {
1073 const CXXRecordDecl *Base =
1074 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
1075 BuildUniqueOverriders(Base);
1076 }
1077 }
1078
1079 static int DclCmp(const void *p1, const void *p2) {
1080 const CXXMethodDecl *MD1 = (const CXXMethodDecl *)p1;
1081 const CXXMethodDecl *MD2 = (const CXXMethodDecl *)p2;
1082 return (MD1->getIdentifier() - MD2->getIdentifier());
1083 }
1084
1085 void MergeForwarding() {
1086 typedef llvm::SmallVector<const CXXMethodDecl *, 100> A_t;
1087 A_t A;
1088 for (ForwardUnique_t::iterator I = ForwardUnique.begin(),
1089 E = ForwardUnique.end(); I != E; ++I) {
1090 if (I->first == I->second)
1091 // Only add the roots of all trees
1092 A.push_back(I->first);
1093 }
1094 llvm::array_pod_sort(A.begin(), A.end(), DclCmp);
1095 for (A_t::iterator I = A.begin(),
1096 E = A.end(); I != E; ++I) {
1097 A_t::iterator J = I;
1098 while (++J != E && DclCmp(*I, *J) == 0)
1099 if (DclIsSame(*I, *J)) {
1100 printf("connecting %s\n", (*I)->getNameAsCString());
1101 ForwardUnique[*J] = *I;
1102 }
1103 }
1104 }
1105
1106 const CXXMethodDecl *getUnique(const CXXMethodDecl *MD) {
1107 const CXXMethodDecl *U = UniqueOverrider[MD];
1108 assert(U && "unique overrider not found");
1109 while (ForwardUnique.count(U)) {
1110 const CXXMethodDecl *NU = ForwardUnique[U];
1111 if (NU == U) break;
1112 U = NU;
1113 }
1114 return U;
1115 }
Anders Carlsson72281172010-01-26 17:36:47 +00001116
1117 GlobalDecl getUnique(GlobalDecl GD) {
1118 const CXXMethodDecl *Unique = getUnique(cast<CXXMethodDecl>(GD.getDecl()));
1119
1120 if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(Unique))
1121 return GlobalDecl(CD, GD.getCtorType());
1122
1123 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(Unique))
1124 return GlobalDecl(DD, GD.getDtorType());
1125
1126 return Unique;
Mike Stump90181eb2010-01-26 00:05:04 +00001127 }
1128
Anders Carlsson323bb042009-11-26 19:54:33 +00001129 /// getPureVirtualFn - Return the __cxa_pure_virtual function.
1130 llvm::Constant* getPureVirtualFn() {
1131 if (!PureVirtualFn) {
1132 const llvm::FunctionType *Ty =
1133 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
1134 /*isVarArg=*/false);
1135 PureVirtualFn = wrap(CGM.CreateRuntimeFunction(Ty, "__cxa_pure_virtual"));
1136 }
1137
1138 return PureVirtualFn;
1139 }
1140
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001141public:
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00001142 OldVtableBuilder(const CXXRecordDecl *MostDerivedClass,
Eli Friedman6c08ce72009-12-05 01:05:03 +00001143 const CXXRecordDecl *l, uint64_t lo, CodeGenModule &cgm,
Anders Carlsson5f9a8812010-01-14 02:29:07 +00001144 bool build, CGVtableInfo::AddressPointsMapTy& AddressPoints)
Eli Friedman6c08ce72009-12-05 01:05:03 +00001145 : BuildVtable(build), MostDerivedClass(MostDerivedClass), LayoutClass(l),
1146 LayoutOffset(lo), BLayout(cgm.getContext().getASTRecordLayout(l)),
1147 rtti(0), VMContext(cgm.getModule().getContext()),CGM(cgm),
1148 PureVirtualFn(0),
Anders Carlssonbad80eb2009-12-04 18:36:22 +00001149 subAddressPoints(AllocAddressPoint(cgm, l, MostDerivedClass)),
Anders Carlsson5f9a8812010-01-14 02:29:07 +00001150 AddressPoints(AddressPoints),
1151 LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0))
1152 {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001153 Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
Anders Carlsson3f4336c2009-12-17 07:09:17 +00001154 if (BuildVtable) {
1155 QualType ClassType = CGM.getContext().getTagDeclType(MostDerivedClass);
1156 rtti = CGM.GetAddrOfRTTIDescriptor(ClassType);
1157 }
Mike Stump90181eb2010-01-26 00:05:04 +00001158 BuildUniqueOverriders(MostDerivedClass);
1159 MergeForwarding();
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001160 }
1161
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001162 // getVtableComponents - Returns a reference to the vtable components.
1163 const VtableComponentsVectorTy &getVtableComponents() const {
1164 return VtableComponents;
Anders Carlsson472404f2009-12-04 16:19:30 +00001165 }
1166
Anders Carlssone36a6b32010-01-02 01:01:18 +00001167 llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getVBIndex()
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001168 { return VBIndex; }
1169
Eli Friedman31bc3ad2009-12-07 23:56:34 +00001170 SavedAdjustmentsVectorTy &getSavedAdjustments()
1171 { return SavedAdjustments; }
Eli Friedman8174f2c2009-12-06 22:01:30 +00001172
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001173 llvm::Constant *wrap(Index_t i) {
1174 llvm::Constant *m;
1175 m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), i);
1176 return llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty);
1177 }
1178
1179 llvm::Constant *wrap(llvm::Constant *m) {
1180 return llvm::ConstantExpr::getBitCast(m, Ptr8Ty);
1181 }
1182
Mike Stumpd2808442010-01-22 02:51:26 +00001183//#define D1(x)
1184#define D1(X) do { if (getenv("DEBUG")) { X; } } while (0)
Mike Stump75ce5732009-10-31 20:06:59 +00001185
1186 void GenerateVBaseOffsets(const CXXRecordDecl *RD, uint64_t Offset,
Mike Stump28431212009-10-13 22:54:56 +00001187 bool updateVBIndex, Index_t current_vbindex) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001188 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
1189 e = RD->bases_end(); i != e; ++i) {
1190 const CXXRecordDecl *Base =
1191 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
Mike Stump28431212009-10-13 22:54:56 +00001192 Index_t next_vbindex = current_vbindex;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001193 if (i->isVirtual() && !SeenVBase.count(Base)) {
1194 SeenVBase.insert(Base);
Mike Stump28431212009-10-13 22:54:56 +00001195 if (updateVBIndex) {
Mike Stump75ce5732009-10-31 20:06:59 +00001196 next_vbindex = (ssize_t)(-(VCalls.size()*LLVMPointerWidth/8)
Mike Stump28431212009-10-13 22:54:56 +00001197 - 3*LLVMPointerWidth/8);
1198 VBIndex[Base] = next_vbindex;
1199 }
Mike Stump75ce5732009-10-31 20:06:59 +00001200 int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8;
1201 VCalls.push_back((0?700:0) + BaseOffset);
1202 D1(printf(" vbase for %s at %d delta %d most derived %s\n",
1203 Base->getNameAsCString(),
1204 (int)-VCalls.size()-3, (int)BaseOffset,
Mike Stumpd2808442010-01-22 02:51:26 +00001205 MostDerivedClass->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001206 }
Mike Stump28431212009-10-13 22:54:56 +00001207 // We also record offsets for non-virtual bases to closest enclosing
1208 // virtual base. We do this so that we don't have to search
1209 // for the nearst virtual base class when generating thunks.
1210 if (updateVBIndex && VBIndex.count(Base) == 0)
1211 VBIndex[Base] = next_vbindex;
Mike Stump75ce5732009-10-31 20:06:59 +00001212 GenerateVBaseOffsets(Base, Offset, updateVBIndex, next_vbindex);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001213 }
1214 }
1215
1216 void StartNewTable() {
1217 SeenVBase.clear();
1218 }
1219
Mike Stump8bccbfd2009-10-15 09:30:16 +00001220 Index_t getNVOffset_1(const CXXRecordDecl *D, const CXXRecordDecl *B,
1221 Index_t Offset = 0) {
1222
1223 if (B == D)
1224 return Offset;
1225
1226 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(D);
1227 for (CXXRecordDecl::base_class_const_iterator i = D->bases_begin(),
1228 e = D->bases_end(); i != e; ++i) {
1229 const CXXRecordDecl *Base =
1230 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
1231 int64_t BaseOffset = 0;
1232 if (!i->isVirtual())
1233 BaseOffset = Offset + Layout.getBaseClassOffset(Base);
1234 int64_t o = getNVOffset_1(Base, B, BaseOffset);
1235 if (o >= 0)
1236 return o;
1237 }
1238
1239 return -1;
1240 }
1241
1242 /// getNVOffset - Returns the non-virtual offset for the given (B) base of the
1243 /// derived class D.
1244 Index_t getNVOffset(QualType qB, QualType qD) {
Mike Stump46271322009-11-03 19:03:17 +00001245 qD = qD->getPointeeType();
1246 qB = qB->getPointeeType();
Mike Stump8bccbfd2009-10-15 09:30:16 +00001247 CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
1248 CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
1249 int64_t o = getNVOffset_1(D, B);
1250 if (o >= 0)
1251 return o;
1252
1253 assert(false && "FIXME: non-virtual base not found");
1254 return 0;
1255 }
1256
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001257 /// getVbaseOffset - Returns the index into the vtable for the virtual base
1258 /// offset for the given (B) virtual base of the derived class D.
1259 Index_t getVbaseOffset(QualType qB, QualType qD) {
Mike Stump46271322009-11-03 19:03:17 +00001260 qD = qD->getPointeeType();
1261 qB = qB->getPointeeType();
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001262 CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
1263 CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
Anders Carlssonbad80eb2009-12-04 18:36:22 +00001264 if (D != MostDerivedClass)
Eli Friedman03aa2f12009-11-30 01:19:33 +00001265 return CGM.getVtableInfo().getVirtualBaseOffsetIndex(D, B);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001266 llvm::DenseMap<const CXXRecordDecl *, Index_t>::iterator i;
1267 i = VBIndex.find(B);
1268 if (i != VBIndex.end())
1269 return i->second;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001270
Mike Stump28431212009-10-13 22:54:56 +00001271 assert(false && "FIXME: Base not found");
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001272 return 0;
1273 }
1274
Eli Friedman81fb0d22009-12-04 08:40:51 +00001275 bool OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
1276 Index_t OverrideOffset, Index_t Offset,
1277 int64_t CurrentVBaseOffset);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001278
Anders Carlsson495634e2009-12-04 02:39:04 +00001279 /// AppendMethods - Append the current methods to the vtable.
Anders Carlssonddf42c82009-12-04 02:56:03 +00001280 void AppendMethodsToVtable();
Anders Carlsson495634e2009-12-04 02:39:04 +00001281
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001282 llvm::Constant *WrapAddrOf(GlobalDecl GD) {
1283 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
1284
Anders Carlsson64457732009-11-24 05:08:52 +00001285 const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVtable(MD);
Mike Stump18e8b472009-10-27 23:36:26 +00001286
Mike Stumpcdeb8002009-12-03 16:55:20 +00001287 return wrap(CGM.GetAddrOfFunction(GD, Ty));
Mike Stump18e8b472009-10-27 23:36:26 +00001288 }
1289
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001290 void OverrideMethods(Path_t *Path, bool MorallyVirtual, int64_t Offset,
1291 int64_t CurrentVBaseOffset) {
Mike Stump37dbe962009-10-15 02:04:03 +00001292 for (Path_t::reverse_iterator i = Path->rbegin(),
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001293 e = Path->rend(); i != e; ++i) {
1294 const CXXRecordDecl *RD = i->first;
Mike Stump8bccbfd2009-10-15 09:30:16 +00001295 int64_t OverrideOffset = i->second;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001296 for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
1297 ++mi) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001298 const CXXMethodDecl *MD = *mi;
1299
1300 if (!MD->isVirtual())
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001301 continue;
1302
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001303 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1304 // Override both the complete and the deleting destructor.
1305 GlobalDecl CompDtor(DD, Dtor_Complete);
Eli Friedman81fb0d22009-12-04 08:40:51 +00001306 OverrideMethod(CompDtor, MorallyVirtual, OverrideOffset, Offset,
1307 CurrentVBaseOffset);
1308
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001309 GlobalDecl DeletingDtor(DD, Dtor_Deleting);
Eli Friedman81fb0d22009-12-04 08:40:51 +00001310 OverrideMethod(DeletingDtor, MorallyVirtual, OverrideOffset, Offset,
1311 CurrentVBaseOffset);
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001312 } else {
Eli Friedman81fb0d22009-12-04 08:40:51 +00001313 OverrideMethod(MD, MorallyVirtual, OverrideOffset, Offset,
1314 CurrentVBaseOffset);
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001315 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001316 }
1317 }
1318 }
1319
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001320 void AddMethod(const GlobalDecl GD, bool MorallyVirtual, Index_t Offset,
Eli Friedman03aa2f12009-11-30 01:19:33 +00001321 int64_t CurrentVBaseOffset) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001322 // If we can find a previously allocated slot for this, reuse it.
Eli Friedman81fb0d22009-12-04 08:40:51 +00001323 if (OverrideMethod(GD, MorallyVirtual, Offset, Offset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001324 CurrentVBaseOffset))
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001325 return;
1326
Mike Stump1f49d652010-01-22 18:48:47 +00001327 D1(printf(" vfn for %s at %d\n",
1328 dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsCString(),
1329 (int)Methods.size()));
1330
Anders Carlssoncdf18982009-12-04 02:08:24 +00001331 // We didn't find an entry in the vtable that we could use, add a new
1332 // entry.
1333 Methods.AddMethod(GD);
1334
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001335 VCallOffset[GD] = Offset/8 - CurrentVBaseOffset/8;
1336
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001337 if (MorallyVirtual) {
Anders Carlsson72281172010-01-26 17:36:47 +00001338 GlobalDecl UGD = getUnique(GD);
1339 const CXXMethodDecl *UMD = cast<CXXMethodDecl>(UGD.getDecl());
1340
Mike Stump90181eb2010-01-26 00:05:04 +00001341 assert(UMD && "final overrider not found");
1342
1343 Index_t &idx = VCall[UMD];
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001344 // Allocate the first one, after that, we reuse the previous one.
1345 if (idx == 0) {
Anders Carlsson72281172010-01-26 17:36:47 +00001346 VCallOffsetForVCall[UGD] = Offset/8;
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001347 NonVirtualOffset[UMD] = Offset/8 - CurrentVBaseOffset/8;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001348 idx = VCalls.size()+1;
Mike Stump90181eb2010-01-26 00:05:04 +00001349 VCalls.push_back(Offset/8 - CurrentVBaseOffset/8);
Mike Stump75ce5732009-10-31 20:06:59 +00001350 D1(printf(" vcall for %s at %d with delta %d\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001351 dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsCString(),
Mike Stump90181eb2010-01-26 00:05:04 +00001352 (int)-VCalls.size()-3, (int)VCalls[idx-1]));
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001353 }
1354 }
1355 }
1356
1357 void AddMethods(const CXXRecordDecl *RD, bool MorallyVirtual,
Eli Friedman03aa2f12009-11-30 01:19:33 +00001358 Index_t Offset, int64_t CurrentVBaseOffset) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001359 for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001360 ++mi) {
1361 const CXXMethodDecl *MD = *mi;
1362 if (!MD->isVirtual())
1363 continue;
1364
1365 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1366 // For destructors, add both the complete and the deleting destructor
1367 // to the vtable.
1368 AddMethod(GlobalDecl(DD, Dtor_Complete), MorallyVirtual, Offset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001369 CurrentVBaseOffset);
Eli Friedman03aa2f12009-11-30 01:19:33 +00001370 AddMethod(GlobalDecl(DD, Dtor_Deleting), MorallyVirtual, Offset,
1371 CurrentVBaseOffset);
1372 } else
1373 AddMethod(MD, MorallyVirtual, Offset, CurrentVBaseOffset);
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001374 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001375 }
1376
1377 void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
1378 const CXXRecordDecl *PrimaryBase,
1379 bool PrimaryBaseWasVirtual, bool MorallyVirtual,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001380 int64_t Offset, int64_t CurrentVBaseOffset,
1381 Path_t *Path) {
Mike Stump37dbe962009-10-15 02:04:03 +00001382 Path->push_back(std::make_pair(RD, Offset));
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001383 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
1384 e = RD->bases_end(); i != e; ++i) {
1385 if (i->isVirtual())
1386 continue;
1387 const CXXRecordDecl *Base =
1388 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
Mike Stump9eb76d42010-01-22 06:45:05 +00001389 uint64_t o = Offset + Layout.getBaseClassOffset(Base);
1390 StartNewTable();
1391 GenerateVtableForBase(Base, o, MorallyVirtual, false,
1392 true, Base == PrimaryBase && !PrimaryBaseWasVirtual,
1393 CurrentVBaseOffset, Path);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001394 }
Mike Stump37dbe962009-10-15 02:04:03 +00001395 Path->pop_back();
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001396 }
1397
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001398// #define D(X) do { X; } while (0)
1399#define D(X)
1400
1401 void insertVCalls(int InsertionPoint) {
Mike Stump75ce5732009-10-31 20:06:59 +00001402 D1(printf("============= combining vbase/vcall\n"));
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001403 D(VCalls.insert(VCalls.begin(), 673));
1404 D(VCalls.push_back(672));
Eli Friedman6c08ce72009-12-05 01:05:03 +00001405
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001406 VtableComponents.insert(VtableComponents.begin() + InsertionPoint,
1407 VCalls.size(), 0);
Eli Friedman6c08ce72009-12-05 01:05:03 +00001408 if (BuildVtable) {
1409 // The vcalls come first...
1410 for (std::vector<Index_t>::reverse_iterator i = VCalls.rbegin(),
1411 e = VCalls.rend();
1412 i != e; ++i)
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001413 VtableComponents[InsertionPoint++] = wrap((0?600:0) + *i);
Eli Friedman6c08ce72009-12-05 01:05:03 +00001414 }
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001415 VCalls.clear();
Mike Stump9f23a142009-11-10 02:30:51 +00001416 VCall.clear();
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001417 VCallOffsetForVCall.clear();
1418 VCallOffset.clear();
1419 NonVirtualOffset.clear();
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001420 }
1421
Mike Stump559387f2009-11-13 23:13:20 +00001422 void AddAddressPoints(const CXXRecordDecl *RD, uint64_t Offset,
1423 Index_t AddressPoint) {
1424 D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001425 RD->getNameAsCString(), MostDerivedClass->getNameAsCString(),
Mike Stump559387f2009-11-13 23:13:20 +00001426 LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
Mike Stumpcd2b8212009-11-19 20:52:19 +00001427 subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
Anders Carlsson5f9a8812010-01-14 02:29:07 +00001428 AddressPoints[BaseSubobject(RD, Offset)] = AddressPoint;
Mike Stump559387f2009-11-13 23:13:20 +00001429
1430 // Now also add the address point for all our primary bases.
1431 while (1) {
1432 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1433 RD = Layout.getPrimaryBase();
1434 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
1435 // FIXME: Double check this.
1436 if (RD == 0)
1437 break;
1438 if (PrimaryBaseWasVirtual &&
1439 BLayout.getVBaseClassOffset(RD) != Offset)
1440 break;
1441 D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001442 RD->getNameAsCString(), MostDerivedClass->getNameAsCString(),
Mike Stump559387f2009-11-13 23:13:20 +00001443 LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
Mike Stumpcd2b8212009-11-19 20:52:19 +00001444 subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
Anders Carlsson5f9a8812010-01-14 02:29:07 +00001445 AddressPoints[BaseSubobject(RD, Offset)] = AddressPoint;
Mike Stump559387f2009-11-13 23:13:20 +00001446 }
1447 }
1448
1449
Mike Stumpd538a6d2009-12-24 07:29:41 +00001450 void FinishGenerateVtable(const CXXRecordDecl *RD,
1451 const ASTRecordLayout &Layout,
1452 const CXXRecordDecl *PrimaryBase,
Mike Stump9eb76d42010-01-22 06:45:05 +00001453 bool ForNPNVBases, bool WasPrimaryBase,
Mike Stumpd538a6d2009-12-24 07:29:41 +00001454 bool PrimaryBaseWasVirtual,
1455 bool MorallyVirtual, int64_t Offset,
1456 bool ForVirtualBase, int64_t CurrentVBaseOffset,
1457 Path_t *Path) {
Mike Stump37dbe962009-10-15 02:04:03 +00001458 bool alloc = false;
1459 if (Path == 0) {
1460 alloc = true;
1461 Path = new Path_t;
1462 }
1463
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001464 StartNewTable();
1465 extra = 0;
Mike Stump9eb76d42010-01-22 06:45:05 +00001466 Index_t AddressPoint = 0;
1467 int VCallInsertionPoint = 0;
1468 if (!ForNPNVBases || !WasPrimaryBase) {
1469 bool DeferVCalls = MorallyVirtual || ForVirtualBase;
1470 VCallInsertionPoint = VtableComponents.size();
1471 if (!DeferVCalls) {
1472 insertVCalls(VCallInsertionPoint);
1473 } else
1474 // FIXME: just for extra, or for all uses of VCalls.size post this?
1475 extra = -VCalls.size();
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001476
Mike Stump9eb76d42010-01-22 06:45:05 +00001477 // Add the offset to top.
1478 VtableComponents.push_back(BuildVtable ? wrap(-((Offset-LayoutOffset)/8)) : 0);
Anders Carlsson472404f2009-12-04 16:19:30 +00001479
Mike Stump9eb76d42010-01-22 06:45:05 +00001480 // Add the RTTI information.
1481 VtableComponents.push_back(rtti);
Anders Carlsson472404f2009-12-04 16:19:30 +00001482
Mike Stump9eb76d42010-01-22 06:45:05 +00001483 AddressPoint = VtableComponents.size();
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001484
Mike Stump9eb76d42010-01-22 06:45:05 +00001485 AppendMethodsToVtable();
1486 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001487
1488 // and then the non-virtual bases.
1489 NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001490 MorallyVirtual, Offset, CurrentVBaseOffset, Path);
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001491
1492 if (ForVirtualBase) {
Mike Stump2cefe382009-11-12 20:47:57 +00001493 // FIXME: We're adding to VCalls in callers, we need to do the overrides
1494 // in the inner part, so that we know the complete set of vcalls during
1495 // the build and don't have to insert into methods. Saving out the
1496 // AddressPoint here, would need to be fixed, if we didn't do that. Also
1497 // retroactively adding vcalls for overrides later wind up in the wrong
1498 // place, the vcall slot has to be alloted during the walk of the base
1499 // when the function is first introduces.
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001500 AddressPoint += VCalls.size();
Mike Stump2cefe382009-11-12 20:47:57 +00001501 insertVCalls(VCallInsertionPoint);
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001502 }
1503
Mike Stump9eb76d42010-01-22 06:45:05 +00001504 if (!ForNPNVBases || !WasPrimaryBase)
1505 AddAddressPoints(RD, Offset, AddressPoint);
Mike Stump2cefe382009-11-12 20:47:57 +00001506
Mike Stump37dbe962009-10-15 02:04:03 +00001507 if (alloc) {
1508 delete Path;
1509 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001510 }
1511
Mike Stump75ce5732009-10-31 20:06:59 +00001512 void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
1513 bool updateVBIndex, Index_t current_vbindex,
Eli Friedman03aa2f12009-11-30 01:19:33 +00001514 int64_t CurrentVBaseOffset) {
Mike Stump75ce5732009-10-31 20:06:59 +00001515 if (!RD->isDynamicClass())
1516 return;
1517
1518 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1519 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1520 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
1521
1522 // vtables are composed from the chain of primaries.
Eli Friedman65d87222009-12-04 08:52:11 +00001523 if (PrimaryBase && !PrimaryBaseWasVirtual) {
Mike Stump75ce5732009-10-31 20:06:59 +00001524 D1(printf(" doing primaries for %s most derived %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001525 RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
Eli Friedman65d87222009-12-04 08:52:11 +00001526 Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
1527 updateVBIndex, current_vbindex, CurrentVBaseOffset);
Mike Stump75ce5732009-10-31 20:06:59 +00001528 }
1529
1530 D1(printf(" doing vcall entries for %s most derived %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001531 RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
Mike Stump75ce5732009-10-31 20:06:59 +00001532
1533 // And add the virtuals for the class to the primary vtable.
Eli Friedman03aa2f12009-11-30 01:19:33 +00001534 AddMethods(RD, MorallyVirtual, Offset, CurrentVBaseOffset);
Mike Stump75ce5732009-10-31 20:06:59 +00001535 }
1536
1537 void VBPrimaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
1538 bool updateVBIndex, Index_t current_vbindex,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001539 bool RDisVirtualBase, int64_t CurrentVBaseOffset,
Eli Friedman03aa2f12009-11-30 01:19:33 +00001540 bool bottom) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001541 if (!RD->isDynamicClass())
1542 return;
1543
1544 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1545 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1546 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
1547
1548 // vtables are composed from the chain of primaries.
1549 if (PrimaryBase) {
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001550 int BaseCurrentVBaseOffset = CurrentVBaseOffset;
1551 if (PrimaryBaseWasVirtual) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001552 IndirectPrimary.insert(PrimaryBase);
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001553 BaseCurrentVBaseOffset = BLayout.getVBaseClassOffset(PrimaryBase);
1554 }
Mike Stump75ce5732009-10-31 20:06:59 +00001555
1556 D1(printf(" doing primaries for %s most derived %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001557 RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
Mike Stump75ce5732009-10-31 20:06:59 +00001558
1559 VBPrimaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001560 updateVBIndex, current_vbindex, PrimaryBaseWasVirtual,
Eli Friedman03aa2f12009-11-30 01:19:33 +00001561 BaseCurrentVBaseOffset, false);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001562 }
1563
Mike Stump75ce5732009-10-31 20:06:59 +00001564 D1(printf(" doing vbase entries for %s most derived %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001565 RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
Mike Stump75ce5732009-10-31 20:06:59 +00001566 GenerateVBaseOffsets(RD, Offset, updateVBIndex, current_vbindex);
1567
1568 if (RDisVirtualBase || bottom) {
1569 Primaries(RD, MorallyVirtual, Offset, updateVBIndex, current_vbindex,
Eli Friedman03aa2f12009-11-30 01:19:33 +00001570 CurrentVBaseOffset);
Mike Stump75ce5732009-10-31 20:06:59 +00001571 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001572 }
1573
Mike Stumpd538a6d2009-12-24 07:29:41 +00001574 void GenerateVtableForBase(const CXXRecordDecl *RD, int64_t Offset = 0,
1575 bool MorallyVirtual = false,
1576 bool ForVirtualBase = false,
Mike Stump9eb76d42010-01-22 06:45:05 +00001577 bool ForNPNVBases = false,
1578 bool WasPrimaryBase = true,
Mike Stumpd538a6d2009-12-24 07:29:41 +00001579 int CurrentVBaseOffset = 0,
1580 Path_t *Path = 0) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001581 if (!RD->isDynamicClass())
Mike Stumpd538a6d2009-12-24 07:29:41 +00001582 return;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001583
Mike Stumpfa818082009-11-13 02:35:38 +00001584 // Construction vtable don't need parts that have no virtual bases and
1585 // aren't morally virtual.
Anders Carlssonbad80eb2009-12-04 18:36:22 +00001586 if ((LayoutClass != MostDerivedClass) &&
1587 RD->getNumVBases() == 0 && !MorallyVirtual)
Mike Stumpd538a6d2009-12-24 07:29:41 +00001588 return;
Mike Stumpfa818082009-11-13 02:35:38 +00001589
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001590 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1591 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1592 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
1593
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001594 extra = 0;
Mike Stump75ce5732009-10-31 20:06:59 +00001595 D1(printf("building entries for base %s most derived %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001596 RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001597
Mike Stump75ce5732009-10-31 20:06:59 +00001598 if (ForVirtualBase)
1599 extra = VCalls.size();
1600
Mike Stump9eb76d42010-01-22 06:45:05 +00001601 if (!ForNPNVBases || !WasPrimaryBase) {
1602 VBPrimaries(RD, MorallyVirtual, Offset, !ForVirtualBase, 0,
1603 ForVirtualBase, CurrentVBaseOffset, true);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001604
Mike Stump9eb76d42010-01-22 06:45:05 +00001605 if (Path)
1606 OverrideMethods(Path, MorallyVirtual, Offset, CurrentVBaseOffset);
1607 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001608
Mike Stump9eb76d42010-01-22 06:45:05 +00001609 FinishGenerateVtable(RD, Layout, PrimaryBase, ForNPNVBases, WasPrimaryBase,
1610 PrimaryBaseWasVirtual, MorallyVirtual, Offset,
1611 ForVirtualBase, CurrentVBaseOffset, Path);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001612 }
1613
1614 void GenerateVtableForVBases(const CXXRecordDecl *RD,
1615 int64_t Offset = 0,
Mike Stump37dbe962009-10-15 02:04:03 +00001616 Path_t *Path = 0) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001617 bool alloc = false;
1618 if (Path == 0) {
1619 alloc = true;
Mike Stump37dbe962009-10-15 02:04:03 +00001620 Path = new Path_t;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001621 }
1622 // FIXME: We also need to override using all paths to a virtual base,
1623 // right now, we just process the first path
1624 Path->push_back(std::make_pair(RD, Offset));
1625 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
1626 e = RD->bases_end(); i != e; ++i) {
1627 const CXXRecordDecl *Base =
1628 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
1629 if (i->isVirtual() && !IndirectPrimary.count(Base)) {
1630 // Mark it so we don't output it twice.
1631 IndirectPrimary.insert(Base);
1632 StartNewTable();
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001633 VCall.clear();
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001634 int64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001635 int64_t CurrentVBaseOffset = BaseOffset;
Mike Stump75ce5732009-10-31 20:06:59 +00001636 D1(printf("vtable %s virtual base %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001637 MostDerivedClass->getNameAsCString(), Base->getNameAsCString()));
Mike Stump9eb76d42010-01-22 06:45:05 +00001638 GenerateVtableForBase(Base, BaseOffset, true, true, false,
1639 true, CurrentVBaseOffset, Path);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001640 }
Mike Stump2cefe382009-11-12 20:47:57 +00001641 int64_t BaseOffset;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001642 if (i->isVirtual())
1643 BaseOffset = BLayout.getVBaseClassOffset(Base);
Mike Stump2cefe382009-11-12 20:47:57 +00001644 else {
1645 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1646 BaseOffset = Offset + Layout.getBaseClassOffset(Base);
1647 }
1648
Mike Stump37dbe962009-10-15 02:04:03 +00001649 if (Base->getNumVBases()) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001650 GenerateVtableForVBases(Base, BaseOffset, Path);
Mike Stump37dbe962009-10-15 02:04:03 +00001651 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001652 }
1653 Path->pop_back();
1654 if (alloc)
1655 delete Path;
1656 }
1657};
Anders Carlssonca1bf682009-12-03 01:54:02 +00001658} // end anonymous namespace
1659
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00001660bool OldVtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
Eli Friedman81fb0d22009-12-04 08:40:51 +00001661 Index_t OverrideOffset, Index_t Offset,
1662 int64_t CurrentVBaseOffset) {
Anders Carlssonca1bf682009-12-03 01:54:02 +00001663 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
1664
1665 const bool isPure = MD->isPure();
Anders Carlsson21bbc1e2009-12-05 17:04:47 +00001666
Anders Carlssonca1bf682009-12-03 01:54:02 +00001667 // FIXME: Should OverrideOffset's be Offset?
1668
Anders Carlsson21bbc1e2009-12-05 17:04:47 +00001669 for (CXXMethodDecl::method_iterator mi = MD->begin_overridden_methods(),
1670 e = MD->end_overridden_methods(); mi != e; ++mi) {
Anders Carlssonca1bf682009-12-03 01:54:02 +00001671 GlobalDecl OGD;
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001672 GlobalDecl OGD2;
Anders Carlssonca1bf682009-12-03 01:54:02 +00001673
Anders Carlssonf3935b42009-12-04 05:51:56 +00001674 const CXXMethodDecl *OMD = *mi;
Anders Carlssonca1bf682009-12-03 01:54:02 +00001675 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(OMD))
1676 OGD = GlobalDecl(DD, GD.getDtorType());
1677 else
1678 OGD = OMD;
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001679
Eli Friedman8174f2c2009-12-06 22:01:30 +00001680 // Check whether this is the method being overridden in this section of
1681 // the vtable.
Anders Carlsson7bb70762009-12-04 15:49:02 +00001682 uint64_t Index;
1683 if (!Methods.getIndex(OGD, Index))
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001684 continue;
1685
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001686 OGD2 = OGD;
1687
Eli Friedman8174f2c2009-12-06 22:01:30 +00001688 // Get the original method, which we should be computing thunks, etc,
1689 // against.
1690 OGD = Methods.getOrigMethod(Index);
1691 OMD = cast<CXXMethodDecl>(OGD.getDecl());
1692
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001693 QualType ReturnType =
1694 MD->getType()->getAs<FunctionType>()->getResultType();
1695 QualType OverriddenReturnType =
1696 OMD->getType()->getAs<FunctionType>()->getResultType();
Anders Carlssonca1bf682009-12-03 01:54:02 +00001697
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001698 // Check if we need a return type adjustment.
1699 if (TypeConversionRequiresAdjustment(CGM.getContext(), ReturnType,
1700 OverriddenReturnType)) {
1701 CanQualType &BaseReturnType = BaseReturnTypes[Index];
Anders Carlssonca1bf682009-12-03 01:54:02 +00001702
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001703 // Insert the base return type.
1704 if (BaseReturnType.isNull())
1705 BaseReturnType =
1706 CGM.getContext().getCanonicalType(OverriddenReturnType);
1707 }
Anders Carlssona93e9802009-12-04 03:52:52 +00001708
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001709 Methods.OverrideMethod(OGD, GD);
1710
Anders Carlsson72281172010-01-26 17:36:47 +00001711 GlobalDecl UGD = getUnique(GD);
1712 const CXXMethodDecl *UMD = cast<CXXMethodDecl>(UGD.getDecl());
1713 assert(UGD.getDecl() && "unique overrider not found");
1714 assert(UGD == getUnique(OGD) && "unique overrider not unique");
Mike Stump90181eb2010-01-26 00:05:04 +00001715
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001716 ThisAdjustments.erase(Index);
Mike Stump90181eb2010-01-26 00:05:04 +00001717 if (MorallyVirtual || VCall.count(UMD)) {
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001718
Mike Stump90181eb2010-01-26 00:05:04 +00001719 Index_t &idx = VCall[UMD];
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001720 if (idx == 0) {
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001721 VCallOffset[GD] = VCallOffset[OGD];
1722 // NonVirtualOffset[UMD] = CurrentVBaseOffset/8 - OverrideOffset/8;
1723 NonVirtualOffset[UMD] = VCallOffset[OGD];
Mike Stump77537b12010-01-26 03:42:22 +00001724 VCallOffsetForVCall[UMD] = OverrideOffset/8;
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001725 idx = VCalls.size()+1;
Mike Stump77537b12010-01-26 03:42:22 +00001726 VCalls.push_back(OverrideOffset/8 - CurrentVBaseOffset/8);
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001727 D1(printf(" vcall for %s at %d with delta %d most derived %s\n",
1728 MD->getNameAsString().c_str(), (int)-idx-3,
Mike Stumpd2808442010-01-22 02:51:26 +00001729 (int)VCalls[idx-1], MostDerivedClass->getNameAsCString()));
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001730 } else {
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001731 VCallOffset[GD] = NonVirtualOffset[UMD];
Anders Carlsson72281172010-01-26 17:36:47 +00001732 VCalls[idx-1] = -VCallOffsetForVCall[UGD] + OverrideOffset/8;
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001733 D1(printf(" vcall patch for %s at %d with delta %d most derived %s\n",
1734 MD->getNameAsString().c_str(), (int)-idx-3,
Mike Stumpd2808442010-01-22 02:51:26 +00001735 (int)VCalls[idx-1], MostDerivedClass->getNameAsCString()));
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001736 }
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001737 int64_t NonVirtualAdjustment = -VCallOffset[OGD];
Mike Stumpded0a402010-01-26 22:44:01 +00001738 QualType DerivedType = MD->getThisType(CGM.getContext());
1739 QualType BaseType = cast<const CXXMethodDecl>(OGD.getDecl())->getThisType(CGM.getContext());
1740 int64_t NonVirtualAdjustment2 = -(getNVOffset(BaseType, DerivedType)/8);
1741 if (NonVirtualAdjustment2 != NonVirtualAdjustment) {
1742 NonVirtualAdjustment = NonVirtualAdjustment2;
1743 }
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001744 int64_t VirtualAdjustment =
1745 -((idx + extra + 2) * LLVMPointerWidth / 8);
Anders Carlsson657f1392009-12-03 02:32:59 +00001746
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001747 // Optimize out virtual adjustments of 0.
1748 if (VCalls[idx-1] == 0)
1749 VirtualAdjustment = 0;
Anders Carlsson657f1392009-12-03 02:32:59 +00001750
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001751 ThunkAdjustment ThisAdjustment(NonVirtualAdjustment,
1752 VirtualAdjustment);
Anders Carlsson2ca285f2009-12-03 02:22:59 +00001753
Eli Friedman8174f2c2009-12-06 22:01:30 +00001754 if (!isPure && !ThisAdjustment.isEmpty()) {
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001755 ThisAdjustments[Index] = ThisAdjustment;
Eli Friedman31bc3ad2009-12-07 23:56:34 +00001756 SavedAdjustments.push_back(
1757 std::make_pair(GD, std::make_pair(OGD, ThisAdjustment)));
Eli Friedman8174f2c2009-12-06 22:01:30 +00001758 }
Anders Carlssonca1bf682009-12-03 01:54:02 +00001759 return true;
1760 }
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001761
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001762 VCallOffset[GD] = VCallOffset[OGD2] - OverrideOffset/8;
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001763
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001764 int64_t NonVirtualAdjustment = -VCallOffset[GD];
1765 QualType DerivedType = MD->getThisType(CGM.getContext());
1766 QualType BaseType = cast<const CXXMethodDecl>(OGD.getDecl())->getThisType(CGM.getContext());
1767 int64_t NonVirtualAdjustment2 = -(getNVOffset(BaseType, DerivedType)/8);
1768 if (NonVirtualAdjustment2 != NonVirtualAdjustment) {
1769 NonVirtualAdjustment = NonVirtualAdjustment2;
1770 }
1771
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001772 if (NonVirtualAdjustment) {
1773 ThunkAdjustment ThisAdjustment(NonVirtualAdjustment, 0);
1774
Eli Friedmanf2eda5e2009-12-06 22:33:51 +00001775 if (!isPure) {
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001776 ThisAdjustments[Index] = ThisAdjustment;
Eli Friedman31bc3ad2009-12-07 23:56:34 +00001777 SavedAdjustments.push_back(
1778 std::make_pair(GD, std::make_pair(OGD, ThisAdjustment)));
Eli Friedmanf2eda5e2009-12-06 22:33:51 +00001779 }
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001780 }
1781 return true;
Anders Carlssonca1bf682009-12-03 01:54:02 +00001782 }
1783
1784 return false;
Anders Carlssond59885022009-11-27 22:21:51 +00001785}
1786
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00001787void OldVtableBuilder::AppendMethodsToVtable() {
Eli Friedman6c08ce72009-12-05 01:05:03 +00001788 if (!BuildVtable) {
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001789 VtableComponents.insert(VtableComponents.end(), Methods.size(),
1790 (llvm::Constant *)0);
Eli Friedman6c08ce72009-12-05 01:05:03 +00001791 ThisAdjustments.clear();
1792 BaseReturnTypes.clear();
1793 Methods.clear();
1794 return;
1795 }
1796
Anders Carlsson472404f2009-12-04 16:19:30 +00001797 // Reserve room in the vtable for our new methods.
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001798 VtableComponents.reserve(VtableComponents.size() + Methods.size());
Anders Carlssonb07567c2009-12-04 03:07:26 +00001799
Anders Carlsson86809cd2009-12-04 02:43:50 +00001800 for (unsigned i = 0, e = Methods.size(); i != e; ++i) {
1801 GlobalDecl GD = Methods[i];
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00001802 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
1803
1804 // Get the 'this' pointer adjustment.
Anders Carlsson86809cd2009-12-04 02:43:50 +00001805 ThunkAdjustment ThisAdjustment = ThisAdjustments.lookup(i);
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00001806
1807 // Construct the return type adjustment.
1808 ThunkAdjustment ReturnAdjustment;
1809
1810 QualType BaseReturnType = BaseReturnTypes.lookup(i);
1811 if (!BaseReturnType.isNull() && !MD->isPure()) {
1812 QualType DerivedType =
1813 MD->getType()->getAs<FunctionType>()->getResultType();
1814
1815 int64_t NonVirtualAdjustment =
1816 getNVOffset(BaseReturnType, DerivedType) / 8;
1817
1818 int64_t VirtualAdjustment =
1819 getVbaseOffset(BaseReturnType, DerivedType);
1820
1821 ReturnAdjustment = ThunkAdjustment(NonVirtualAdjustment,
1822 VirtualAdjustment);
1823 }
1824
Anders Carlsson50f14742009-12-04 03:06:03 +00001825 llvm::Constant *Method = 0;
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00001826 if (!ReturnAdjustment.isEmpty()) {
1827 // Build a covariant thunk.
1828 CovariantThunkAdjustment Adjustment(ThisAdjustment, ReturnAdjustment);
Eli Friedman8174f2c2009-12-06 22:01:30 +00001829 Method = wrap(CGM.GetAddrOfCovariantThunk(GD, Adjustment));
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00001830 } else if (!ThisAdjustment.isEmpty()) {
1831 // Build a "regular" thunk.
Eli Friedman8174f2c2009-12-06 22:01:30 +00001832 Method = wrap(CGM.GetAddrOfThunk(GD, ThisAdjustment));
Anders Carlssonddf42c82009-12-04 02:56:03 +00001833 } else if (MD->isPure()) {
1834 // We have a pure virtual method.
Anders Carlsson50f14742009-12-04 03:06:03 +00001835 Method = getPureVirtualFn();
1836 } else {
1837 // We have a good old regular method.
1838 Method = WrapAddrOf(GD);
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00001839 }
Anders Carlsson50f14742009-12-04 03:06:03 +00001840
1841 // Add the method to the vtable.
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001842 VtableComponents.push_back(Method);
Anders Carlsson86809cd2009-12-04 02:43:50 +00001843 }
1844
Anders Carlsson50f14742009-12-04 03:06:03 +00001845
Anders Carlsson86809cd2009-12-04 02:43:50 +00001846 ThisAdjustments.clear();
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00001847 BaseReturnTypes.clear();
Anders Carlsson86809cd2009-12-04 02:43:50 +00001848
Anders Carlsson495634e2009-12-04 02:39:04 +00001849 Methods.clear();
Anders Carlsson495634e2009-12-04 02:39:04 +00001850}
1851
Anders Carlssonf942ee02009-11-27 20:47:55 +00001852void CGVtableInfo::ComputeMethodVtableIndices(const CXXRecordDecl *RD) {
1853
1854 // Itanium C++ ABI 2.5.2:
Anders Carlsson259688c2010-02-02 03:37:46 +00001855 // The order of the virtual function pointers in a virtual table is the
1856 // order of declaration of the corresponding member functions in the class.
Anders Carlssonf942ee02009-11-27 20:47:55 +00001857 //
Anders Carlsson259688c2010-02-02 03:37:46 +00001858 // There is an entry for any virtual function declared in a class,
1859 // whether it is a new function or overrides a base class function,
1860 // unless it overrides a function from the primary base, and conversion
1861 // between their return types does not require an adjustment.
Anders Carlssonf942ee02009-11-27 20:47:55 +00001862
1863 int64_t CurrentIndex = 0;
1864
1865 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1866 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1867
1868 if (PrimaryBase) {
Anders Carlssonc920fa22009-11-30 19:43:26 +00001869 assert(PrimaryBase->isDefinition() &&
1870 "Should have the definition decl of the primary base!");
Anders Carlssonf942ee02009-11-27 20:47:55 +00001871
1872 // Since the record decl shares its vtable pointer with the primary base
1873 // we need to start counting at the end of the primary base's vtable.
1874 CurrentIndex = getNumVirtualFunctionPointers(PrimaryBase);
1875 }
Eli Friedman21517252009-12-15 03:31:17 +00001876
1877 // Collect all the primary bases, so we can check whether methods override
1878 // a method from the base.
Anders Carlsson65b49782010-02-12 05:25:12 +00001879 VtableBuilder::PrimaryBasesSetTy PrimaryBases;
Eli Friedman21517252009-12-15 03:31:17 +00001880 for (ASTRecordLayout::primary_base_info_iterator
1881 I = Layout.primary_base_begin(), E = Layout.primary_base_end();
1882 I != E; ++I)
1883 PrimaryBases.insert((*I).getBase());
1884
Anders Carlssonf942ee02009-11-27 20:47:55 +00001885 const CXXDestructorDecl *ImplicitVirtualDtor = 0;
1886
1887 for (CXXRecordDecl::method_iterator i = RD->method_begin(),
1888 e = RD->method_end(); i != e; ++i) {
1889 const CXXMethodDecl *MD = *i;
1890
1891 // We only want virtual methods.
1892 if (!MD->isVirtual())
1893 continue;
1894
1895 bool ShouldAddEntryForMethod = true;
1896
1897 // Check if this method overrides a method in the primary base.
Anders Carlsson65b49782010-02-12 05:25:12 +00001898 if (const CXXMethodDecl *OverriddenMD =
1899 OverridesMethodInPrimaryBase(MD, PrimaryBases)) {
1900 // Check if converting from the return type of the method to the
1901 // return type of the overridden method requires conversion.
1902 if (!ReturnTypeConversionRequiresAdjustment(CGM.getContext(),
1903 MD, OverriddenMD)) {
1904 // This index is shared between the index in the vtable of the primary
1905 // base class.
1906 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1907 const CXXDestructorDecl *OverriddenDD =
1908 cast<CXXDestructorDecl>(OverriddenMD);
Anders Carlssonf942ee02009-11-27 20:47:55 +00001909
Anders Carlsson65b49782010-02-12 05:25:12 +00001910 // Add both the complete and deleting entries.
1911 MethodVtableIndices[GlobalDecl(DD, Dtor_Complete)] =
1912 getMethodVtableIndex(GlobalDecl(OverriddenDD, Dtor_Complete));
1913 MethodVtableIndices[GlobalDecl(DD, Dtor_Deleting)] =
1914 getMethodVtableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting));
1915 } else {
1916 MethodVtableIndices[MD] = getMethodVtableIndex(OverriddenMD);
1917 }
1918
1919 // We don't need to add an entry for this method.
1920 ShouldAddEntryForMethod = false;
1921 break;
Anders Carlssonf942ee02009-11-27 20:47:55 +00001922 }
1923 }
1924
1925 if (!ShouldAddEntryForMethod)
1926 continue;
1927
1928 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1929 if (MD->isImplicit()) {
1930 assert(!ImplicitVirtualDtor &&
1931 "Did already see an implicit virtual dtor!");
1932 ImplicitVirtualDtor = DD;
1933 continue;
1934 }
1935
1936 // Add the complete dtor.
1937 MethodVtableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++;
1938
1939 // Add the deleting dtor.
1940 MethodVtableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++;
1941 } else {
1942 // Add the entry.
1943 MethodVtableIndices[MD] = CurrentIndex++;
1944 }
1945 }
1946
1947 if (ImplicitVirtualDtor) {
1948 // Itanium C++ ABI 2.5.2:
1949 // If a class has an implicitly-defined virtual destructor,
1950 // its entries come after the declared virtual function pointers.
1951
1952 // Add the complete dtor.
1953 MethodVtableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Complete)] =
1954 CurrentIndex++;
1955
1956 // Add the deleting dtor.
1957 MethodVtableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Deleting)] =
1958 CurrentIndex++;
1959 }
1960
1961 NumVirtualFunctionPointers[RD] = CurrentIndex;
1962}
1963
1964uint64_t CGVtableInfo::getNumVirtualFunctionPointers(const CXXRecordDecl *RD) {
1965 llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
1966 NumVirtualFunctionPointers.find(RD);
1967 if (I != NumVirtualFunctionPointers.end())
1968 return I->second;
1969
1970 ComputeMethodVtableIndices(RD);
1971
1972 I = NumVirtualFunctionPointers.find(RD);
1973 assert(I != NumVirtualFunctionPointers.end() && "Did not find entry!");
1974 return I->second;
1975}
1976
1977uint64_t CGVtableInfo::getMethodVtableIndex(GlobalDecl GD) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001978 MethodVtableIndicesTy::iterator I = MethodVtableIndices.find(GD);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001979 if (I != MethodVtableIndices.end())
1980 return I->second;
1981
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001982 const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
Anders Carlssonf942ee02009-11-27 20:47:55 +00001983
1984 ComputeMethodVtableIndices(RD);
1985
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001986 I = MethodVtableIndices.find(GD);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001987 assert(I != MethodVtableIndices.end() && "Did not find index!");
1988 return I->second;
1989}
1990
Eli Friedman31bc3ad2009-12-07 23:56:34 +00001991CGVtableInfo::AdjustmentVectorTy*
1992CGVtableInfo::getAdjustments(GlobalDecl GD) {
1993 SavedAdjustmentsTy::iterator I = SavedAdjustments.find(GD);
1994 if (I != SavedAdjustments.end())
1995 return &I->second;
Eli Friedman8174f2c2009-12-06 22:01:30 +00001996
1997 const CXXRecordDecl *RD = cast<CXXRecordDecl>(GD.getDecl()->getDeclContext());
Eli Friedman31bc3ad2009-12-07 23:56:34 +00001998 if (!SavedAdjustmentRecords.insert(RD).second)
1999 return 0;
Eli Friedman8174f2c2009-12-06 22:01:30 +00002000
Anders Carlsson5f9a8812010-01-14 02:29:07 +00002001 AddressPointsMapTy AddressPoints;
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00002002 OldVtableBuilder b(RD, RD, 0, CGM, false, AddressPoints);
Eli Friedman8174f2c2009-12-06 22:01:30 +00002003 D1(printf("vtable %s\n", RD->getNameAsCString()));
2004 b.GenerateVtableForBase(RD);
2005 b.GenerateVtableForVBases(RD);
Eli Friedman8174f2c2009-12-06 22:01:30 +00002006
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00002007 for (OldVtableBuilder::SavedAdjustmentsVectorTy::iterator
Eli Friedman31bc3ad2009-12-07 23:56:34 +00002008 i = b.getSavedAdjustments().begin(),
2009 e = b.getSavedAdjustments().end(); i != e; i++)
2010 SavedAdjustments[i->first].push_back(i->second);
Eli Friedman8174f2c2009-12-06 22:01:30 +00002011
Eli Friedman31bc3ad2009-12-07 23:56:34 +00002012 I = SavedAdjustments.find(GD);
2013 if (I != SavedAdjustments.end())
2014 return &I->second;
2015
2016 return 0;
Eli Friedman8174f2c2009-12-06 22:01:30 +00002017}
2018
Anders Carlsson2bb27f52009-10-11 22:13:54 +00002019int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
2020 const CXXRecordDecl *VBase) {
2021 ClassPairTy ClassPair(RD, VBase);
2022
2023 VirtualBaseClassIndiciesTy::iterator I =
2024 VirtualBaseClassIndicies.find(ClassPair);
2025 if (I != VirtualBaseClassIndicies.end())
2026 return I->second;
2027
Anders Carlsson2bb27f52009-10-11 22:13:54 +00002028 // FIXME: This seems expensive. Can we do a partial job to get
2029 // just this data.
Anders Carlsson5f9a8812010-01-14 02:29:07 +00002030 AddressPointsMapTy AddressPoints;
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00002031 OldVtableBuilder b(RD, RD, 0, CGM, false, AddressPoints);
Mike Stump75ce5732009-10-31 20:06:59 +00002032 D1(printf("vtable %s\n", RD->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +00002033 b.GenerateVtableForBase(RD);
2034 b.GenerateVtableForVBases(RD);
2035
2036 for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
2037 b.getVBIndex().begin(), E = b.getVBIndex().end(); I != E; ++I) {
2038 // Insert all types.
2039 ClassPairTy ClassPair(RD, I->first);
2040
2041 VirtualBaseClassIndicies.insert(std::make_pair(ClassPair, I->second));
2042 }
2043
2044 I = VirtualBaseClassIndicies.find(ClassPair);
2045 assert(I != VirtualBaseClassIndicies.end() && "Did not find index!");
2046
2047 return I->second;
2048}
2049
Anders Carlssonc8e39ec2009-12-05 21:03:56 +00002050uint64_t CGVtableInfo::getVtableAddressPoint(const CXXRecordDecl *RD) {
2051 uint64_t AddressPoint =
Anders Carlsson93a18842010-01-02 18:02:32 +00002052 (*(*(CGM.getVtableInfo().AddressPoints[RD]))[RD])[std::make_pair(RD, 0)];
Anders Carlssonc8e39ec2009-12-05 21:03:56 +00002053
2054 return AddressPoint;
2055}
2056
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00002057llvm::GlobalVariable *
Anders Carlsson0911ae82009-12-06 00:23:49 +00002058CGVtableInfo::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
Anders Carlsson232324c2009-12-06 00:53:22 +00002059 bool GenerateDefinition,
Anders Carlsson0911ae82009-12-06 00:23:49 +00002060 const CXXRecordDecl *LayoutClass,
Anders Carlsson5f9a8812010-01-14 02:29:07 +00002061 const CXXRecordDecl *RD, uint64_t Offset,
2062 AddressPointsMapTy& AddressPoints) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00002063 llvm::SmallString<256> OutName;
Mike Stump2cefe382009-11-12 20:47:57 +00002064 if (LayoutClass != RD)
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00002065 CGM.getMangleContext().mangleCXXCtorVtable(LayoutClass, Offset / 8,
2066 RD, OutName);
Mike Stumpeac45592009-11-11 20:26:26 +00002067 else
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00002068 CGM.getMangleContext().mangleCXXVtable(RD, OutName);
Daniel Dunbare128dd12009-11-21 09:06:22 +00002069 llvm::StringRef Name = OutName.str();
Benjamin Kramerbb0a07b2009-10-11 22:57:54 +00002070
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00002071 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
Anders Carlsson93a18842010-01-02 18:02:32 +00002072 if (GV == 0 || CGM.getVtableInfo().AddressPoints[LayoutClass] == 0 ||
2073 GV->isDeclaration()) {
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00002074 OldVtableBuilder b(RD, LayoutClass, Offset, CGM, GenerateDefinition,
2075 AddressPoints);
Eli Friedman6c08ce72009-12-05 01:05:03 +00002076
2077 D1(printf("vtable %s\n", RD->getNameAsCString()));
2078 // First comes the vtables for all the non-virtual bases...
Mike Stumpd538a6d2009-12-24 07:29:41 +00002079 b.GenerateVtableForBase(RD, Offset);
Eli Friedman6c08ce72009-12-05 01:05:03 +00002080
2081 // then the vtables for all the virtual bases.
2082 b.GenerateVtableForVBases(RD, Offset);
2083
Anders Carlsson58b271d2009-12-05 22:19:10 +00002084 llvm::Constant *Init = 0;
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00002085 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
Anders Carlsson58b271d2009-12-05 22:19:10 +00002086 llvm::ArrayType *ArrayType =
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00002087 llvm::ArrayType::get(Int8PtrTy, b.getVtableComponents().size());
Anders Carlssona95d4c52009-12-05 21:09:05 +00002088
Anders Carlsson232324c2009-12-06 00:53:22 +00002089 if (GenerateDefinition)
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00002090 Init = llvm::ConstantArray::get(ArrayType, &b.getVtableComponents()[0],
2091 b.getVtableComponents().size());
Anders Carlsson232324c2009-12-06 00:53:22 +00002092
Mike Stumpaa51ad62009-11-19 04:04:36 +00002093 llvm::GlobalVariable *OGV = GV;
Anders Carlsson232324c2009-12-06 00:53:22 +00002094
2095 GV = new llvm::GlobalVariable(CGM.getModule(), ArrayType,
2096 /*isConstant=*/true, Linkage, Init, Name);
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00002097 CGM.setGlobalVisibility(GV, RD);
2098
Mike Stumpaa51ad62009-11-19 04:04:36 +00002099 if (OGV) {
2100 GV->takeName(OGV);
Anders Carlsson58b271d2009-12-05 22:19:10 +00002101 llvm::Constant *NewPtr =
2102 llvm::ConstantExpr::getBitCast(GV, OGV->getType());
Mike Stumpaa51ad62009-11-19 04:04:36 +00002103 OGV->replaceAllUsesWith(NewPtr);
2104 OGV->eraseFromParent();
2105 }
Mike Stumpaa51ad62009-11-19 04:04:36 +00002106 }
Anders Carlssonb3f54b72009-12-05 21:28:12 +00002107
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00002108 if (GenerateDefinition && CGM.getLangOptions().DumpVtableLayouts) {
2109 VtableBuilder Builder(RD);
2110
2111 Builder.dumpLayout(llvm::errs());
2112 }
2113
Anders Carlssonb3f54b72009-12-05 21:28:12 +00002114 return GV;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00002115}
Mike Stump9f23a142009-11-10 02:30:51 +00002116
Anders Carlsson232324c2009-12-06 00:53:22 +00002117void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
2118 const CXXRecordDecl *RD) {
Anders Carlssone1b3e622009-12-07 07:59:52 +00002119 llvm::GlobalVariable *&Vtable = Vtables[RD];
2120 if (Vtable) {
2121 assert(Vtable->getInitializer() && "Vtable doesn't have a definition!");
2122 return;
2123 }
2124
Anders Carlsson5f9a8812010-01-14 02:29:07 +00002125 AddressPointsMapTy AddressPoints;
2126 Vtable = GenerateVtable(Linkage, /*GenerateDefinition=*/true, RD, RD, 0,
2127 AddressPoints);
Anders Carlssone36a6b32010-01-02 01:01:18 +00002128 GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD);
Mike Stump1a139f82009-11-19 01:08:19 +00002129}
2130
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00002131llvm::GlobalVariable *CGVtableInfo::getVtable(const CXXRecordDecl *RD) {
Anders Carlsson232324c2009-12-06 00:53:22 +00002132 llvm::GlobalVariable *Vtable = Vtables.lookup(RD);
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00002133
Anders Carlsson5f9a8812010-01-14 02:29:07 +00002134 if (!Vtable) {
2135 AddressPointsMapTy AddressPoints;
Anders Carlsson232324c2009-12-06 00:53:22 +00002136 Vtable = GenerateVtable(llvm::GlobalValue::ExternalLinkage,
Anders Carlsson5f9a8812010-01-14 02:29:07 +00002137 /*GenerateDefinition=*/false, RD, RD, 0,
2138 AddressPoints);
2139 }
Mike Stumpaa51ad62009-11-19 04:04:36 +00002140
Anders Carlsson4ed44eb2009-12-05 22:42:54 +00002141 return Vtable;
Mike Stumpd846d082009-11-10 07:44:33 +00002142}
Mike Stumpeac45592009-11-11 20:26:26 +00002143
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00002144void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
2145 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
2146 const CXXRecordDecl *RD = MD->getParent();
2147
Anders Carlsson4ed44eb2009-12-05 22:42:54 +00002148 // If the class doesn't have a vtable we don't need to emit one.
2149 if (!RD->isDynamicClass())
2150 return;
2151
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00002152 // Get the key function.
Anders Carlsson5ebf8b42009-12-07 04:35:11 +00002153 const CXXMethodDecl *KeyFunction = CGM.getContext().getKeyFunction(RD);
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00002154
Anders Carlsson4ed44eb2009-12-05 22:42:54 +00002155 if (KeyFunction) {
2156 // We don't have the right key function.
2157 if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl())
2158 return;
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00002159 }
2160
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00002161 // Emit the data.
Douglas Gregorccecc1b2010-01-06 20:27:16 +00002162 GenerateClassData(CGM.getVtableLinkage(RD), RD);
Eli Friedman8174f2c2009-12-06 22:01:30 +00002163
2164 for (CXXRecordDecl::method_iterator i = RD->method_begin(),
2165 e = RD->method_end(); i != e; ++i) {
Eli Friedman31bc3ad2009-12-07 23:56:34 +00002166 if ((*i)->isVirtual() && ((*i)->hasInlineBody() || (*i)->isImplicit())) {
Eli Friedman8174f2c2009-12-06 22:01:30 +00002167 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(*i)) {
2168 CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Complete));
2169 CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Deleting));
2170 } else {
2171 CGM.BuildThunksForVirtual(GlobalDecl(*i));
2172 }
2173 }
2174 }
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00002175}
2176