blob: 715fb184280d5b2b63b1ef9b235b26c8044b706b [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
Anders Carlsson5272c252010-02-12 17:37:14 +0000107ReturnTypeConversionRequiresAdjustment(const CXXMethodDecl *DerivedMD,
Anders Carlsson65b49782010-02-12 05:25:12 +0000108 const CXXMethodDecl *BaseMD) {
Anders Carlsson5272c252010-02-12 17:37:14 +0000109 ASTContext &Context = DerivedMD->getASTContext();
110
Anders Carlsson65b49782010-02-12 05:25:12 +0000111 const FunctionType *BaseFT = BaseMD->getType()->getAs<FunctionType>();
112 const FunctionType *DerivedFT = DerivedMD->getType()->getAs<FunctionType>();
113
114 return TypeConversionRequiresAdjustment(Context, DerivedFT->getResultType(),
115 BaseFT->getResultType());
116}
117
Anders Carlssond59885022009-11-27 22:21:51 +0000118namespace {
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000119
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000120/// FinalOverriders - Contains the final overrider member functions for all
121/// member functions in the base subobjects of a class.
122class FinalOverriders {
Anders Carlsson136bd192010-02-12 16:55:34 +0000123public:
Anders Carlssoneee53d92010-02-13 02:02:03 +0000124 /// BaseOffset - Represents an offset from a derived class to a direct or
125 /// indirect base class.
126 struct BaseOffset {
127 /// VirtualBase - If the path from the derived class to the base class
128 /// involves a virtual base class, this holds its declaration.
129 const CXXRecordDecl *VirtualBase;
130
131 /// NonVirtualOffset - The offset from the derived class to the base class.
132 /// Or the offset from the virtual base class to the base class, if the path
133 /// from the derived class to the base class involves a virtual base class.
134 uint64_t NonVirtualOffset;
135
136 BaseOffset() : VirtualBase(0), NonVirtualOffset(0) { }
137 BaseOffset(const CXXRecordDecl *VirtualBase, uint64_t NonVirtualOffset)
138 : VirtualBase(VirtualBase), NonVirtualOffset(NonVirtualOffset) { }
139
140 bool isEmpty() const { return !NonVirtualOffset && !VirtualBase; };
141 };
142
Anders Carlsson136bd192010-02-12 16:55:34 +0000143 /// OverriderInfo - Information about a final overrider.
144 struct OverriderInfo {
145 /// Method - The method decl of the overrider.
146 const CXXMethodDecl *Method;
147
Anders Carlssoneee53d92010-02-13 02:02:03 +0000148 OverriderInfo() : Method(0) { }
Anders Carlsson136bd192010-02-12 16:55:34 +0000149 };
150
151private:
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000152 /// MostDerivedClass - The most derived class for which the final overriders
153 /// are stored.
154 const CXXRecordDecl *MostDerivedClass;
155
156 ASTContext &Context;
157
158 /// MostDerivedClassLayout - the AST record layout of the most derived class.
159 const ASTRecordLayout &MostDerivedClassLayout;
160
Anders Carlssoneee53d92010-02-13 02:02:03 +0000161 /// BaseSubobjectMethodPairTy - Uniquely identifies a member function
162 /// in a base subobject.
163 typedef std::pair<BaseSubobject, const CXXMethodDecl *>
164 BaseSubobjectMethodPairTy;
165
166 typedef llvm::DenseMap<BaseSubobjectMethodPairTy,
Anders Carlsson136bd192010-02-12 16:55:34 +0000167 OverriderInfo> OverridersMapTy;
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000168
169 /// OverridersMap - The final overriders for all virtual member functions of
170 /// all the base subobjects of the most derived class.
171 OverridersMapTy OverridersMap;
172
Anders Carlssoneee53d92010-02-13 02:02:03 +0000173 typedef llvm::DenseMap<BaseSubobjectMethodPairTy, BaseOffset>
174 AdjustmentOffsetsMapTy;
175
176 /// ReturnAdjustments - Holds return adjustments for all the overriders that
177 /// need to perform return value adjustments.
178 AdjustmentOffsetsMapTy ReturnAdjustments;
179
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000180 typedef llvm::SmallVector<uint64_t, 1> OffsetVectorTy;
181
182 /// SubobjectOffsetsMapTy - This map is used for keeping track of all the
183 /// base subobject offsets that a single class declaration might refer to.
184 ///
185 /// For example, in:
186 ///
187 /// struct A { virtual void f(); };
188 /// struct B1 : A { };
189 /// struct B2 : A { };
190 /// struct C : B1, B2 { virtual void f(); };
191 ///
192 /// when we determine that C::f() overrides A::f(), we need to update the
193 /// overriders map for both A-in-B1 and A-in-B2 and the subobject offsets map
194 /// will have the subobject offsets for both A copies.
195 typedef llvm::DenseMap<const CXXRecordDecl *, OffsetVectorTy>
196 SubobjectOffsetsMapTy;
197
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000198 /// ComputeFinalOverriders - Compute the final overriders for a given base
199 /// subobject (and all its direct and indirect bases).
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000200 void ComputeFinalOverriders(BaseSubobject Base,
201 SubobjectOffsetsMapTy &Offsets);
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000202
203 /// AddOverriders - Add the final overriders for this base subobject to the
204 /// map of final overriders.
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000205 void AddOverriders(BaseSubobject Base, SubobjectOffsetsMapTy &Offsets);
206
207 /// PropagateOverrider - Propagate the NewMD overrider to all the functions
208 /// that OldMD overrides. For example, if we have:
209 ///
210 /// struct A { virtual void f(); };
211 /// struct B : A { virtual void f(); };
212 /// struct C : B { virtual void f(); };
213 ///
214 /// and we want to override B::f with C::f, we also need to override A::f with
215 /// C::f.
216 void PropagateOverrider(const CXXMethodDecl *OldMD,
217 const CXXMethodDecl *NewMD,
218 SubobjectOffsetsMapTy &Offsets);
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000219
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000220 static void MergeSubobjectOffsets(const SubobjectOffsetsMapTy &NewOffsets,
221 SubobjectOffsetsMapTy &Offsets);
222
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000223public:
224 explicit FinalOverriders(const CXXRecordDecl *MostDerivedClass);
225
226 /// getOverrider - Get the final overrider for the given method declaration in
227 /// the given base subobject.
Anders Carlsson136bd192010-02-12 16:55:34 +0000228 const OverriderInfo getOverrider(BaseSubobject Base,
229 const CXXMethodDecl *MD) const {
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000230 assert(OverridersMap.count(std::make_pair(Base, MD)) &&
231 "Did not find overrider!");
232
233 return OverridersMap.lookup(std::make_pair(Base, MD));
234 }
235
236 /// dump - dump the final overriders.
237 void dump() const {
238 dump(llvm::errs(), BaseSubobject(MostDerivedClass, 0));
239 }
240
241 /// dump - dump the final overriders for a base subobject, and all its direct
242 /// and indirect base subobjects.
243 void dump(llvm::raw_ostream &Out, BaseSubobject Base) const;
244};
Anders Carlssoneee53d92010-02-13 02:02:03 +0000245
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000246FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass)
247 : MostDerivedClass(MostDerivedClass),
248 Context(MostDerivedClass->getASTContext()),
249 MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)) {
250
251 // Compute the final overriders.
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000252 SubobjectOffsetsMapTy Offsets;
253 ComputeFinalOverriders(BaseSubobject(MostDerivedClass, 0), Offsets);
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000254
255 // And dump them (for now).
256 dump();
257}
258
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000259void FinalOverriders::AddOverriders(BaseSubobject Base,
260 SubobjectOffsetsMapTy &Offsets) {
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000261 const CXXRecordDecl *RD = Base.getBase();
262
263 for (CXXRecordDecl::method_iterator I = RD->method_begin(),
264 E = RD->method_end(); I != E; ++I) {
265 const CXXMethodDecl *MD = *I;
266
267 if (!MD->isVirtual())
268 continue;
269
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000270 // First, propagate the overrider.
271 PropagateOverrider(MD, MD, Offsets);
272
273 // Add the overrider as the final overrider of itself.
Anders Carlsson136bd192010-02-12 16:55:34 +0000274 OverriderInfo& Overrider = OverridersMap[std::make_pair(Base, MD)];
275 assert(!Overrider.Method && "Overrider should not exist yet!");
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000276
Anders Carlsson136bd192010-02-12 16:55:34 +0000277 Overrider.Method = MD;
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000278 }
279}
280
Anders Carlssoneee53d92010-02-13 02:02:03 +0000281static FinalOverriders::BaseOffset
282ComputeBaseOffset(ASTContext &Context,
283 const CXXRecordDecl *DerivedRD,
284 const CXXRecordDecl *BaseRD) {
285 CXXBasePaths Paths(/*FindAmbiguities=*/false,
286 /*RecordPaths=*/true, /*DetectVirtual=*/true);
287
288 if (!const_cast<CXXRecordDecl *>(DerivedRD)->
289 isDerivedFrom(const_cast<CXXRecordDecl *>(BaseRD), Paths)) {
290 assert(false && "Class must be derived from the passed in base class!");
291 return FinalOverriders::BaseOffset();
292 }
293
294 assert(!Paths.getDetectedVirtual() &&
295 "FIXME: Handle virtual bases!");
296
297 uint64_t NonVirtualOffset = 0;
298
299 const CXXBasePath &Path = Paths.front();
300
301 for (size_t Start = 0, End = Path.size(); Start != End; ++Start) {
302 const CXXBasePathElement &Element = Path[Start];
303
304 // Check the base class offset.
305 const ASTRecordLayout &Layout = Context.getASTRecordLayout(Element.Class);
306
307 const RecordType *BaseType = Element.Base->getType()->getAs<RecordType>();
308 const CXXRecordDecl *Base = cast<CXXRecordDecl>(BaseType->getDecl());
309
310 NonVirtualOffset += Layout.getBaseClassOffset(Base);
311 }
312
313 // FIXME: This should probably use CharUnits or something. Maybe we should
314 // even change the base offsets in ASTRecordLayout to be specified in
315 // CharUnits.
316 return FinalOverriders::BaseOffset(0, NonVirtualOffset / 8);
317}
318
319static FinalOverriders::BaseOffset
320ComputeReturnTypeBaseOffset(ASTContext &Context,
321 const CXXMethodDecl *DerivedMD,
322 const CXXMethodDecl *BaseMD) {
323 const FunctionType *BaseFT = BaseMD->getType()->getAs<FunctionType>();
324 const FunctionType *DerivedFT = DerivedMD->getType()->getAs<FunctionType>();
325
326 // Canonicalize the return types.
327 CanQualType CanDerivedReturnType =
328 Context.getCanonicalType(DerivedFT->getResultType());
329 CanQualType CanBaseReturnType =
330 Context.getCanonicalType(BaseFT->getResultType());
331
332 assert(CanDerivedReturnType->getTypeClass() ==
333 CanBaseReturnType->getTypeClass() &&
334 "Types must have same type class!");
335
336 if (CanDerivedReturnType == CanBaseReturnType) {
337 // No adjustment needed.
338 return FinalOverriders::BaseOffset();
339 }
340
341 if (isa<ReferenceType>(CanDerivedReturnType)) {
342 CanDerivedReturnType =
343 CanDerivedReturnType->getAs<ReferenceType>()->getPointeeType();
344 CanBaseReturnType =
345 CanBaseReturnType->getAs<ReferenceType>()->getPointeeType();
346 } else if (isa<PointerType>(CanDerivedReturnType)) {
347 CanDerivedReturnType =
348 CanDerivedReturnType->getAs<PointerType>()->getPointeeType();
349 CanBaseReturnType =
350 CanBaseReturnType->getAs<PointerType>()->getPointeeType();
351 } else {
352 assert(false && "Unexpected return type!");
353 }
354
355 // We need to compare unqualified types here; consider
356 // const T *Base::foo();
357 // T *Derived::foo();
358 if (CanDerivedReturnType.getUnqualifiedType() ==
359 CanBaseReturnType.getUnqualifiedType()) {
360 // No adjustment needed.
361 return FinalOverriders::BaseOffset();
362 }
363
364 const CXXRecordDecl *DerivedRD =
365 cast<CXXRecordDecl>(cast<RecordType>(CanDerivedReturnType)->getDecl());
366
367 const CXXRecordDecl *BaseRD =
368 cast<CXXRecordDecl>(cast<RecordType>(CanBaseReturnType)->getDecl());
369
370 return ComputeBaseOffset(Context, DerivedRD, BaseRD);
371}
372
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000373void FinalOverriders::PropagateOverrider(const CXXMethodDecl *OldMD,
374 const CXXMethodDecl *NewMD,
375 SubobjectOffsetsMapTy &Offsets) {
376 for (CXXMethodDecl::method_iterator I = OldMD->begin_overridden_methods(),
377 E = OldMD->end_overridden_methods(); I != E; ++I) {
378 const CXXMethodDecl *OverriddenMD = *I;
379 const CXXRecordDecl *OverriddenRD = OverriddenMD->getParent();
380
381 // We want to override OverriddenMD in all subobjects, for example:
382 //
383 /// struct A { virtual void f(); };
384 /// struct B1 : A { };
385 /// struct B2 : A { };
386 /// struct C : B1, B2 { virtual void f(); };
387 ///
388 /// When overriding A::f with C::f we need to do so in both A subobjects.
389 const OffsetVectorTy &OffsetVector = Offsets[OverriddenRD];
390
391 // Go through all the subobjects.
392 for (unsigned I = 0, E = OffsetVector.size(); I != E; ++I) {
393 uint64_t Offset = OffsetVector[I];
394
Anders Carlssoneee53d92010-02-13 02:02:03 +0000395 BaseSubobjectMethodPairTy SubobjectAndMethod =
396 std::make_pair(BaseSubobject(OverriddenRD, Offset), OverriddenMD);
397
398 OverriderInfo &Overrider = OverridersMap[SubobjectAndMethod];
399
Anders Carlsson136bd192010-02-12 16:55:34 +0000400 assert(Overrider.Method && "Did not find existing overrider!");
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000401
Anders Carlssoneee53d92010-02-13 02:02:03 +0000402 // Get the return adjustment base offset.
403 BaseOffset ReturnBaseOffset =
404 ComputeReturnTypeBaseOffset(Context, NewMD, OverriddenMD);
405 if (!ReturnBaseOffset.isEmpty()) {
406 // Store the return adjustment base offset.
407 ReturnAdjustments[SubobjectAndMethod] = ReturnBaseOffset;
Anders Carlsson8e661e12010-02-12 17:13:23 +0000408 }
409
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000410 // Set the new overrider.
Anders Carlsson136bd192010-02-12 16:55:34 +0000411 Overrider.Method = NewMD;
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000412
413 // And propagate it further.
414 PropagateOverrider(OverriddenMD, NewMD, Offsets);
415 }
416 }
417}
418
419void
420FinalOverriders::MergeSubobjectOffsets(const SubobjectOffsetsMapTy &NewOffsets,
421 SubobjectOffsetsMapTy &Offsets) {
422 // Iterate over the new offsets.
423 for (SubobjectOffsetsMapTy::const_iterator I = NewOffsets.begin(),
424 E = NewOffsets.end(); I != E; ++I) {
425 const CXXRecordDecl *NewRD = I->first;
426 const OffsetVectorTy& NewOffsetsVector = I->second;
427
428 OffsetVectorTy &OffsetsVector = Offsets[NewRD];
429 if (OffsetsVector.empty()) {
430 // There were no previous offsets in this vector, just insert all entries
431 // from the new offsets vector.
432 OffsetsVector.append(NewOffsetsVector.begin(), NewOffsetsVector.end());
433 continue;
434 }
435
436 assert(false && "FIXME: Handle merging the subobject offsets!");
437 }
438}
439
440void FinalOverriders::ComputeFinalOverriders(BaseSubobject Base,
441 SubobjectOffsetsMapTy &Offsets) {
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000442 const CXXRecordDecl *RD = Base.getBase();
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000443 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000444
Anders Carlsson9fbf6d92010-02-12 01:40:03 +0000445 SubobjectOffsetsMapTy NewOffsets;
446
447 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
448 E = RD->bases_end(); I != E; ++I) {
449 const CXXRecordDecl *BaseDecl =
450 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
451
452 assert(!I->isVirtual() && "FIXME: Handle virtual bases!");
453
454 uint64_t BaseOffset = Layout.getBaseClassOffset(BaseDecl) +
455 Base.getBaseOffset();
456
457 // Compute the final overriders for this base.
458 ComputeFinalOverriders(BaseSubobject(BaseDecl, BaseOffset), NewOffsets);
459 }
460
461 /// Now add the overriders for this particular subobject.
462 AddOverriders(Base, NewOffsets);
463
464 // And merge the newly discovered subobject offsets.
465 MergeSubobjectOffsets(NewOffsets, Offsets);
466
467 /// Finally, add the offset for our own subobject.
468 Offsets[RD].push_back(Base.getBaseOffset());
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000469}
470
471void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) const {
472
473 const CXXRecordDecl *RD = Base.getBase();
474 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
475
476 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
477 E = RD->bases_end(); I != E; ++I) {
478 assert(!I->isVirtual() && "FIXME: Handle virtual bases!");
479
480 const CXXRecordDecl *BaseDecl =
481 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
482
483 uint64_t BaseOffset = Layout.getBaseClassOffset(BaseDecl) +
484 Base.getBaseOffset();
485
486 dump(Out, BaseSubobject(BaseDecl, BaseOffset));
487 }
488
489 Out << "Final overriders for (" << RD->getQualifiedNameAsString() << ", ";
490 Out << Base.getBaseOffset() << ")\n";
491
492 // Now dump the overriders for this base subobject.
493 for (CXXRecordDecl::method_iterator I = RD->method_begin(),
494 E = RD->method_end(); I != E; ++I) {
495 const CXXMethodDecl *MD = *I;
496
497 if (!MD->isVirtual())
498 continue;
499
Anders Carlsson136bd192010-02-12 16:55:34 +0000500 OverriderInfo Overrider = getOverrider(Base, MD);
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000501
502 Out << " " << MD->getQualifiedNameAsString() << " - ";
Anders Carlsson8e661e12010-02-12 17:13:23 +0000503 Out << Overrider.Method->getQualifiedNameAsString();
Anders Carlssoneee53d92010-02-13 02:02:03 +0000504
Benjamin Kramer02c67372010-02-13 09:11:28 +0000505 AdjustmentOffsetsMapTy::const_iterator AI =
Anders Carlssoneee53d92010-02-13 02:02:03 +0000506 ReturnAdjustments.find(std::make_pair(Base, MD));
Benjamin Kramer02c67372010-02-13 09:11:28 +0000507 if (AI != ReturnAdjustments.end()) {
508 const BaseOffset &Offset = AI->second;
Anders Carlssoneee53d92010-02-13 02:02:03 +0000509
510 assert(!Offset.VirtualBase && "FIXME: Handle vbases!");
511
512 Out << " [ret-adj: " << Offset.NonVirtualOffset << " nv]";
513 }
Anders Carlsson8e661e12010-02-12 17:13:23 +0000514 Out << "\n";
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000515 }
516}
517
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000518/// VtableComponent - Represents a single component in a vtable.
519class VtableComponent {
520public:
521 enum Kind {
522 CK_VCallOffset,
523 CK_VBaseOffset,
524 CK_OffsetToTop,
525 CK_RTTI,
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000526 CK_FunctionPointer,
527
528 /// CK_CompleteDtorPointer - A pointer to the complete destructor.
529 CK_CompleteDtorPointer,
530
531 /// CK_DeletingDtorPointer - A pointer to the deleting destructor.
532 CK_DeletingDtorPointer
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000533 };
534
535 /// dump - Dump the contents of this component to the given stream.
536 void dump(llvm::raw_ostream &Out);
537
538 static VtableComponent MakeOffsetToTop(int64_t Offset) {
539 return VtableComponent(CK_OffsetToTop, Offset);
540 }
541
542 static VtableComponent MakeRTTI(const CXXRecordDecl *RD) {
543 return VtableComponent(CK_RTTI, reinterpret_cast<uintptr_t>(RD));
544 }
545
546 static VtableComponent MakeFunction(const CXXMethodDecl *MD) {
547 assert(!isa<CXXDestructorDecl>(MD) &&
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000548 "Don't use MakeFunction with destructors!");
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000549
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000550 return VtableComponent(CK_FunctionPointer,
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000551 reinterpret_cast<uintptr_t>(MD));
552 }
553
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000554 static VtableComponent MakeCompleteDtor(const CXXDestructorDecl *DD) {
555 return VtableComponent(CK_CompleteDtorPointer,
556 reinterpret_cast<uintptr_t>(DD));
557 }
558
559 static VtableComponent MakeDeletingDtor(const CXXDestructorDecl *DD) {
560 return VtableComponent(CK_DeletingDtorPointer,
561 reinterpret_cast<uintptr_t>(DD));
562 }
563
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000564 /// getKind - Get the kind of this vtable component.
565 Kind getKind() const {
566 return (Kind)(Value & 0x7);
567 }
568
569 int64_t getOffsetToTop() const {
570 assert(getKind() == CK_OffsetToTop && "Invalid component kind!");
571
572 return getOffset();
573 }
574
575 const CXXRecordDecl *getRTTIDecl() const {
576 assert(getKind() == CK_RTTI && "Invalid component kind!");
577
578 return reinterpret_cast<CXXRecordDecl *>(getPointer());
579 }
580
581 const CXXMethodDecl *getFunctionDecl() const {
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000582 assert(getKind() == CK_FunctionPointer);
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000583
584 return reinterpret_cast<CXXMethodDecl *>(getPointer());
585 }
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000586
587 const CXXDestructorDecl *getDestructorDecl() const {
588 assert((getKind() == CK_CompleteDtorPointer ||
589 getKind() == CK_DeletingDtorPointer) && "Invalid component kind!");
590
591 return reinterpret_cast<CXXDestructorDecl *>(getPointer());
592 }
593
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000594private:
595 VtableComponent(Kind ComponentKind, int64_t Offset) {
596 assert((ComponentKind == CK_VCallOffset ||
597 ComponentKind == CK_VBaseOffset ||
598 ComponentKind == CK_OffsetToTop) && "Invalid component kind!");
599 assert(Offset <= ((1LL << 56) - 1) && "Offset is too big!");
600
601 Value = ((Offset << 3) | ComponentKind);
602 }
603
604 VtableComponent(Kind ComponentKind, uintptr_t Ptr) {
605 assert((ComponentKind == CK_RTTI ||
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000606 ComponentKind == CK_FunctionPointer ||
607 ComponentKind == CK_CompleteDtorPointer ||
608 ComponentKind == CK_DeletingDtorPointer) &&
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000609 "Invalid component kind!");
610
611 assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!");
612
613 Value = Ptr | ComponentKind;
614 }
615
616 int64_t getOffset() const {
617 assert((getKind() == CK_VCallOffset || getKind() == CK_VBaseOffset ||
618 getKind() == CK_OffsetToTop) && "Invalid component kind!");
619
620 return Value >> 3;
621 }
622
623 uintptr_t getPointer() const {
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000624 assert((getKind() == CK_RTTI ||
625 getKind() == CK_FunctionPointer ||
626 getKind() == CK_CompleteDtorPointer ||
627 getKind() == CK_DeletingDtorPointer) &&
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000628 "Invalid component kind!");
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000629
630 return static_cast<uintptr_t>(Value & ~7ULL);
631 }
632
633 /// The kind is stored in the lower 3 bits of the value. For offsets, we
634 /// make use of the facts that classes can't be larger than 2^55 bytes,
635 /// so we store the offset in the lower part of the 61 bytes that remain.
636 /// (The reason that we're not simply using a PointerIntPair here is that we
637 /// need the offsets to be 64-bit, even when on a 32-bit machine).
638 int64_t Value;
639};
640
641/// VtableBuilder - Class for building vtable layout information.
Benjamin Kramer337e3a52009-11-28 19:45:26 +0000642class VtableBuilder {
Anders Carlsson65b49782010-02-12 05:25:12 +0000643public:
644 /// PrimaryBasesSetTy - A set of direct and indirect primary bases.
645 typedef llvm::SmallPtrSet<const CXXRecordDecl *, 8> PrimaryBasesSetTy;
646
647private:
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000648 /// MostDerivedClass - The most derived class for which we're building this
649 /// vtable.
650 const CXXRecordDecl *MostDerivedClass;
651
652 /// Context - The ASTContext which we will use for layout information.
Anders Carlsson65b49782010-02-12 05:25:12 +0000653 ASTContext &Context;
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000654
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000655 /// FinalOverriders - The final overriders of the most derived class.
656 FinalOverriders Overriders;
657
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000658 /// Components - The components of the vtable being built.
659 llvm::SmallVector<VtableComponent, 64> Components;
660
Anders Carlsson932c2f22010-02-11 17:18:51 +0000661 /// AddressPoints - Address points for the vtable being built.
662 CGVtableInfo::AddressPointsMapTy AddressPoints;
663
Anders Carlsson5272c252010-02-12 17:37:14 +0000664 /// ReturnAdjustment - A return adjustment thunk.
665 struct ReturnAdjustment {
666 /// NonVirtual - The non-virtual adjustment from the derived object to its
667 /// nearest virtual base.
668 int64_t NonVirtual;
669
670 /// VBaseOffsetIndex - The index relative to the address point of the
671 /// virtual base class offset.
672 int64_t VBaseOffsetIndex;
673 };
674
Anders Carlsson65b49782010-02-12 05:25:12 +0000675 void layoutVirtualMemberFunctions(BaseSubobject Base,
676 PrimaryBasesSetTy &PrimaryBases);
677
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000678 /// layoutSimpleVtable - A test function that will layout very simple vtables
679 /// without any bases. Just used for testing for now.
Anders Carlsson65b49782010-02-12 05:25:12 +0000680 void layoutSimpleVtable(BaseSubobject Base);
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000681
682public:
683 VtableBuilder(const CXXRecordDecl *MostDerivedClass)
684 : MostDerivedClass(MostDerivedClass),
Anders Carlssone8ac42a2010-02-11 21:24:32 +0000685 Context(MostDerivedClass->getASTContext()), Overriders(MostDerivedClass) {
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000686
Anders Carlsson65b49782010-02-12 05:25:12 +0000687 layoutSimpleVtable(BaseSubobject(MostDerivedClass, 0));
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000688 }
689
690 /// dumpLayout - Dump the vtable layout.
691 void dumpLayout(llvm::raw_ostream&);
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000692};
693
Anders Carlsson65b49782010-02-12 05:25:12 +0000694/// OverridesMethodInPrimaryBase - Checks whether whether this virtual member
695/// function overrides a member function in a direct or indirect primary base.
696/// Returns the overridden member function, or null if none was found.
697static const CXXMethodDecl *
698OverridesMethodInPrimaryBase(const CXXMethodDecl *MD,
699 VtableBuilder::PrimaryBasesSetTy &PrimaryBases) {
700 for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
701 E = MD->end_overridden_methods(); I != E; ++I) {
702 const CXXMethodDecl *OverriddenMD = *I;
703 const CXXRecordDecl *OverriddenRD = OverriddenMD->getParent();
704 assert(OverriddenMD->isCanonicalDecl() &&
705 "Should have the canonical decl of the overridden RD!");
706
707 if (PrimaryBases.count(OverriddenRD))
708 return OverriddenMD;
709 }
710
711 return 0;
712}
713
714void
715VtableBuilder::layoutVirtualMemberFunctions(BaseSubobject Base,
716 PrimaryBasesSetTy &PrimaryBases) {
717 const CXXRecordDecl *RD = Base.getBase();
718
719 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
720
721 if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
722 if (Layout.getPrimaryBaseWasVirtual())
723 assert(false && "FIXME: Handle vbases here.");
724 else
725 assert(Layout.getBaseClassOffset(PrimaryBase) == 0 &&
726 "Primary base should have a zero offset!");
727
728 layoutVirtualMemberFunctions(BaseSubobject(PrimaryBase, 0), PrimaryBases);
729
730 if (!PrimaryBases.insert(PrimaryBase))
731 assert(false && "Found a duplicate primary base!");
732 }
Anders Carlsson932c2f22010-02-11 17:18:51 +0000733
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000734 // Now go through all virtual member functions and add them.
735 for (CXXRecordDecl::method_iterator I = RD->method_begin(),
736 E = RD->method_end(); I != E; ++I) {
737 const CXXMethodDecl *MD = *I;
Anders Carlsson65b49782010-02-12 05:25:12 +0000738
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000739 if (!MD->isVirtual())
740 continue;
Anders Carlsson65b49782010-02-12 05:25:12 +0000741
742 // Get the final overrider.
Anders Carlsson136bd192010-02-12 16:55:34 +0000743 FinalOverriders::OverriderInfo Overrider =
744 Overriders.getOverrider(Base, MD);
Anders Carlsson65b49782010-02-12 05:25:12 +0000745
746 // Check if this virtual member function overrides a method in a primary
747 // base. If this is the case, and the return type doesn't require adjustment
748 // then we can just use the member function from the primary base.
Anders Carlsson5272c252010-02-12 17:37:14 +0000749 if (const CXXMethodDecl *OverriddenMD =
750 OverridesMethodInPrimaryBase(MD, PrimaryBases)) {
Anders Carlssoneee53d92010-02-13 02:02:03 +0000751 assert(!ReturnTypeConversionRequiresAdjustment(MD, OverriddenMD)
Anders Carlsson5272c252010-02-12 17:37:14 +0000752 && "FIXME: Handle covariant thunks!");
Anders Carlssoneee53d92010-02-13 02:02:03 +0000753
Anders Carlsson65b49782010-02-12 05:25:12 +0000754 continue;
755 }
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000756
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000757 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
758 // Add both the complete destructor and the deleting destructor.
759 Components.push_back(VtableComponent::MakeCompleteDtor(DD));
760 Components.push_back(VtableComponent::MakeDeletingDtor(DD));
761 } else {
762 // Add the function.
763 Components.push_back(VtableComponent::MakeFunction(MD));
764 }
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000765 }
766}
767
Anders Carlsson65b49782010-02-12 05:25:12 +0000768void VtableBuilder::layoutSimpleVtable(BaseSubobject Base) {
769 const CXXRecordDecl *RD = Base.getBase();
770
771 // First, add the offset to top.
772 Components.push_back(VtableComponent::MakeOffsetToTop(0));
773
774 // Next, add the RTTI.
775 Components.push_back(VtableComponent::MakeRTTI(RD));
776
Anders Carlssone8a97562010-02-12 07:43:48 +0000777 uint64_t AddressPoint = Components.size();
Anders Carlsson65b49782010-02-12 05:25:12 +0000778
779 // Now go through all virtual member functions and add them.
780 PrimaryBasesSetTy PrimaryBases;
781 layoutVirtualMemberFunctions(Base, PrimaryBases);
782
Anders Carlssone8a97562010-02-12 07:43:48 +0000783 // Record the address point.
784 AddressPoints.insert(std::make_pair(Base, AddressPoint));
785
786 // Record the address points for all primary bases.
787 for (PrimaryBasesSetTy::const_iterator I = PrimaryBases.begin(),
788 E = PrimaryBases.end(); I != E; ++I) {
789 const CXXRecordDecl *BaseDecl = *I;
790
791 // We know that all the primary bases have the same offset as the base
792 // subobject.
793 BaseSubobject PrimaryBase(BaseDecl, Base.getBaseOffset());
794 AddressPoints.insert(std::make_pair(PrimaryBase, AddressPoint));
795 }
796
Anders Carlsson65b49782010-02-12 05:25:12 +0000797 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
798 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
799
800 // Traverse bases.
801 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
802 E = RD->bases_end(); I != E; ++I) {
803 const CXXRecordDecl *BaseDecl =
804 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
805
806 // Ignore the primary base.
807 if (BaseDecl == PrimaryBase)
808 continue;
809
810 assert(!I->isVirtual() && "FIXME: Handle virtual bases");
811
812 assert(false && "FIXME: Handle secondary virtual tables!");
813 }
814}
815
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000816/// dumpLayout - Dump the vtable layout.
817void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
818
819 Out << "Vtable for '" << MostDerivedClass->getQualifiedNameAsString();
820 Out << "' (" << Components.size() << " entries).\n";
821
Anders Carlsson932c2f22010-02-11 17:18:51 +0000822 // Iterate through the address points and insert them into a new map where
823 // they are keyed by the index and not the base object.
824 // Since an address point can be shared by multiple subobjects, we use an
825 // STL multimap.
826 std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
827 for (CGVtableInfo::AddressPointsMapTy::const_iterator I =
828 AddressPoints.begin(), E = AddressPoints.end(); I != E; ++I) {
829 const BaseSubobject& Base = I->first;
830 uint64_t Index = I->second;
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000831
Anders Carlsson932c2f22010-02-11 17:18:51 +0000832 AddressPointsByIndex.insert(std::make_pair(Index, Base));
833 }
834
835 for (unsigned I = 0, E = Components.size(); I != E; ++I) {
Anders Carlssone8a97562010-02-12 07:43:48 +0000836 uint64_t Index = I;
837
Anders Carlsson932c2f22010-02-11 17:18:51 +0000838 if (AddressPointsByIndex.count(I)) {
Anders Carlssone8a97562010-02-12 07:43:48 +0000839 std::string Str;
840
Anders Carlsson932c2f22010-02-11 17:18:51 +0000841
Anders Carlssone8a97562010-02-12 07:43:48 +0000842 if (AddressPointsByIndex.count(Index) == 1) {
843 const BaseSubobject &Base = AddressPointsByIndex.find(Index)->second;
844
845 // FIXME: Instead of dividing by 8, we should be using CharUnits.
846 Out << " -- (" << Base.getBase()->getQualifiedNameAsString();
847 Out << ", " << Base.getBaseOffset() / 8 << ") vtable address --\n";
848 } else {
849 uint64_t BaseOffset =
850 AddressPointsByIndex.lower_bound(Index)->second.getBaseOffset();
851
852 // We store the class names in a set to get a stable order.
853 std::set<std::string> ClassNames;
854 for (std::multimap<uint64_t, BaseSubobject>::const_iterator I =
855 AddressPointsByIndex.lower_bound(Index), E =
856 AddressPointsByIndex.upper_bound(Index); I != E; ++I) {
857 assert(I->second.getBaseOffset() == BaseOffset &&
858 "Invalid base offset!");
859 const CXXRecordDecl *RD = I->second.getBase();
860 ClassNames.insert(RD->getQualifiedNameAsString());
861 }
862
863 for (std::set<std::string>::const_iterator I = ClassNames.begin(),
864 E = ClassNames.end(); I != E; ++I) {
865 // FIXME: Instead of dividing by 8, we should be using CharUnits.
866 Out << " -- (" << *I;
867 Out << ", " << BaseOffset / 8 << ") vtable address --\n";
868 }
869 }
Anders Carlsson932c2f22010-02-11 17:18:51 +0000870 }
871
872 Out << llvm::format("%4d | ", I);
873
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000874 const VtableComponent &Component = Components[I];
875
876 // Dump the component.
877 switch (Component.getKind()) {
878 // FIXME: Remove this default case.
879 default:
880 assert(false && "Unhandled component kind!");
881 break;
882
883 case VtableComponent::CK_OffsetToTop:
884 Out << "offset_to_top (" << Component.getOffsetToTop() << ")";
885 break;
886
887 case VtableComponent::CK_RTTI:
888 Out << Component.getRTTIDecl()->getQualifiedNameAsString() << " RTTI";
889 break;
890
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000891 case VtableComponent::CK_FunctionPointer: {
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000892 const CXXMethodDecl *MD = Component.getFunctionDecl();
893
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000894 std::string Str =
895 PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
896 MD);
897 Out << Str;
Anders Carlsson09da3372010-02-12 02:38:13 +0000898 if (MD->isPure())
899 Out << " [pure]";
900
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000901 break;
902 }
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000903
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000904 case VtableComponent::CK_CompleteDtorPointer: {
905 const CXXDestructorDecl *DD = Component.getDestructorDecl();
906
907 Out << DD->getQualifiedNameAsString() << "() [complete]";
Anders Carlsson09da3372010-02-12 02:38:13 +0000908 if (DD->isPure())
909 Out << " [pure]";
910
Anders Carlsson5bd8d192010-02-11 18:20:28 +0000911 break;
912 }
913
914 case VtableComponent::CK_DeletingDtorPointer: {
915 const CXXDestructorDecl *DD = Component.getDestructorDecl();
916
917 Out << DD->getQualifiedNameAsString() << "() [deleting]";
Anders Carlsson09da3372010-02-12 02:38:13 +0000918 if (DD->isPure())
919 Out << " [pure]";
920
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000921 break;
922 }
923
924 }
Anders Carlsson932c2f22010-02-11 17:18:51 +0000925
Anders Carlsson5d40c6f2010-02-11 08:02:13 +0000926 Out << '\n';
927 }
928
929}
930
931}
932
933namespace {
934class OldVtableBuilder {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000935public:
936 /// Index_t - Vtable index type.
937 typedef uint64_t Index_t;
Eli Friedman31bc3ad2009-12-07 23:56:34 +0000938 typedef std::vector<std::pair<GlobalDecl,
939 std::pair<GlobalDecl, ThunkAdjustment> > >
940 SavedAdjustmentsVectorTy;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000941private:
Anders Carlsson472404f2009-12-04 16:19:30 +0000942
Anders Carlssonfe5f7d92009-12-06 01:09:21 +0000943 // VtableComponents - The components of the vtable being built.
944 typedef llvm::SmallVector<llvm::Constant *, 64> VtableComponentsVectorTy;
945 VtableComponentsVectorTy VtableComponents;
946
Eli Friedman6c08ce72009-12-05 01:05:03 +0000947 const bool BuildVtable;
948
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000949 llvm::Type *Ptr8Ty;
Anders Carlssonbad80eb2009-12-04 18:36:22 +0000950
951 /// MostDerivedClass - The most derived class that this vtable is being
952 /// built for.
953 const CXXRecordDecl *MostDerivedClass;
954
Mike Stump83066c82009-11-13 01:54:23 +0000955 /// LayoutClass - The most derived class used for virtual base layout
956 /// information.
957 const CXXRecordDecl *LayoutClass;
Mike Stump653d0b92009-11-13 02:13:54 +0000958 /// LayoutOffset - The offset for Class in LayoutClass.
959 uint64_t LayoutOffset;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000960 /// BLayout - Layout for the most derived class that this vtable is being
961 /// built for.
962 const ASTRecordLayout &BLayout;
963 llvm::SmallSet<const CXXRecordDecl *, 32> IndirectPrimary;
964 llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase;
965 llvm::Constant *rtti;
966 llvm::LLVMContext &VMContext;
967 CodeGenModule &CGM; // Per-module state.
Anders Carlssonf2f31f42009-12-04 03:46:21 +0000968
Mike Stump90181eb2010-01-26 00:05:04 +0000969 llvm::DenseMap<const CXXMethodDecl *, Index_t> VCall;
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000970 llvm::DenseMap<GlobalDecl, Index_t> VCallOffset;
Mike Stump77537b12010-01-26 03:42:22 +0000971 llvm::DenseMap<GlobalDecl, Index_t> VCallOffsetForVCall;
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000972 // This is the offset to the nearest virtual base
Mike Stump90181eb2010-01-26 00:05:04 +0000973 llvm::DenseMap<const CXXMethodDecl *, Index_t> NonVirtualOffset;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000974 llvm::DenseMap<const CXXRecordDecl *, Index_t> VBIndex;
Mike Stumpbb9ff052009-10-27 23:46:47 +0000975
Anders Carlsson323bb042009-11-26 19:54:33 +0000976 /// PureVirtualFunction - Points to __cxa_pure_virtual.
977 llvm::Constant *PureVirtualFn;
978
Anders Carlssona84b6e82009-12-04 02:01:07 +0000979 /// VtableMethods - A data structure for keeping track of methods in a vtable.
980 /// Can add methods, override methods and iterate in vtable order.
981 class VtableMethods {
982 // MethodToIndexMap - Maps from a global decl to the index it has in the
983 // Methods vector.
984 llvm::DenseMap<GlobalDecl, uint64_t> MethodToIndexMap;
985
986 /// Methods - The methods, in vtable order.
987 typedef llvm::SmallVector<GlobalDecl, 16> MethodsVectorTy;
988 MethodsVectorTy Methods;
Eli Friedman8174f2c2009-12-06 22:01:30 +0000989 MethodsVectorTy OrigMethods;
Anders Carlssona84b6e82009-12-04 02:01:07 +0000990
991 public:
992 /// AddMethod - Add a method to the vtable methods.
993 void AddMethod(GlobalDecl GD) {
994 assert(!MethodToIndexMap.count(GD) &&
995 "Method has already been added!");
996
997 MethodToIndexMap[GD] = Methods.size();
998 Methods.push_back(GD);
Eli Friedman8174f2c2009-12-06 22:01:30 +0000999 OrigMethods.push_back(GD);
Anders Carlssona84b6e82009-12-04 02:01:07 +00001000 }
1001
1002 /// OverrideMethod - Replace a method with another.
1003 void OverrideMethod(GlobalDecl OverriddenGD, GlobalDecl GD) {
1004 llvm::DenseMap<GlobalDecl, uint64_t>::iterator i
1005 = MethodToIndexMap.find(OverriddenGD);
1006 assert(i != MethodToIndexMap.end() && "Did not find entry!");
1007
1008 // Get the index of the old decl.
1009 uint64_t Index = i->second;
1010
1011 // Replace the old decl with the new decl.
1012 Methods[Index] = GD;
1013
Anders Carlssona84b6e82009-12-04 02:01:07 +00001014 // And add the new.
1015 MethodToIndexMap[GD] = Index;
1016 }
1017
Anders Carlsson7bb70762009-12-04 15:49:02 +00001018 /// getIndex - Gives the index of a passed in GlobalDecl. Returns false if
1019 /// the index couldn't be found.
Benjamin Kramer62ab6162009-12-04 22:45:27 +00001020 bool getIndex(GlobalDecl GD, uint64_t &Index) const {
Anders Carlsson7bb70762009-12-04 15:49:02 +00001021 llvm::DenseMap<GlobalDecl, uint64_t>::const_iterator i
1022 = MethodToIndexMap.find(GD);
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001023
Anders Carlsson7bb70762009-12-04 15:49:02 +00001024 if (i == MethodToIndexMap.end())
1025 return false;
Anders Carlssone6096362009-12-04 03:41:37 +00001026
Anders Carlsson7bb70762009-12-04 15:49:02 +00001027 Index = i->second;
1028 return true;
Anders Carlssone6096362009-12-04 03:41:37 +00001029 }
1030
Eli Friedman8174f2c2009-12-06 22:01:30 +00001031 GlobalDecl getOrigMethod(uint64_t Index) const {
1032 return OrigMethods[Index];
1033 }
1034
Anders Carlssona84b6e82009-12-04 02:01:07 +00001035 MethodsVectorTy::size_type size() const {
1036 return Methods.size();
1037 }
1038
1039 void clear() {
1040 MethodToIndexMap.clear();
1041 Methods.clear();
Eli Friedman8174f2c2009-12-06 22:01:30 +00001042 OrigMethods.clear();
Anders Carlssona84b6e82009-12-04 02:01:07 +00001043 }
1044
Anders Carlssone6096362009-12-04 03:41:37 +00001045 GlobalDecl operator[](uint64_t Index) const {
Anders Carlssona84b6e82009-12-04 02:01:07 +00001046 return Methods[Index];
1047 }
1048 };
1049
1050 /// Methods - The vtable methods we're currently building.
1051 VtableMethods Methods;
1052
Anders Carlsson4c837d22009-12-04 02:26:15 +00001053 /// ThisAdjustments - For a given index in the vtable, contains the 'this'
1054 /// pointer adjustment needed for a method.
1055 typedef llvm::DenseMap<uint64_t, ThunkAdjustment> ThisAdjustmentsMapTy;
1056 ThisAdjustmentsMapTy ThisAdjustments;
Anders Carlssond420a312009-11-26 19:32:45 +00001057
Eli Friedman31bc3ad2009-12-07 23:56:34 +00001058 SavedAdjustmentsVectorTy SavedAdjustments;
Eli Friedman8174f2c2009-12-06 22:01:30 +00001059
Anders Carlssonc521f952009-12-04 02:22:02 +00001060 /// BaseReturnTypes - Contains the base return types of methods who have been
1061 /// overridden with methods whose return types require adjustment. Used for
1062 /// generating covariant thunk information.
1063 typedef llvm::DenseMap<uint64_t, CanQualType> BaseReturnTypesMapTy;
1064 BaseReturnTypesMapTy BaseReturnTypes;
Anders Carlssond420a312009-11-26 19:32:45 +00001065
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001066 std::vector<Index_t> VCalls;
Mike Stump2cefe382009-11-12 20:47:57 +00001067
1068 typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
Mike Stumpcd2b8212009-11-19 20:52:19 +00001069 // subAddressPoints - Used to hold the AddressPoints (offsets) into the built
1070 // vtable for use in computing the initializers for the VTT.
1071 llvm::DenseMap<CtorVtable_t, int64_t> &subAddressPoints;
Mike Stump2cefe382009-11-12 20:47:57 +00001072
Anders Carlsson5f9a8812010-01-14 02:29:07 +00001073 /// AddressPoints - Address points for this vtable.
1074 CGVtableInfo::AddressPointsMapTy& AddressPoints;
1075
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001076 typedef CXXRecordDecl::method_iterator method_iter;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001077 const uint32_t LLVMPointerWidth;
1078 Index_t extra;
Mike Stump37dbe962009-10-15 02:04:03 +00001079 typedef std::vector<std::pair<const CXXRecordDecl *, int64_t> > Path_t;
Mike Stumpcd2b8212009-11-19 20:52:19 +00001080 static llvm::DenseMap<CtorVtable_t, int64_t>&
1081 AllocAddressPoint(CodeGenModule &cgm, const CXXRecordDecl *l,
1082 const CXXRecordDecl *c) {
Anders Carlsson93a18842010-01-02 18:02:32 +00001083 CGVtableInfo::AddrMap_t *&oref = cgm.getVtableInfo().AddressPoints[l];
Mike Stumpcd2b8212009-11-19 20:52:19 +00001084 if (oref == 0)
Anders Carlsson93a18842010-01-02 18:02:32 +00001085 oref = new CGVtableInfo::AddrMap_t;
Mike Stumpcd2b8212009-11-19 20:52:19 +00001086
1087 llvm::DenseMap<CtorVtable_t, int64_t> *&ref = (*oref)[c];
1088 if (ref == 0)
1089 ref = new llvm::DenseMap<CtorVtable_t, int64_t>;
1090 return *ref;
1091 }
Anders Carlsson323bb042009-11-26 19:54:33 +00001092
Mike Stump90181eb2010-01-26 00:05:04 +00001093 bool DclIsSame(const FunctionDecl *New, const FunctionDecl *Old) {
1094 FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
1095 FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
1096
1097 // C++ [temp.fct]p2:
1098 // A function template can be overloaded with other function templates
1099 // and with normal (non-template) functions.
1100 if ((OldTemplate == 0) != (NewTemplate == 0))
1101 return false;
1102
1103 // Is the function New an overload of the function Old?
1104 QualType OldQType = CGM.getContext().getCanonicalType(Old->getType());
1105 QualType NewQType = CGM.getContext().getCanonicalType(New->getType());
1106
1107 // Compare the signatures (C++ 1.3.10) of the two functions to
1108 // determine whether they are overloads. If we find any mismatch
1109 // in the signature, they are overloads.
1110
1111 // If either of these functions is a K&R-style function (no
1112 // prototype), then we consider them to have matching signatures.
1113 if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) ||
1114 isa<FunctionNoProtoType>(NewQType.getTypePtr()))
1115 return true;
1116
1117 FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
1118 FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
1119
1120 // The signature of a function includes the types of its
1121 // parameters (C++ 1.3.10), which includes the presence or absence
1122 // of the ellipsis; see C++ DR 357).
1123 if (OldQType != NewQType &&
1124 (OldType->getNumArgs() != NewType->getNumArgs() ||
1125 OldType->isVariadic() != NewType->isVariadic() ||
1126 !std::equal(OldType->arg_type_begin(), OldType->arg_type_end(),
1127 NewType->arg_type_begin())))
1128 return false;
1129
1130#if 0
1131 // C++ [temp.over.link]p4:
1132 // The signature of a function template consists of its function
1133 // signature, its return type and its template parameter list. The names
1134 // of the template parameters are significant only for establishing the
1135 // relationship between the template parameters and the rest of the
1136 // signature.
1137 //
1138 // We check the return type and template parameter lists for function
1139 // templates first; the remaining checks follow.
1140 if (NewTemplate &&
1141 (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
1142 OldTemplate->getTemplateParameters(),
1143 TPL_TemplateMatch) ||
1144 OldType->getResultType() != NewType->getResultType()))
1145 return false;
1146#endif
1147
1148 // If the function is a class member, its signature includes the
1149 // cv-qualifiers (if any) on the function itself.
1150 //
1151 // As part of this, also check whether one of the member functions
1152 // is static, in which case they are not overloads (C++
1153 // 13.1p2). While not part of the definition of the signature,
1154 // this check is important to determine whether these functions
1155 // can be overloaded.
1156 const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
1157 const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
1158 if (OldMethod && NewMethod &&
1159 !OldMethod->isStatic() && !NewMethod->isStatic() &&
1160 OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers())
1161 return false;
1162
1163 // The signatures match; this is not an overload.
1164 return true;
1165 }
1166
1167 typedef llvm::DenseMap<const CXXMethodDecl *, const CXXMethodDecl*>
1168 ForwardUnique_t;
1169 ForwardUnique_t ForwardUnique;
1170 llvm::DenseMap<const CXXMethodDecl*, const CXXMethodDecl*> UniqueOverrider;
1171
1172 void BuildUniqueOverrider(const CXXMethodDecl *U, const CXXMethodDecl *MD) {
1173 const CXXMethodDecl *PrevU = UniqueOverrider[MD];
1174 assert(U && "no unique overrider");
1175 if (PrevU == U)
1176 return;
1177 if (PrevU != U && PrevU != 0) {
1178 // If already set, note the two sets as the same
1179 if (0)
1180 printf("%s::%s same as %s::%s\n",
1181 PrevU->getParent()->getNameAsCString(),
1182 PrevU->getNameAsCString(),
1183 U->getParent()->getNameAsCString(),
1184 U->getNameAsCString());
1185 ForwardUnique[PrevU] = U;
1186 return;
1187 }
1188
1189 // Not set, set it now
1190 if (0)
1191 printf("marking %s::%s %p override as %s::%s\n",
1192 MD->getParent()->getNameAsCString(),
1193 MD->getNameAsCString(),
1194 (void*)MD,
1195 U->getParent()->getNameAsCString(),
1196 U->getNameAsCString());
1197 UniqueOverrider[MD] = U;
1198
1199 for (CXXMethodDecl::method_iterator mi = MD->begin_overridden_methods(),
1200 me = MD->end_overridden_methods(); mi != me; ++mi) {
1201 BuildUniqueOverrider(U, *mi);
1202 }
1203 }
1204
1205 void BuildUniqueOverriders(const CXXRecordDecl *RD) {
1206 if (0) printf("walking %s\n", RD->getNameAsCString());
1207 for (CXXRecordDecl::method_iterator i = RD->method_begin(),
1208 e = RD->method_end(); i != e; ++i) {
1209 const CXXMethodDecl *MD = *i;
1210 if (!MD->isVirtual())
1211 continue;
1212
1213 if (UniqueOverrider[MD] == 0) {
1214 // Only set this, if it hasn't been set yet.
1215 BuildUniqueOverrider(MD, MD);
1216 if (0)
1217 printf("top set is %s::%s %p\n",
1218 MD->getParent()->getNameAsCString(),
1219 MD->getNameAsCString(),
1220 (void*)MD);
1221 ForwardUnique[MD] = MD;
1222 }
1223 }
1224 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
1225 e = RD->bases_end(); i != e; ++i) {
1226 const CXXRecordDecl *Base =
1227 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
1228 BuildUniqueOverriders(Base);
1229 }
1230 }
1231
1232 static int DclCmp(const void *p1, const void *p2) {
John McCallef3057c2010-02-13 01:04:05 +00001233 const CXXMethodDecl *MD1 = *(const CXXMethodDecl *const *)p1;
1234 const CXXMethodDecl *MD2 = *(const CXXMethodDecl *const *)p2;
1235
1236 return (DeclarationName::compare(MD1->getDeclName(), MD2->getDeclName()));
Mike Stump90181eb2010-01-26 00:05:04 +00001237 }
1238
1239 void MergeForwarding() {
1240 typedef llvm::SmallVector<const CXXMethodDecl *, 100> A_t;
1241 A_t A;
1242 for (ForwardUnique_t::iterator I = ForwardUnique.begin(),
1243 E = ForwardUnique.end(); I != E; ++I) {
1244 if (I->first == I->second)
1245 // Only add the roots of all trees
1246 A.push_back(I->first);
1247 }
1248 llvm::array_pod_sort(A.begin(), A.end(), DclCmp);
1249 for (A_t::iterator I = A.begin(),
1250 E = A.end(); I != E; ++I) {
1251 A_t::iterator J = I;
John McCallef3057c2010-02-13 01:04:05 +00001252 while (++J != E && DclCmp(I, J) == 0)
Mike Stump90181eb2010-01-26 00:05:04 +00001253 if (DclIsSame(*I, *J)) {
Eli Friedman18c28f62010-02-13 00:03:21 +00001254 if (0) printf("connecting %s\n", (*I)->getNameAsCString());
Mike Stump90181eb2010-01-26 00:05:04 +00001255 ForwardUnique[*J] = *I;
1256 }
1257 }
1258 }
1259
1260 const CXXMethodDecl *getUnique(const CXXMethodDecl *MD) {
1261 const CXXMethodDecl *U = UniqueOverrider[MD];
1262 assert(U && "unique overrider not found");
1263 while (ForwardUnique.count(U)) {
1264 const CXXMethodDecl *NU = ForwardUnique[U];
1265 if (NU == U) break;
1266 U = NU;
1267 }
1268 return U;
1269 }
Anders Carlsson72281172010-01-26 17:36:47 +00001270
1271 GlobalDecl getUnique(GlobalDecl GD) {
1272 const CXXMethodDecl *Unique = getUnique(cast<CXXMethodDecl>(GD.getDecl()));
1273
1274 if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(Unique))
1275 return GlobalDecl(CD, GD.getCtorType());
1276
1277 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(Unique))
1278 return GlobalDecl(DD, GD.getDtorType());
1279
1280 return Unique;
Mike Stump90181eb2010-01-26 00:05:04 +00001281 }
1282
Anders Carlsson323bb042009-11-26 19:54:33 +00001283 /// getPureVirtualFn - Return the __cxa_pure_virtual function.
1284 llvm::Constant* getPureVirtualFn() {
1285 if (!PureVirtualFn) {
1286 const llvm::FunctionType *Ty =
1287 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
1288 /*isVarArg=*/false);
1289 PureVirtualFn = wrap(CGM.CreateRuntimeFunction(Ty, "__cxa_pure_virtual"));
1290 }
1291
1292 return PureVirtualFn;
1293 }
1294
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001295public:
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00001296 OldVtableBuilder(const CXXRecordDecl *MostDerivedClass,
Eli Friedman6c08ce72009-12-05 01:05:03 +00001297 const CXXRecordDecl *l, uint64_t lo, CodeGenModule &cgm,
Anders Carlsson5f9a8812010-01-14 02:29:07 +00001298 bool build, CGVtableInfo::AddressPointsMapTy& AddressPoints)
Eli Friedman6c08ce72009-12-05 01:05:03 +00001299 : BuildVtable(build), MostDerivedClass(MostDerivedClass), LayoutClass(l),
1300 LayoutOffset(lo), BLayout(cgm.getContext().getASTRecordLayout(l)),
1301 rtti(0), VMContext(cgm.getModule().getContext()),CGM(cgm),
1302 PureVirtualFn(0),
Anders Carlssonbad80eb2009-12-04 18:36:22 +00001303 subAddressPoints(AllocAddressPoint(cgm, l, MostDerivedClass)),
Anders Carlsson5f9a8812010-01-14 02:29:07 +00001304 AddressPoints(AddressPoints),
1305 LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0))
1306 {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001307 Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
Anders Carlsson3f4336c2009-12-17 07:09:17 +00001308 if (BuildVtable) {
1309 QualType ClassType = CGM.getContext().getTagDeclType(MostDerivedClass);
1310 rtti = CGM.GetAddrOfRTTIDescriptor(ClassType);
1311 }
Mike Stump90181eb2010-01-26 00:05:04 +00001312 BuildUniqueOverriders(MostDerivedClass);
1313 MergeForwarding();
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001314 }
1315
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001316 // getVtableComponents - Returns a reference to the vtable components.
1317 const VtableComponentsVectorTy &getVtableComponents() const {
1318 return VtableComponents;
Anders Carlsson472404f2009-12-04 16:19:30 +00001319 }
1320
Anders Carlssone36a6b32010-01-02 01:01:18 +00001321 llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getVBIndex()
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001322 { return VBIndex; }
1323
Eli Friedman31bc3ad2009-12-07 23:56:34 +00001324 SavedAdjustmentsVectorTy &getSavedAdjustments()
1325 { return SavedAdjustments; }
Eli Friedman8174f2c2009-12-06 22:01:30 +00001326
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001327 llvm::Constant *wrap(Index_t i) {
1328 llvm::Constant *m;
1329 m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), i);
1330 return llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty);
1331 }
1332
1333 llvm::Constant *wrap(llvm::Constant *m) {
1334 return llvm::ConstantExpr::getBitCast(m, Ptr8Ty);
1335 }
1336
Mike Stumpd2808442010-01-22 02:51:26 +00001337//#define D1(x)
1338#define D1(X) do { if (getenv("DEBUG")) { X; } } while (0)
Mike Stump75ce5732009-10-31 20:06:59 +00001339
1340 void GenerateVBaseOffsets(const CXXRecordDecl *RD, uint64_t Offset,
Mike Stump28431212009-10-13 22:54:56 +00001341 bool updateVBIndex, Index_t current_vbindex) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001342 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
1343 e = RD->bases_end(); i != e; ++i) {
1344 const CXXRecordDecl *Base =
1345 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
Mike Stump28431212009-10-13 22:54:56 +00001346 Index_t next_vbindex = current_vbindex;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001347 if (i->isVirtual() && !SeenVBase.count(Base)) {
1348 SeenVBase.insert(Base);
Mike Stump28431212009-10-13 22:54:56 +00001349 if (updateVBIndex) {
Mike Stump75ce5732009-10-31 20:06:59 +00001350 next_vbindex = (ssize_t)(-(VCalls.size()*LLVMPointerWidth/8)
Mike Stump28431212009-10-13 22:54:56 +00001351 - 3*LLVMPointerWidth/8);
1352 VBIndex[Base] = next_vbindex;
1353 }
Mike Stump75ce5732009-10-31 20:06:59 +00001354 int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8;
1355 VCalls.push_back((0?700:0) + BaseOffset);
1356 D1(printf(" vbase for %s at %d delta %d most derived %s\n",
1357 Base->getNameAsCString(),
1358 (int)-VCalls.size()-3, (int)BaseOffset,
Mike Stumpd2808442010-01-22 02:51:26 +00001359 MostDerivedClass->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001360 }
Mike Stump28431212009-10-13 22:54:56 +00001361 // We also record offsets for non-virtual bases to closest enclosing
1362 // virtual base. We do this so that we don't have to search
1363 // for the nearst virtual base class when generating thunks.
1364 if (updateVBIndex && VBIndex.count(Base) == 0)
1365 VBIndex[Base] = next_vbindex;
Mike Stump75ce5732009-10-31 20:06:59 +00001366 GenerateVBaseOffsets(Base, Offset, updateVBIndex, next_vbindex);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001367 }
1368 }
1369
1370 void StartNewTable() {
1371 SeenVBase.clear();
1372 }
1373
Mike Stump8bccbfd2009-10-15 09:30:16 +00001374 Index_t getNVOffset_1(const CXXRecordDecl *D, const CXXRecordDecl *B,
1375 Index_t Offset = 0) {
1376
1377 if (B == D)
1378 return Offset;
1379
1380 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(D);
1381 for (CXXRecordDecl::base_class_const_iterator i = D->bases_begin(),
1382 e = D->bases_end(); i != e; ++i) {
1383 const CXXRecordDecl *Base =
1384 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
1385 int64_t BaseOffset = 0;
1386 if (!i->isVirtual())
1387 BaseOffset = Offset + Layout.getBaseClassOffset(Base);
1388 int64_t o = getNVOffset_1(Base, B, BaseOffset);
1389 if (o >= 0)
1390 return o;
1391 }
1392
1393 return -1;
1394 }
1395
1396 /// getNVOffset - Returns the non-virtual offset for the given (B) base of the
1397 /// derived class D.
1398 Index_t getNVOffset(QualType qB, QualType qD) {
Mike Stump46271322009-11-03 19:03:17 +00001399 qD = qD->getPointeeType();
1400 qB = qB->getPointeeType();
Mike Stump8bccbfd2009-10-15 09:30:16 +00001401 CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
1402 CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
1403 int64_t o = getNVOffset_1(D, B);
1404 if (o >= 0)
1405 return o;
1406
1407 assert(false && "FIXME: non-virtual base not found");
1408 return 0;
1409 }
1410
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001411 /// getVbaseOffset - Returns the index into the vtable for the virtual base
1412 /// offset for the given (B) virtual base of the derived class D.
1413 Index_t getVbaseOffset(QualType qB, QualType qD) {
Mike Stump46271322009-11-03 19:03:17 +00001414 qD = qD->getPointeeType();
1415 qB = qB->getPointeeType();
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001416 CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
1417 CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
Anders Carlssonbad80eb2009-12-04 18:36:22 +00001418 if (D != MostDerivedClass)
Eli Friedman03aa2f12009-11-30 01:19:33 +00001419 return CGM.getVtableInfo().getVirtualBaseOffsetIndex(D, B);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001420 llvm::DenseMap<const CXXRecordDecl *, Index_t>::iterator i;
1421 i = VBIndex.find(B);
1422 if (i != VBIndex.end())
1423 return i->second;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001424
Mike Stump28431212009-10-13 22:54:56 +00001425 assert(false && "FIXME: Base not found");
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001426 return 0;
1427 }
1428
Eli Friedman81fb0d22009-12-04 08:40:51 +00001429 bool OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
1430 Index_t OverrideOffset, Index_t Offset,
1431 int64_t CurrentVBaseOffset);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001432
Anders Carlsson495634e2009-12-04 02:39:04 +00001433 /// AppendMethods - Append the current methods to the vtable.
Anders Carlssonddf42c82009-12-04 02:56:03 +00001434 void AppendMethodsToVtable();
Anders Carlsson495634e2009-12-04 02:39:04 +00001435
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001436 llvm::Constant *WrapAddrOf(GlobalDecl GD) {
1437 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
1438
Anders Carlsson64457732009-11-24 05:08:52 +00001439 const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVtable(MD);
Mike Stump18e8b472009-10-27 23:36:26 +00001440
Mike Stumpcdeb8002009-12-03 16:55:20 +00001441 return wrap(CGM.GetAddrOfFunction(GD, Ty));
Mike Stump18e8b472009-10-27 23:36:26 +00001442 }
1443
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001444 void OverrideMethods(Path_t *Path, bool MorallyVirtual, int64_t Offset,
1445 int64_t CurrentVBaseOffset) {
Mike Stump37dbe962009-10-15 02:04:03 +00001446 for (Path_t::reverse_iterator i = Path->rbegin(),
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001447 e = Path->rend(); i != e; ++i) {
1448 const CXXRecordDecl *RD = i->first;
Mike Stump8bccbfd2009-10-15 09:30:16 +00001449 int64_t OverrideOffset = i->second;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001450 for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
1451 ++mi) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001452 const CXXMethodDecl *MD = *mi;
1453
1454 if (!MD->isVirtual())
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001455 continue;
1456
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001457 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1458 // Override both the complete and the deleting destructor.
1459 GlobalDecl CompDtor(DD, Dtor_Complete);
Eli Friedman81fb0d22009-12-04 08:40:51 +00001460 OverrideMethod(CompDtor, MorallyVirtual, OverrideOffset, Offset,
1461 CurrentVBaseOffset);
1462
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001463 GlobalDecl DeletingDtor(DD, Dtor_Deleting);
Eli Friedman81fb0d22009-12-04 08:40:51 +00001464 OverrideMethod(DeletingDtor, MorallyVirtual, OverrideOffset, Offset,
1465 CurrentVBaseOffset);
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001466 } else {
Eli Friedman81fb0d22009-12-04 08:40:51 +00001467 OverrideMethod(MD, MorallyVirtual, OverrideOffset, Offset,
1468 CurrentVBaseOffset);
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001469 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001470 }
1471 }
1472 }
1473
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001474 void AddMethod(const GlobalDecl GD, bool MorallyVirtual, Index_t Offset,
Eli Friedman03aa2f12009-11-30 01:19:33 +00001475 int64_t CurrentVBaseOffset) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001476 // If we can find a previously allocated slot for this, reuse it.
Eli Friedman81fb0d22009-12-04 08:40:51 +00001477 if (OverrideMethod(GD, MorallyVirtual, Offset, Offset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001478 CurrentVBaseOffset))
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001479 return;
1480
Mike Stump1f49d652010-01-22 18:48:47 +00001481 D1(printf(" vfn for %s at %d\n",
1482 dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsCString(),
1483 (int)Methods.size()));
1484
Anders Carlssoncdf18982009-12-04 02:08:24 +00001485 // We didn't find an entry in the vtable that we could use, add a new
1486 // entry.
1487 Methods.AddMethod(GD);
1488
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001489 VCallOffset[GD] = Offset/8 - CurrentVBaseOffset/8;
1490
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001491 if (MorallyVirtual) {
Anders Carlsson72281172010-01-26 17:36:47 +00001492 GlobalDecl UGD = getUnique(GD);
1493 const CXXMethodDecl *UMD = cast<CXXMethodDecl>(UGD.getDecl());
1494
Mike Stump90181eb2010-01-26 00:05:04 +00001495 assert(UMD && "final overrider not found");
1496
1497 Index_t &idx = VCall[UMD];
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001498 // Allocate the first one, after that, we reuse the previous one.
1499 if (idx == 0) {
Anders Carlsson72281172010-01-26 17:36:47 +00001500 VCallOffsetForVCall[UGD] = Offset/8;
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001501 NonVirtualOffset[UMD] = Offset/8 - CurrentVBaseOffset/8;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001502 idx = VCalls.size()+1;
Mike Stump90181eb2010-01-26 00:05:04 +00001503 VCalls.push_back(Offset/8 - CurrentVBaseOffset/8);
Mike Stump75ce5732009-10-31 20:06:59 +00001504 D1(printf(" vcall for %s at %d with delta %d\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001505 dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsCString(),
Mike Stump90181eb2010-01-26 00:05:04 +00001506 (int)-VCalls.size()-3, (int)VCalls[idx-1]));
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001507 }
1508 }
1509 }
1510
1511 void AddMethods(const CXXRecordDecl *RD, bool MorallyVirtual,
Eli Friedman03aa2f12009-11-30 01:19:33 +00001512 Index_t Offset, int64_t CurrentVBaseOffset) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001513 for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001514 ++mi) {
1515 const CXXMethodDecl *MD = *mi;
1516 if (!MD->isVirtual())
1517 continue;
1518
1519 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1520 // For destructors, add both the complete and the deleting destructor
1521 // to the vtable.
1522 AddMethod(GlobalDecl(DD, Dtor_Complete), MorallyVirtual, Offset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001523 CurrentVBaseOffset);
Eli Friedman03aa2f12009-11-30 01:19:33 +00001524 AddMethod(GlobalDecl(DD, Dtor_Deleting), MorallyVirtual, Offset,
1525 CurrentVBaseOffset);
1526 } else
1527 AddMethod(MD, MorallyVirtual, Offset, CurrentVBaseOffset);
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001528 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001529 }
1530
1531 void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
1532 const CXXRecordDecl *PrimaryBase,
1533 bool PrimaryBaseWasVirtual, bool MorallyVirtual,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001534 int64_t Offset, int64_t CurrentVBaseOffset,
1535 Path_t *Path) {
Mike Stump37dbe962009-10-15 02:04:03 +00001536 Path->push_back(std::make_pair(RD, Offset));
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001537 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
1538 e = RD->bases_end(); i != e; ++i) {
1539 if (i->isVirtual())
1540 continue;
1541 const CXXRecordDecl *Base =
1542 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
Mike Stump9eb76d42010-01-22 06:45:05 +00001543 uint64_t o = Offset + Layout.getBaseClassOffset(Base);
1544 StartNewTable();
1545 GenerateVtableForBase(Base, o, MorallyVirtual, false,
1546 true, Base == PrimaryBase && !PrimaryBaseWasVirtual,
1547 CurrentVBaseOffset, Path);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001548 }
Mike Stump37dbe962009-10-15 02:04:03 +00001549 Path->pop_back();
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001550 }
1551
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001552// #define D(X) do { X; } while (0)
1553#define D(X)
1554
1555 void insertVCalls(int InsertionPoint) {
Mike Stump75ce5732009-10-31 20:06:59 +00001556 D1(printf("============= combining vbase/vcall\n"));
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001557 D(VCalls.insert(VCalls.begin(), 673));
1558 D(VCalls.push_back(672));
Eli Friedman6c08ce72009-12-05 01:05:03 +00001559
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001560 VtableComponents.insert(VtableComponents.begin() + InsertionPoint,
1561 VCalls.size(), 0);
Eli Friedman6c08ce72009-12-05 01:05:03 +00001562 if (BuildVtable) {
1563 // The vcalls come first...
1564 for (std::vector<Index_t>::reverse_iterator i = VCalls.rbegin(),
1565 e = VCalls.rend();
1566 i != e; ++i)
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001567 VtableComponents[InsertionPoint++] = wrap((0?600:0) + *i);
Eli Friedman6c08ce72009-12-05 01:05:03 +00001568 }
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001569 VCalls.clear();
Mike Stump9f23a142009-11-10 02:30:51 +00001570 VCall.clear();
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001571 VCallOffsetForVCall.clear();
1572 VCallOffset.clear();
1573 NonVirtualOffset.clear();
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001574 }
1575
Mike Stump559387f2009-11-13 23:13:20 +00001576 void AddAddressPoints(const CXXRecordDecl *RD, uint64_t Offset,
1577 Index_t AddressPoint) {
1578 D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001579 RD->getNameAsCString(), MostDerivedClass->getNameAsCString(),
Mike Stump559387f2009-11-13 23:13:20 +00001580 LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
Mike Stumpcd2b8212009-11-19 20:52:19 +00001581 subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
Anders Carlsson5f9a8812010-01-14 02:29:07 +00001582 AddressPoints[BaseSubobject(RD, Offset)] = AddressPoint;
Mike Stump559387f2009-11-13 23:13:20 +00001583
1584 // Now also add the address point for all our primary bases.
1585 while (1) {
1586 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1587 RD = Layout.getPrimaryBase();
1588 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
1589 // FIXME: Double check this.
1590 if (RD == 0)
1591 break;
1592 if (PrimaryBaseWasVirtual &&
1593 BLayout.getVBaseClassOffset(RD) != Offset)
1594 break;
1595 D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001596 RD->getNameAsCString(), MostDerivedClass->getNameAsCString(),
Mike Stump559387f2009-11-13 23:13:20 +00001597 LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
Mike Stumpcd2b8212009-11-19 20:52:19 +00001598 subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
Anders Carlsson5f9a8812010-01-14 02:29:07 +00001599 AddressPoints[BaseSubobject(RD, Offset)] = AddressPoint;
Mike Stump559387f2009-11-13 23:13:20 +00001600 }
1601 }
1602
1603
Mike Stumpd538a6d2009-12-24 07:29:41 +00001604 void FinishGenerateVtable(const CXXRecordDecl *RD,
1605 const ASTRecordLayout &Layout,
1606 const CXXRecordDecl *PrimaryBase,
Mike Stump9eb76d42010-01-22 06:45:05 +00001607 bool ForNPNVBases, bool WasPrimaryBase,
Mike Stumpd538a6d2009-12-24 07:29:41 +00001608 bool PrimaryBaseWasVirtual,
1609 bool MorallyVirtual, int64_t Offset,
1610 bool ForVirtualBase, int64_t CurrentVBaseOffset,
1611 Path_t *Path) {
Mike Stump37dbe962009-10-15 02:04:03 +00001612 bool alloc = false;
1613 if (Path == 0) {
1614 alloc = true;
1615 Path = new Path_t;
1616 }
1617
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001618 StartNewTable();
1619 extra = 0;
Mike Stump9eb76d42010-01-22 06:45:05 +00001620 Index_t AddressPoint = 0;
1621 int VCallInsertionPoint = 0;
1622 if (!ForNPNVBases || !WasPrimaryBase) {
1623 bool DeferVCalls = MorallyVirtual || ForVirtualBase;
1624 VCallInsertionPoint = VtableComponents.size();
1625 if (!DeferVCalls) {
1626 insertVCalls(VCallInsertionPoint);
1627 } else
1628 // FIXME: just for extra, or for all uses of VCalls.size post this?
1629 extra = -VCalls.size();
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001630
Mike Stump9eb76d42010-01-22 06:45:05 +00001631 // Add the offset to top.
1632 VtableComponents.push_back(BuildVtable ? wrap(-((Offset-LayoutOffset)/8)) : 0);
Anders Carlsson472404f2009-12-04 16:19:30 +00001633
Mike Stump9eb76d42010-01-22 06:45:05 +00001634 // Add the RTTI information.
1635 VtableComponents.push_back(rtti);
Anders Carlsson472404f2009-12-04 16:19:30 +00001636
Mike Stump9eb76d42010-01-22 06:45:05 +00001637 AddressPoint = VtableComponents.size();
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001638
Mike Stump9eb76d42010-01-22 06:45:05 +00001639 AppendMethodsToVtable();
1640 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001641
1642 // and then the non-virtual bases.
1643 NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001644 MorallyVirtual, Offset, CurrentVBaseOffset, Path);
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001645
1646 if (ForVirtualBase) {
Mike Stump2cefe382009-11-12 20:47:57 +00001647 // FIXME: We're adding to VCalls in callers, we need to do the overrides
1648 // in the inner part, so that we know the complete set of vcalls during
1649 // the build and don't have to insert into methods. Saving out the
1650 // AddressPoint here, would need to be fixed, if we didn't do that. Also
1651 // retroactively adding vcalls for overrides later wind up in the wrong
1652 // place, the vcall slot has to be alloted during the walk of the base
1653 // when the function is first introduces.
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001654 AddressPoint += VCalls.size();
Mike Stump2cefe382009-11-12 20:47:57 +00001655 insertVCalls(VCallInsertionPoint);
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001656 }
1657
Mike Stump9eb76d42010-01-22 06:45:05 +00001658 if (!ForNPNVBases || !WasPrimaryBase)
1659 AddAddressPoints(RD, Offset, AddressPoint);
Mike Stump2cefe382009-11-12 20:47:57 +00001660
Mike Stump37dbe962009-10-15 02:04:03 +00001661 if (alloc) {
1662 delete Path;
1663 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001664 }
1665
Mike Stump75ce5732009-10-31 20:06:59 +00001666 void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
1667 bool updateVBIndex, Index_t current_vbindex,
Eli Friedman03aa2f12009-11-30 01:19:33 +00001668 int64_t CurrentVBaseOffset) {
Mike Stump75ce5732009-10-31 20:06:59 +00001669 if (!RD->isDynamicClass())
1670 return;
1671
1672 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1673 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1674 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
1675
1676 // vtables are composed from the chain of primaries.
Eli Friedman65d87222009-12-04 08:52:11 +00001677 if (PrimaryBase && !PrimaryBaseWasVirtual) {
Mike Stump75ce5732009-10-31 20:06:59 +00001678 D1(printf(" doing primaries for %s most derived %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001679 RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
Eli Friedman65d87222009-12-04 08:52:11 +00001680 Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
1681 updateVBIndex, current_vbindex, CurrentVBaseOffset);
Mike Stump75ce5732009-10-31 20:06:59 +00001682 }
1683
1684 D1(printf(" doing vcall entries for %s most derived %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001685 RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
Mike Stump75ce5732009-10-31 20:06:59 +00001686
1687 // And add the virtuals for the class to the primary vtable.
Eli Friedman03aa2f12009-11-30 01:19:33 +00001688 AddMethods(RD, MorallyVirtual, Offset, CurrentVBaseOffset);
Mike Stump75ce5732009-10-31 20:06:59 +00001689 }
1690
1691 void VBPrimaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
1692 bool updateVBIndex, Index_t current_vbindex,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001693 bool RDisVirtualBase, int64_t CurrentVBaseOffset,
Eli Friedman03aa2f12009-11-30 01:19:33 +00001694 bool bottom) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001695 if (!RD->isDynamicClass())
1696 return;
1697
1698 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1699 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1700 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
1701
1702 // vtables are composed from the chain of primaries.
1703 if (PrimaryBase) {
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001704 int BaseCurrentVBaseOffset = CurrentVBaseOffset;
1705 if (PrimaryBaseWasVirtual) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001706 IndirectPrimary.insert(PrimaryBase);
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001707 BaseCurrentVBaseOffset = BLayout.getVBaseClassOffset(PrimaryBase);
1708 }
Mike Stump75ce5732009-10-31 20:06:59 +00001709
1710 D1(printf(" doing primaries for %s most derived %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001711 RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
Mike Stump75ce5732009-10-31 20:06:59 +00001712
1713 VBPrimaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001714 updateVBIndex, current_vbindex, PrimaryBaseWasVirtual,
Eli Friedman03aa2f12009-11-30 01:19:33 +00001715 BaseCurrentVBaseOffset, false);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001716 }
1717
Mike Stump75ce5732009-10-31 20:06:59 +00001718 D1(printf(" doing vbase entries for %s most derived %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001719 RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
Mike Stump75ce5732009-10-31 20:06:59 +00001720 GenerateVBaseOffsets(RD, Offset, updateVBIndex, current_vbindex);
1721
1722 if (RDisVirtualBase || bottom) {
1723 Primaries(RD, MorallyVirtual, Offset, updateVBIndex, current_vbindex,
Eli Friedman03aa2f12009-11-30 01:19:33 +00001724 CurrentVBaseOffset);
Mike Stump75ce5732009-10-31 20:06:59 +00001725 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001726 }
1727
Mike Stumpd538a6d2009-12-24 07:29:41 +00001728 void GenerateVtableForBase(const CXXRecordDecl *RD, int64_t Offset = 0,
1729 bool MorallyVirtual = false,
1730 bool ForVirtualBase = false,
Mike Stump9eb76d42010-01-22 06:45:05 +00001731 bool ForNPNVBases = false,
1732 bool WasPrimaryBase = true,
Mike Stumpd538a6d2009-12-24 07:29:41 +00001733 int CurrentVBaseOffset = 0,
1734 Path_t *Path = 0) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001735 if (!RD->isDynamicClass())
Mike Stumpd538a6d2009-12-24 07:29:41 +00001736 return;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001737
Mike Stumpfa818082009-11-13 02:35:38 +00001738 // Construction vtable don't need parts that have no virtual bases and
1739 // aren't morally virtual.
Anders Carlssonbad80eb2009-12-04 18:36:22 +00001740 if ((LayoutClass != MostDerivedClass) &&
1741 RD->getNumVBases() == 0 && !MorallyVirtual)
Mike Stumpd538a6d2009-12-24 07:29:41 +00001742 return;
Mike Stumpfa818082009-11-13 02:35:38 +00001743
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001744 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1745 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1746 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
1747
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001748 extra = 0;
Mike Stump75ce5732009-10-31 20:06:59 +00001749 D1(printf("building entries for base %s most derived %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001750 RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001751
Mike Stump75ce5732009-10-31 20:06:59 +00001752 if (ForVirtualBase)
1753 extra = VCalls.size();
1754
Mike Stump9eb76d42010-01-22 06:45:05 +00001755 if (!ForNPNVBases || !WasPrimaryBase) {
1756 VBPrimaries(RD, MorallyVirtual, Offset, !ForVirtualBase, 0,
1757 ForVirtualBase, CurrentVBaseOffset, true);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001758
Mike Stump9eb76d42010-01-22 06:45:05 +00001759 if (Path)
1760 OverrideMethods(Path, MorallyVirtual, Offset, CurrentVBaseOffset);
1761 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001762
Mike Stump9eb76d42010-01-22 06:45:05 +00001763 FinishGenerateVtable(RD, Layout, PrimaryBase, ForNPNVBases, WasPrimaryBase,
1764 PrimaryBaseWasVirtual, MorallyVirtual, Offset,
1765 ForVirtualBase, CurrentVBaseOffset, Path);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001766 }
1767
1768 void GenerateVtableForVBases(const CXXRecordDecl *RD,
1769 int64_t Offset = 0,
Mike Stump37dbe962009-10-15 02:04:03 +00001770 Path_t *Path = 0) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001771 bool alloc = false;
1772 if (Path == 0) {
1773 alloc = true;
Mike Stump37dbe962009-10-15 02:04:03 +00001774 Path = new Path_t;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001775 }
1776 // FIXME: We also need to override using all paths to a virtual base,
1777 // right now, we just process the first path
1778 Path->push_back(std::make_pair(RD, Offset));
1779 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
1780 e = RD->bases_end(); i != e; ++i) {
1781 const CXXRecordDecl *Base =
1782 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
1783 if (i->isVirtual() && !IndirectPrimary.count(Base)) {
1784 // Mark it so we don't output it twice.
1785 IndirectPrimary.insert(Base);
1786 StartNewTable();
Mike Stumpb21c4ee2009-10-14 18:14:51 +00001787 VCall.clear();
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001788 int64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
Mike Stumpcd6f9ed2009-11-06 23:27:42 +00001789 int64_t CurrentVBaseOffset = BaseOffset;
Mike Stump75ce5732009-10-31 20:06:59 +00001790 D1(printf("vtable %s virtual base %s\n",
Mike Stumpd2808442010-01-22 02:51:26 +00001791 MostDerivedClass->getNameAsCString(), Base->getNameAsCString()));
Mike Stump9eb76d42010-01-22 06:45:05 +00001792 GenerateVtableForBase(Base, BaseOffset, true, true, false,
1793 true, CurrentVBaseOffset, Path);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001794 }
Mike Stump2cefe382009-11-12 20:47:57 +00001795 int64_t BaseOffset;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001796 if (i->isVirtual())
1797 BaseOffset = BLayout.getVBaseClassOffset(Base);
Mike Stump2cefe382009-11-12 20:47:57 +00001798 else {
1799 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1800 BaseOffset = Offset + Layout.getBaseClassOffset(Base);
1801 }
1802
Mike Stump37dbe962009-10-15 02:04:03 +00001803 if (Base->getNumVBases()) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001804 GenerateVtableForVBases(Base, BaseOffset, Path);
Mike Stump37dbe962009-10-15 02:04:03 +00001805 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001806 }
1807 Path->pop_back();
1808 if (alloc)
1809 delete Path;
1810 }
1811};
Anders Carlssonca1bf682009-12-03 01:54:02 +00001812} // end anonymous namespace
1813
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00001814bool OldVtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
Eli Friedman81fb0d22009-12-04 08:40:51 +00001815 Index_t OverrideOffset, Index_t Offset,
1816 int64_t CurrentVBaseOffset) {
Anders Carlssonca1bf682009-12-03 01:54:02 +00001817 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
1818
1819 const bool isPure = MD->isPure();
Anders Carlsson21bbc1e2009-12-05 17:04:47 +00001820
Anders Carlssonca1bf682009-12-03 01:54:02 +00001821 // FIXME: Should OverrideOffset's be Offset?
1822
Anders Carlsson21bbc1e2009-12-05 17:04:47 +00001823 for (CXXMethodDecl::method_iterator mi = MD->begin_overridden_methods(),
1824 e = MD->end_overridden_methods(); mi != e; ++mi) {
Anders Carlssonca1bf682009-12-03 01:54:02 +00001825 GlobalDecl OGD;
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001826 GlobalDecl OGD2;
Anders Carlssonca1bf682009-12-03 01:54:02 +00001827
Anders Carlssonf3935b42009-12-04 05:51:56 +00001828 const CXXMethodDecl *OMD = *mi;
Anders Carlssonca1bf682009-12-03 01:54:02 +00001829 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(OMD))
1830 OGD = GlobalDecl(DD, GD.getDtorType());
1831 else
1832 OGD = OMD;
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001833
Eli Friedman8174f2c2009-12-06 22:01:30 +00001834 // Check whether this is the method being overridden in this section of
1835 // the vtable.
Anders Carlsson7bb70762009-12-04 15:49:02 +00001836 uint64_t Index;
1837 if (!Methods.getIndex(OGD, Index))
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001838 continue;
1839
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001840 OGD2 = OGD;
1841
Eli Friedman8174f2c2009-12-06 22:01:30 +00001842 // Get the original method, which we should be computing thunks, etc,
1843 // against.
1844 OGD = Methods.getOrigMethod(Index);
1845 OMD = cast<CXXMethodDecl>(OGD.getDecl());
1846
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001847 QualType ReturnType =
1848 MD->getType()->getAs<FunctionType>()->getResultType();
1849 QualType OverriddenReturnType =
1850 OMD->getType()->getAs<FunctionType>()->getResultType();
Anders Carlssonca1bf682009-12-03 01:54:02 +00001851
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001852 // Check if we need a return type adjustment.
1853 if (TypeConversionRequiresAdjustment(CGM.getContext(), ReturnType,
1854 OverriddenReturnType)) {
1855 CanQualType &BaseReturnType = BaseReturnTypes[Index];
Anders Carlssonca1bf682009-12-03 01:54:02 +00001856
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001857 // Insert the base return type.
1858 if (BaseReturnType.isNull())
1859 BaseReturnType =
1860 CGM.getContext().getCanonicalType(OverriddenReturnType);
1861 }
Anders Carlssona93e9802009-12-04 03:52:52 +00001862
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001863 Methods.OverrideMethod(OGD, GD);
1864
Anders Carlsson72281172010-01-26 17:36:47 +00001865 GlobalDecl UGD = getUnique(GD);
1866 const CXXMethodDecl *UMD = cast<CXXMethodDecl>(UGD.getDecl());
1867 assert(UGD.getDecl() && "unique overrider not found");
1868 assert(UGD == getUnique(OGD) && "unique overrider not unique");
Mike Stump90181eb2010-01-26 00:05:04 +00001869
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001870 ThisAdjustments.erase(Index);
Mike Stump90181eb2010-01-26 00:05:04 +00001871 if (MorallyVirtual || VCall.count(UMD)) {
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001872
Mike Stump90181eb2010-01-26 00:05:04 +00001873 Index_t &idx = VCall[UMD];
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001874 if (idx == 0) {
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001875 VCallOffset[GD] = VCallOffset[OGD];
1876 // NonVirtualOffset[UMD] = CurrentVBaseOffset/8 - OverrideOffset/8;
1877 NonVirtualOffset[UMD] = VCallOffset[OGD];
Mike Stump77537b12010-01-26 03:42:22 +00001878 VCallOffsetForVCall[UMD] = OverrideOffset/8;
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001879 idx = VCalls.size()+1;
Mike Stump77537b12010-01-26 03:42:22 +00001880 VCalls.push_back(OverrideOffset/8 - CurrentVBaseOffset/8);
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001881 D1(printf(" vcall for %s at %d with delta %d most derived %s\n",
1882 MD->getNameAsString().c_str(), (int)-idx-3,
Mike Stumpd2808442010-01-22 02:51:26 +00001883 (int)VCalls[idx-1], MostDerivedClass->getNameAsCString()));
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001884 } else {
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001885 VCallOffset[GD] = NonVirtualOffset[UMD];
Anders Carlsson72281172010-01-26 17:36:47 +00001886 VCalls[idx-1] = -VCallOffsetForVCall[UGD] + OverrideOffset/8;
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001887 D1(printf(" vcall patch for %s at %d with delta %d most derived %s\n",
1888 MD->getNameAsString().c_str(), (int)-idx-3,
Mike Stumpd2808442010-01-22 02:51:26 +00001889 (int)VCalls[idx-1], MostDerivedClass->getNameAsCString()));
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001890 }
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001891 int64_t NonVirtualAdjustment = -VCallOffset[OGD];
Mike Stumpded0a402010-01-26 22:44:01 +00001892 QualType DerivedType = MD->getThisType(CGM.getContext());
1893 QualType BaseType = cast<const CXXMethodDecl>(OGD.getDecl())->getThisType(CGM.getContext());
1894 int64_t NonVirtualAdjustment2 = -(getNVOffset(BaseType, DerivedType)/8);
1895 if (NonVirtualAdjustment2 != NonVirtualAdjustment) {
1896 NonVirtualAdjustment = NonVirtualAdjustment2;
1897 }
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001898 int64_t VirtualAdjustment =
1899 -((idx + extra + 2) * LLVMPointerWidth / 8);
Anders Carlsson657f1392009-12-03 02:32:59 +00001900
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001901 // Optimize out virtual adjustments of 0.
1902 if (VCalls[idx-1] == 0)
1903 VirtualAdjustment = 0;
Anders Carlsson657f1392009-12-03 02:32:59 +00001904
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001905 ThunkAdjustment ThisAdjustment(NonVirtualAdjustment,
1906 VirtualAdjustment);
Anders Carlsson2ca285f2009-12-03 02:22:59 +00001907
Eli Friedman8174f2c2009-12-06 22:01:30 +00001908 if (!isPure && !ThisAdjustment.isEmpty()) {
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001909 ThisAdjustments[Index] = ThisAdjustment;
Eli Friedman31bc3ad2009-12-07 23:56:34 +00001910 SavedAdjustments.push_back(
1911 std::make_pair(GD, std::make_pair(OGD, ThisAdjustment)));
Eli Friedman8174f2c2009-12-06 22:01:30 +00001912 }
Anders Carlssonca1bf682009-12-03 01:54:02 +00001913 return true;
1914 }
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001915
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001916 VCallOffset[GD] = VCallOffset[OGD2] - OverrideOffset/8;
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001917
Mike Stumpa04ecfb2010-01-26 21:35:27 +00001918 int64_t NonVirtualAdjustment = -VCallOffset[GD];
1919 QualType DerivedType = MD->getThisType(CGM.getContext());
1920 QualType BaseType = cast<const CXXMethodDecl>(OGD.getDecl())->getThisType(CGM.getContext());
1921 int64_t NonVirtualAdjustment2 = -(getNVOffset(BaseType, DerivedType)/8);
1922 if (NonVirtualAdjustment2 != NonVirtualAdjustment) {
1923 NonVirtualAdjustment = NonVirtualAdjustment2;
1924 }
1925
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001926 if (NonVirtualAdjustment) {
1927 ThunkAdjustment ThisAdjustment(NonVirtualAdjustment, 0);
1928
Eli Friedmanf2eda5e2009-12-06 22:33:51 +00001929 if (!isPure) {
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001930 ThisAdjustments[Index] = ThisAdjustment;
Eli Friedman31bc3ad2009-12-07 23:56:34 +00001931 SavedAdjustments.push_back(
1932 std::make_pair(GD, std::make_pair(OGD, ThisAdjustment)));
Eli Friedmanf2eda5e2009-12-06 22:33:51 +00001933 }
Eli Friedman3d2e9de2009-12-04 08:34:14 +00001934 }
1935 return true;
Anders Carlssonca1bf682009-12-03 01:54:02 +00001936 }
1937
1938 return false;
Anders Carlssond59885022009-11-27 22:21:51 +00001939}
1940
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00001941void OldVtableBuilder::AppendMethodsToVtable() {
Eli Friedman6c08ce72009-12-05 01:05:03 +00001942 if (!BuildVtable) {
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001943 VtableComponents.insert(VtableComponents.end(), Methods.size(),
1944 (llvm::Constant *)0);
Eli Friedman6c08ce72009-12-05 01:05:03 +00001945 ThisAdjustments.clear();
1946 BaseReturnTypes.clear();
1947 Methods.clear();
1948 return;
1949 }
1950
Anders Carlsson472404f2009-12-04 16:19:30 +00001951 // Reserve room in the vtable for our new methods.
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001952 VtableComponents.reserve(VtableComponents.size() + Methods.size());
Anders Carlssonb07567c2009-12-04 03:07:26 +00001953
Anders Carlsson86809cd2009-12-04 02:43:50 +00001954 for (unsigned i = 0, e = Methods.size(); i != e; ++i) {
1955 GlobalDecl GD = Methods[i];
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00001956 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
1957
1958 // Get the 'this' pointer adjustment.
Anders Carlsson86809cd2009-12-04 02:43:50 +00001959 ThunkAdjustment ThisAdjustment = ThisAdjustments.lookup(i);
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00001960
1961 // Construct the return type adjustment.
1962 ThunkAdjustment ReturnAdjustment;
1963
1964 QualType BaseReturnType = BaseReturnTypes.lookup(i);
1965 if (!BaseReturnType.isNull() && !MD->isPure()) {
1966 QualType DerivedType =
1967 MD->getType()->getAs<FunctionType>()->getResultType();
1968
1969 int64_t NonVirtualAdjustment =
1970 getNVOffset(BaseReturnType, DerivedType) / 8;
1971
1972 int64_t VirtualAdjustment =
1973 getVbaseOffset(BaseReturnType, DerivedType);
1974
1975 ReturnAdjustment = ThunkAdjustment(NonVirtualAdjustment,
1976 VirtualAdjustment);
1977 }
1978
Anders Carlsson50f14742009-12-04 03:06:03 +00001979 llvm::Constant *Method = 0;
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00001980 if (!ReturnAdjustment.isEmpty()) {
1981 // Build a covariant thunk.
1982 CovariantThunkAdjustment Adjustment(ThisAdjustment, ReturnAdjustment);
Eli Friedman8174f2c2009-12-06 22:01:30 +00001983 Method = wrap(CGM.GetAddrOfCovariantThunk(GD, Adjustment));
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00001984 } else if (!ThisAdjustment.isEmpty()) {
1985 // Build a "regular" thunk.
Eli Friedman8174f2c2009-12-06 22:01:30 +00001986 Method = wrap(CGM.GetAddrOfThunk(GD, ThisAdjustment));
Anders Carlssonddf42c82009-12-04 02:56:03 +00001987 } else if (MD->isPure()) {
1988 // We have a pure virtual method.
Anders Carlsson50f14742009-12-04 03:06:03 +00001989 Method = getPureVirtualFn();
1990 } else {
1991 // We have a good old regular method.
1992 Method = WrapAddrOf(GD);
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00001993 }
Anders Carlsson50f14742009-12-04 03:06:03 +00001994
1995 // Add the method to the vtable.
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00001996 VtableComponents.push_back(Method);
Anders Carlsson86809cd2009-12-04 02:43:50 +00001997 }
1998
Anders Carlsson50f14742009-12-04 03:06:03 +00001999
Anders Carlsson86809cd2009-12-04 02:43:50 +00002000 ThisAdjustments.clear();
Anders Carlsson5b3ea9b2009-12-04 02:52:22 +00002001 BaseReturnTypes.clear();
Anders Carlsson86809cd2009-12-04 02:43:50 +00002002
Anders Carlsson495634e2009-12-04 02:39:04 +00002003 Methods.clear();
Anders Carlsson495634e2009-12-04 02:39:04 +00002004}
2005
Anders Carlssonf942ee02009-11-27 20:47:55 +00002006void CGVtableInfo::ComputeMethodVtableIndices(const CXXRecordDecl *RD) {
2007
2008 // Itanium C++ ABI 2.5.2:
Anders Carlsson259688c2010-02-02 03:37:46 +00002009 // The order of the virtual function pointers in a virtual table is the
2010 // order of declaration of the corresponding member functions in the class.
Anders Carlssonf942ee02009-11-27 20:47:55 +00002011 //
Anders Carlsson259688c2010-02-02 03:37:46 +00002012 // There is an entry for any virtual function declared in a class,
2013 // whether it is a new function or overrides a base class function,
2014 // unless it overrides a function from the primary base, and conversion
2015 // between their return types does not require an adjustment.
Anders Carlssonf942ee02009-11-27 20:47:55 +00002016
2017 int64_t CurrentIndex = 0;
2018
2019 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
2020 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
2021
2022 if (PrimaryBase) {
Anders Carlssonc920fa22009-11-30 19:43:26 +00002023 assert(PrimaryBase->isDefinition() &&
2024 "Should have the definition decl of the primary base!");
Anders Carlssonf942ee02009-11-27 20:47:55 +00002025
2026 // Since the record decl shares its vtable pointer with the primary base
2027 // we need to start counting at the end of the primary base's vtable.
2028 CurrentIndex = getNumVirtualFunctionPointers(PrimaryBase);
2029 }
Eli Friedman21517252009-12-15 03:31:17 +00002030
2031 // Collect all the primary bases, so we can check whether methods override
2032 // a method from the base.
Anders Carlsson65b49782010-02-12 05:25:12 +00002033 VtableBuilder::PrimaryBasesSetTy PrimaryBases;
Eli Friedman21517252009-12-15 03:31:17 +00002034 for (ASTRecordLayout::primary_base_info_iterator
2035 I = Layout.primary_base_begin(), E = Layout.primary_base_end();
2036 I != E; ++I)
2037 PrimaryBases.insert((*I).getBase());
2038
Anders Carlssonf942ee02009-11-27 20:47:55 +00002039 const CXXDestructorDecl *ImplicitVirtualDtor = 0;
2040
2041 for (CXXRecordDecl::method_iterator i = RD->method_begin(),
2042 e = RD->method_end(); i != e; ++i) {
2043 const CXXMethodDecl *MD = *i;
2044
2045 // We only want virtual methods.
2046 if (!MD->isVirtual())
2047 continue;
2048
Anders Carlssonf942ee02009-11-27 20:47:55 +00002049 // Check if this method overrides a method in the primary base.
Anders Carlsson65b49782010-02-12 05:25:12 +00002050 if (const CXXMethodDecl *OverriddenMD =
2051 OverridesMethodInPrimaryBase(MD, PrimaryBases)) {
2052 // Check if converting from the return type of the method to the
2053 // return type of the overridden method requires conversion.
Anders Carlsson5272c252010-02-12 17:37:14 +00002054 if (!ReturnTypeConversionRequiresAdjustment(MD, OverriddenMD)) {
Anders Carlsson65b49782010-02-12 05:25:12 +00002055 // This index is shared between the index in the vtable of the primary
2056 // base class.
2057 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2058 const CXXDestructorDecl *OverriddenDD =
2059 cast<CXXDestructorDecl>(OverriddenMD);
Anders Carlssonf942ee02009-11-27 20:47:55 +00002060
Anders Carlsson65b49782010-02-12 05:25:12 +00002061 // Add both the complete and deleting entries.
2062 MethodVtableIndices[GlobalDecl(DD, Dtor_Complete)] =
2063 getMethodVtableIndex(GlobalDecl(OverriddenDD, Dtor_Complete));
2064 MethodVtableIndices[GlobalDecl(DD, Dtor_Deleting)] =
2065 getMethodVtableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting));
2066 } else {
2067 MethodVtableIndices[MD] = getMethodVtableIndex(OverriddenMD);
2068 }
2069
2070 // We don't need to add an entry for this method.
Anders Carlsson07604812010-02-12 18:14:46 +00002071 continue;
Anders Carlssonf942ee02009-11-27 20:47:55 +00002072 }
2073 }
2074
Anders Carlssonf942ee02009-11-27 20:47:55 +00002075 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2076 if (MD->isImplicit()) {
2077 assert(!ImplicitVirtualDtor &&
2078 "Did already see an implicit virtual dtor!");
2079 ImplicitVirtualDtor = DD;
2080 continue;
2081 }
2082
2083 // Add the complete dtor.
2084 MethodVtableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++;
2085
2086 // Add the deleting dtor.
2087 MethodVtableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++;
2088 } else {
2089 // Add the entry.
2090 MethodVtableIndices[MD] = CurrentIndex++;
2091 }
2092 }
2093
2094 if (ImplicitVirtualDtor) {
2095 // Itanium C++ ABI 2.5.2:
2096 // If a class has an implicitly-defined virtual destructor,
2097 // its entries come after the declared virtual function pointers.
2098
2099 // Add the complete dtor.
2100 MethodVtableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Complete)] =
2101 CurrentIndex++;
2102
2103 // Add the deleting dtor.
2104 MethodVtableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Deleting)] =
2105 CurrentIndex++;
2106 }
2107
2108 NumVirtualFunctionPointers[RD] = CurrentIndex;
2109}
2110
2111uint64_t CGVtableInfo::getNumVirtualFunctionPointers(const CXXRecordDecl *RD) {
2112 llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
2113 NumVirtualFunctionPointers.find(RD);
2114 if (I != NumVirtualFunctionPointers.end())
2115 return I->second;
2116
2117 ComputeMethodVtableIndices(RD);
2118
2119 I = NumVirtualFunctionPointers.find(RD);
2120 assert(I != NumVirtualFunctionPointers.end() && "Did not find entry!");
2121 return I->second;
2122}
2123
2124uint64_t CGVtableInfo::getMethodVtableIndex(GlobalDecl GD) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +00002125 MethodVtableIndicesTy::iterator I = MethodVtableIndices.find(GD);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00002126 if (I != MethodVtableIndices.end())
2127 return I->second;
2128
Anders Carlssonfb4dda42009-11-13 17:08:56 +00002129 const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
Anders Carlssonf942ee02009-11-27 20:47:55 +00002130
2131 ComputeMethodVtableIndices(RD);
2132
Anders Carlssonfb4dda42009-11-13 17:08:56 +00002133 I = MethodVtableIndices.find(GD);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00002134 assert(I != MethodVtableIndices.end() && "Did not find index!");
2135 return I->second;
2136}
2137
Eli Friedman31bc3ad2009-12-07 23:56:34 +00002138CGVtableInfo::AdjustmentVectorTy*
2139CGVtableInfo::getAdjustments(GlobalDecl GD) {
2140 SavedAdjustmentsTy::iterator I = SavedAdjustments.find(GD);
2141 if (I != SavedAdjustments.end())
2142 return &I->second;
Eli Friedman8174f2c2009-12-06 22:01:30 +00002143
2144 const CXXRecordDecl *RD = cast<CXXRecordDecl>(GD.getDecl()->getDeclContext());
Eli Friedman31bc3ad2009-12-07 23:56:34 +00002145 if (!SavedAdjustmentRecords.insert(RD).second)
2146 return 0;
Eli Friedman8174f2c2009-12-06 22:01:30 +00002147
Anders Carlsson5f9a8812010-01-14 02:29:07 +00002148 AddressPointsMapTy AddressPoints;
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00002149 OldVtableBuilder b(RD, RD, 0, CGM, false, AddressPoints);
Eli Friedman8174f2c2009-12-06 22:01:30 +00002150 D1(printf("vtable %s\n", RD->getNameAsCString()));
2151 b.GenerateVtableForBase(RD);
2152 b.GenerateVtableForVBases(RD);
Eli Friedman8174f2c2009-12-06 22:01:30 +00002153
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00002154 for (OldVtableBuilder::SavedAdjustmentsVectorTy::iterator
Eli Friedman31bc3ad2009-12-07 23:56:34 +00002155 i = b.getSavedAdjustments().begin(),
2156 e = b.getSavedAdjustments().end(); i != e; i++)
2157 SavedAdjustments[i->first].push_back(i->second);
Eli Friedman8174f2c2009-12-06 22:01:30 +00002158
Eli Friedman31bc3ad2009-12-07 23:56:34 +00002159 I = SavedAdjustments.find(GD);
2160 if (I != SavedAdjustments.end())
2161 return &I->second;
2162
2163 return 0;
Eli Friedman8174f2c2009-12-06 22:01:30 +00002164}
2165
Anders Carlsson2bb27f52009-10-11 22:13:54 +00002166int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
2167 const CXXRecordDecl *VBase) {
2168 ClassPairTy ClassPair(RD, VBase);
2169
2170 VirtualBaseClassIndiciesTy::iterator I =
2171 VirtualBaseClassIndicies.find(ClassPair);
2172 if (I != VirtualBaseClassIndicies.end())
2173 return I->second;
2174
Anders Carlsson2bb27f52009-10-11 22:13:54 +00002175 // FIXME: This seems expensive. Can we do a partial job to get
2176 // just this data.
Anders Carlsson5f9a8812010-01-14 02:29:07 +00002177 AddressPointsMapTy AddressPoints;
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00002178 OldVtableBuilder b(RD, RD, 0, CGM, false, AddressPoints);
Mike Stump75ce5732009-10-31 20:06:59 +00002179 D1(printf("vtable %s\n", RD->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +00002180 b.GenerateVtableForBase(RD);
2181 b.GenerateVtableForVBases(RD);
2182
2183 for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
2184 b.getVBIndex().begin(), E = b.getVBIndex().end(); I != E; ++I) {
2185 // Insert all types.
2186 ClassPairTy ClassPair(RD, I->first);
2187
2188 VirtualBaseClassIndicies.insert(std::make_pair(ClassPair, I->second));
2189 }
2190
2191 I = VirtualBaseClassIndicies.find(ClassPair);
2192 assert(I != VirtualBaseClassIndicies.end() && "Did not find index!");
2193
2194 return I->second;
2195}
2196
Anders Carlssonc8e39ec2009-12-05 21:03:56 +00002197uint64_t CGVtableInfo::getVtableAddressPoint(const CXXRecordDecl *RD) {
2198 uint64_t AddressPoint =
Anders Carlsson93a18842010-01-02 18:02:32 +00002199 (*(*(CGM.getVtableInfo().AddressPoints[RD]))[RD])[std::make_pair(RD, 0)];
Anders Carlssonc8e39ec2009-12-05 21:03:56 +00002200
2201 return AddressPoint;
2202}
2203
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00002204llvm::GlobalVariable *
Anders Carlsson0911ae82009-12-06 00:23:49 +00002205CGVtableInfo::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
Anders Carlsson232324c2009-12-06 00:53:22 +00002206 bool GenerateDefinition,
Anders Carlsson0911ae82009-12-06 00:23:49 +00002207 const CXXRecordDecl *LayoutClass,
Anders Carlsson5f9a8812010-01-14 02:29:07 +00002208 const CXXRecordDecl *RD, uint64_t Offset,
2209 AddressPointsMapTy& AddressPoints) {
Anders Carlssoneee53d92010-02-13 02:02:03 +00002210 if (GenerateDefinition && CGM.getLangOptions().DumpVtableLayouts) {
2211 VtableBuilder Builder(RD);
2212
2213 Builder.dumpLayout(llvm::errs());
2214 }
2215
Anders Carlsson2bb27f52009-10-11 22:13:54 +00002216 llvm::SmallString<256> OutName;
Mike Stump2cefe382009-11-12 20:47:57 +00002217 if (LayoutClass != RD)
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00002218 CGM.getMangleContext().mangleCXXCtorVtable(LayoutClass, Offset / 8,
2219 RD, OutName);
Mike Stumpeac45592009-11-11 20:26:26 +00002220 else
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00002221 CGM.getMangleContext().mangleCXXVtable(RD, OutName);
Daniel Dunbare128dd12009-11-21 09:06:22 +00002222 llvm::StringRef Name = OutName.str();
Benjamin Kramerbb0a07b2009-10-11 22:57:54 +00002223
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00002224 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
Anders Carlsson93a18842010-01-02 18:02:32 +00002225 if (GV == 0 || CGM.getVtableInfo().AddressPoints[LayoutClass] == 0 ||
2226 GV->isDeclaration()) {
Anders Carlsson5d40c6f2010-02-11 08:02:13 +00002227 OldVtableBuilder b(RD, LayoutClass, Offset, CGM, GenerateDefinition,
2228 AddressPoints);
Eli Friedman6c08ce72009-12-05 01:05:03 +00002229
2230 D1(printf("vtable %s\n", RD->getNameAsCString()));
2231 // First comes the vtables for all the non-virtual bases...
Mike Stumpd538a6d2009-12-24 07:29:41 +00002232 b.GenerateVtableForBase(RD, Offset);
Eli Friedman6c08ce72009-12-05 01:05:03 +00002233
2234 // then the vtables for all the virtual bases.
2235 b.GenerateVtableForVBases(RD, Offset);
2236
Anders Carlsson58b271d2009-12-05 22:19:10 +00002237 llvm::Constant *Init = 0;
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00002238 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
Anders Carlsson58b271d2009-12-05 22:19:10 +00002239 llvm::ArrayType *ArrayType =
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00002240 llvm::ArrayType::get(Int8PtrTy, b.getVtableComponents().size());
Anders Carlssona95d4c52009-12-05 21:09:05 +00002241
Anders Carlsson232324c2009-12-06 00:53:22 +00002242 if (GenerateDefinition)
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00002243 Init = llvm::ConstantArray::get(ArrayType, &b.getVtableComponents()[0],
2244 b.getVtableComponents().size());
Anders Carlsson232324c2009-12-06 00:53:22 +00002245
Mike Stumpaa51ad62009-11-19 04:04:36 +00002246 llvm::GlobalVariable *OGV = GV;
Anders Carlsson232324c2009-12-06 00:53:22 +00002247
2248 GV = new llvm::GlobalVariable(CGM.getModule(), ArrayType,
2249 /*isConstant=*/true, Linkage, Init, Name);
Anders Carlssonfe5f7d92009-12-06 01:09:21 +00002250 CGM.setGlobalVisibility(GV, RD);
2251
Mike Stumpaa51ad62009-11-19 04:04:36 +00002252 if (OGV) {
2253 GV->takeName(OGV);
Anders Carlsson58b271d2009-12-05 22:19:10 +00002254 llvm::Constant *NewPtr =
2255 llvm::ConstantExpr::getBitCast(GV, OGV->getType());
Mike Stumpaa51ad62009-11-19 04:04:36 +00002256 OGV->replaceAllUsesWith(NewPtr);
2257 OGV->eraseFromParent();
2258 }
Mike Stumpaa51ad62009-11-19 04:04:36 +00002259 }
Anders Carlssonb3f54b72009-12-05 21:28:12 +00002260
2261 return GV;
Anders Carlsson2bb27f52009-10-11 22:13:54 +00002262}
Mike Stump9f23a142009-11-10 02:30:51 +00002263
Anders Carlsson232324c2009-12-06 00:53:22 +00002264void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
2265 const CXXRecordDecl *RD) {
Anders Carlssone1b3e622009-12-07 07:59:52 +00002266 llvm::GlobalVariable *&Vtable = Vtables[RD];
2267 if (Vtable) {
2268 assert(Vtable->getInitializer() && "Vtable doesn't have a definition!");
2269 return;
2270 }
2271
Anders Carlsson5f9a8812010-01-14 02:29:07 +00002272 AddressPointsMapTy AddressPoints;
2273 Vtable = GenerateVtable(Linkage, /*GenerateDefinition=*/true, RD, RD, 0,
2274 AddressPoints);
Anders Carlssone36a6b32010-01-02 01:01:18 +00002275 GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD);
Mike Stump1a139f82009-11-19 01:08:19 +00002276}
2277
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00002278llvm::GlobalVariable *CGVtableInfo::getVtable(const CXXRecordDecl *RD) {
Anders Carlsson232324c2009-12-06 00:53:22 +00002279 llvm::GlobalVariable *Vtable = Vtables.lookup(RD);
Anders Carlsson7e28c5f2009-12-06 00:01:05 +00002280
Anders Carlsson5f9a8812010-01-14 02:29:07 +00002281 if (!Vtable) {
2282 AddressPointsMapTy AddressPoints;
Anders Carlsson232324c2009-12-06 00:53:22 +00002283 Vtable = GenerateVtable(llvm::GlobalValue::ExternalLinkage,
Anders Carlsson5f9a8812010-01-14 02:29:07 +00002284 /*GenerateDefinition=*/false, RD, RD, 0,
2285 AddressPoints);
2286 }
Mike Stumpaa51ad62009-11-19 04:04:36 +00002287
Anders Carlsson4ed44eb2009-12-05 22:42:54 +00002288 return Vtable;
Mike Stumpd846d082009-11-10 07:44:33 +00002289}
Mike Stumpeac45592009-11-11 20:26:26 +00002290
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00002291void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
2292 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
2293 const CXXRecordDecl *RD = MD->getParent();
2294
Anders Carlsson4ed44eb2009-12-05 22:42:54 +00002295 // If the class doesn't have a vtable we don't need to emit one.
2296 if (!RD->isDynamicClass())
2297 return;
2298
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00002299 // Get the key function.
Anders Carlsson5ebf8b42009-12-07 04:35:11 +00002300 const CXXMethodDecl *KeyFunction = CGM.getContext().getKeyFunction(RD);
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00002301
Anders Carlsson4ed44eb2009-12-05 22:42:54 +00002302 if (KeyFunction) {
2303 // We don't have the right key function.
2304 if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl())
2305 return;
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00002306 }
2307
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00002308 // Emit the data.
Douglas Gregorccecc1b2010-01-06 20:27:16 +00002309 GenerateClassData(CGM.getVtableLinkage(RD), RD);
Eli Friedman8174f2c2009-12-06 22:01:30 +00002310
2311 for (CXXRecordDecl::method_iterator i = RD->method_begin(),
2312 e = RD->method_end(); i != e; ++i) {
Eli Friedman31bc3ad2009-12-07 23:56:34 +00002313 if ((*i)->isVirtual() && ((*i)->hasInlineBody() || (*i)->isImplicit())) {
Eli Friedman8174f2c2009-12-06 22:01:30 +00002314 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(*i)) {
2315 CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Complete));
2316 CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Deleting));
2317 } else {
2318 CGM.BuildThunksForVirtual(GlobalDecl(*i));
2319 }
2320 }
2321 }
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00002322}
2323