 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
75.3% |
324 / 430 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
91.6% |
394 / 430 |
| |
|
Line Coverage: |
91.5% |
626 / 684 |
| |
 |
|
 |
1 : //===--- 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"
16 : #include "clang/AST/CXXInheritance.h"
17 : #include "clang/AST/RecordLayout.h"
18 : #include "llvm/ADT/DenseSet.h"
19 : #include <cstdio>
20 :
21 : using namespace clang;
22 : using namespace CodeGen;
23 :
24 : namespace {
25 652: class VtableBuilder {
26 : public:
27 : /// Index_t - Vtable index type.
28 : typedef uint64_t Index_t;
29 : typedef std::vector<std::pair<GlobalDecl,
30 : std::pair<GlobalDecl, ThunkAdjustment> > >
31 : SavedAdjustmentsVectorTy;
32 : private:
33 :
34 : // VtableComponents - The components of the vtable being built.
35 : typedef llvm::SmallVector<llvm::Constant *, 64> VtableComponentsVectorTy;
36 : VtableComponentsVectorTy VtableComponents;
37 :
38 : const bool BuildVtable;
39 :
40 : llvm::Type *Ptr8Ty;
41 :
42 : /// MostDerivedClass - The most derived class that this vtable is being
43 : /// built for.
44 : const CXXRecordDecl *MostDerivedClass;
45 :
46 : /// LayoutClass - The most derived class used for virtual base layout
47 : /// information.
48 : const CXXRecordDecl *LayoutClass;
49 : /// LayoutOffset - The offset for Class in LayoutClass.
50 : uint64_t LayoutOffset;
51 : /// BLayout - Layout for the most derived class that this vtable is being
52 : /// built for.
53 : const ASTRecordLayout &BLayout;
54 : llvm::SmallSet<const CXXRecordDecl *, 32> IndirectPrimary;
55 : llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase;
56 : llvm::Constant *rtti;
57 : llvm::LLVMContext &VMContext;
58 : CodeGenModule &CGM; // Per-module state.
59 :
60 : llvm::DenseMap<const CXXMethodDecl *, Index_t> VCall;
61 : llvm::DenseMap<GlobalDecl, Index_t> VCallOffset;
62 : llvm::DenseMap<GlobalDecl, Index_t> VCallOffsetForVCall;
63 : // This is the offset to the nearest virtual base
64 : llvm::DenseMap<const CXXMethodDecl *, Index_t> NonVirtualOffset;
65 : llvm::DenseMap<const CXXRecordDecl *, Index_t> VBIndex;
66 :
67 : /// PureVirtualFunction - Points to __cxa_pure_virtual.
68 : llvm::Constant *PureVirtualFn;
69 :
70 : /// VtableMethods - A data structure for keeping track of methods in a vtable.
71 : /// Can add methods, override methods and iterate in vtable order.
72 1304: class VtableMethods {
73 : // MethodToIndexMap - Maps from a global decl to the index it has in the
74 : // Methods vector.
75 : llvm::DenseMap<GlobalDecl, uint64_t> MethodToIndexMap;
76 :
77 : /// Methods - The methods, in vtable order.
78 : typedef llvm::SmallVector<GlobalDecl, 16> MethodsVectorTy;
79 : MethodsVectorTy Methods;
80 : MethodsVectorTy OrigMethods;
81 :
82 : public:
83 : /// AddMethod - Add a method to the vtable methods.
84 2270: void AddMethod(GlobalDecl GD) {
85 : assert(!MethodToIndexMap.count(GD) &&
2270: branch 1 taken
0: branch 2 not taken
86 2270: "Method has already been added!");
87 :
88 2270: MethodToIndexMap[GD] = Methods.size();
89 2270: Methods.push_back(GD);
90 2270: OrigMethods.push_back(GD);
91 2270: }
92 :
93 : /// OverrideMethod - Replace a method with another.
94 596: void OverrideMethod(GlobalDecl OverriddenGD, GlobalDecl GD) {
95 : llvm::DenseMap<GlobalDecl, uint64_t>::iterator i
96 596: = MethodToIndexMap.find(OverriddenGD);
596: branch 3 taken
0: branch 4 not taken
97 596: assert(i != MethodToIndexMap.end() && "Did not find entry!");
98 :
99 : // Get the index of the old decl.
100 596: uint64_t Index = i->second;
101 :
102 : // Replace the old decl with the new decl.
103 596: Methods[Index] = GD;
104 :
105 : // And add the new.
106 596: MethodToIndexMap[GD] = Index;
107 596: }
108 :
109 : /// getIndex - Gives the index of a passed in GlobalDecl. Returns false if
110 : /// the index couldn't be found.
111 856: bool getIndex(GlobalDecl GD, uint64_t &Index) const {
112 : llvm::DenseMap<GlobalDecl, uint64_t>::const_iterator i
113 856: = MethodToIndexMap.find(GD);
114 :
260: branch 2 taken
596: branch 3 taken
115 856: if (i == MethodToIndexMap.end())
116 260: return false;
117 :
118 596: Index = i->second;
119 596: return true;
120 : }
121 :
122 596: GlobalDecl getOrigMethod(uint64_t Index) const {
123 596: return OrigMethods[Index];
124 : }
125 :
126 1682: MethodsVectorTy::size_type size() const {
127 1682: return Methods.size();
128 : }
129 :
130 1125: void clear() {
131 1125: MethodToIndexMap.clear();
132 1125: Methods.clear();
133 1125: OrigMethods.clear();
134 1125: }
135 :
136 1070: GlobalDecl operator[](uint64_t Index) const {
137 1070: return Methods[Index];
138 : }
139 : };
140 :
141 : /// Methods - The vtable methods we're currently building.
142 : VtableMethods Methods;
143 :
144 : /// ThisAdjustments - For a given index in the vtable, contains the 'this'
145 : /// pointer adjustment needed for a method.
146 : typedef llvm::DenseMap<uint64_t, ThunkAdjustment> ThisAdjustmentsMapTy;
147 : ThisAdjustmentsMapTy ThisAdjustments;
148 :
149 : SavedAdjustmentsVectorTy SavedAdjustments;
150 :
151 : /// BaseReturnTypes - Contains the base return types of methods who have been
152 : /// overridden with methods whose return types require adjustment. Used for
153 : /// generating covariant thunk information.
154 : typedef llvm::DenseMap<uint64_t, CanQualType> BaseReturnTypesMapTy;
155 : BaseReturnTypesMapTy BaseReturnTypes;
156 :
157 : std::vector<Index_t> VCalls;
158 :
159 : typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
160 : // subAddressPoints - Used to hold the AddressPoints (offsets) into the built
161 : // vtable for use in computing the initializers for the VTT.
162 : llvm::DenseMap<CtorVtable_t, int64_t> &subAddressPoints;
163 :
164 : /// AddressPoints - Address points for this vtable.
165 : CGVtableInfo::AddressPointsMapTy& AddressPoints;
166 :
167 : typedef CXXRecordDecl::method_iterator method_iter;
168 : const uint32_t LLVMPointerWidth;
169 : Index_t extra;
170 : typedef std::vector<std::pair<const CXXRecordDecl *, int64_t> > Path_t;
171 : static llvm::DenseMap<CtorVtable_t, int64_t>&
172 : AllocAddressPoint(CodeGenModule &cgm, const CXXRecordDecl *l,
173 652: const CXXRecordDecl *c) {
174 652: CGVtableInfo::AddrMap_t *&oref = cgm.getVtableInfo().AddressPoints[l];
298: branch 0 taken
354: branch 1 taken
175 652: if (oref == 0)
176 298: oref = new CGVtableInfo::AddrMap_t;
177 :
178 652: llvm::DenseMap<CtorVtable_t, int64_t> *&ref = (*oref)[c];
409: branch 0 taken
243: branch 1 taken
179 652: if (ref == 0)
180 409: ref = new llvm::DenseMap<CtorVtable_t, int64_t>;
181 652: return *ref;
182 : }
183 :
184 0: bool DclIsSame(const FunctionDecl *New, const FunctionDecl *Old) {
185 0: FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
186 0: FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
187 :
188 : // C++ [temp.fct]p2:
189 : // A function template can be overloaded with other function templates
190 : // and with normal (non-template) functions.
0: branch 0 not taken
0: branch 1 not taken
191 0: if ((OldTemplate == 0) != (NewTemplate == 0))
192 0: return false;
193 :
194 : // Is the function New an overload of the function Old?
195 0: QualType OldQType = CGM.getContext().getCanonicalType(Old->getType());
196 0: QualType NewQType = CGM.getContext().getCanonicalType(New->getType());
197 :
198 : // Compare the signatures (C++ 1.3.10) of the two functions to
199 : // determine whether they are overloads. If we find any mismatch
200 : // in the signature, they are overloads.
201 :
202 : // If either of these functions is a K&R-style function (no
203 : // prototype), then we consider them to have matching signatures.
0: branch 2 not taken
0: branch 3 not taken
0: branch 6 not taken
0: branch 7 not taken
0: branch 8 not taken
0: branch 9 not taken
204 0: if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) ||
205 : isa<FunctionNoProtoType>(NewQType.getTypePtr()))
206 0: return true;
207 :
208 0: FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
209 0: FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
210 :
211 : // The signature of a function includes the types of its
212 : // parameters (C++ 1.3.10), which includes the presence or absence
213 : // of the ellipsis; see C++ DR 357).
0: branch 1 not taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
0: branch 9 not taken
0: branch 10 not taken
0: branch 15 not taken
0: branch 16 not taken
0: branch 17 not taken
0: branch 18 not taken
214 0: if (OldQType != NewQType &&
215 : (OldType->getNumArgs() != NewType->getNumArgs() ||
216 : OldType->isVariadic() != NewType->isVariadic() ||
217 : !std::equal(OldType->arg_type_begin(), OldType->arg_type_end(),
218 : NewType->arg_type_begin())))
219 0: return false;
220 :
221 : #if 0
222 : // C++ [temp.over.link]p4:
223 : // The signature of a function template consists of its function
224 : // signature, its return type and its template parameter list. The names
225 : // of the template parameters are significant only for establishing the
226 : // relationship between the template parameters and the rest of the
227 : // signature.
228 : //
229 : // We check the return type and template parameter lists for function
230 : // templates first; the remaining checks follow.
231 : if (NewTemplate &&
232 : (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
233 : OldTemplate->getTemplateParameters(),
234 : TPL_TemplateMatch) ||
235 : OldType->getResultType() != NewType->getResultType()))
236 : return false;
237 : #endif
238 :
239 : // If the function is a class member, its signature includes the
240 : // cv-qualifiers (if any) on the function itself.
241 : //
242 : // As part of this, also check whether one of the member functions
243 : // is static, in which case they are not overloads (C++
244 : // 13.1p2). While not part of the definition of the signature,
245 : // this check is important to determine whether these functions
246 : // can be overloaded.
247 0: const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
248 0: const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
0: branch 0 not taken
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
0: branch 5 not taken
0: branch 6 not taken
0: branch 8 not taken
0: branch 9 not taken
0: branch 12 not taken
0: branch 13 not taken
0: branch 14 not taken
0: branch 15 not taken
249 0: if (OldMethod && NewMethod &&
250 : !OldMethod->isStatic() && !NewMethod->isStatic() &&
251 : OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers())
252 0: return false;
253 :
254 : // The signatures match; this is not an overload.
255 0: return true;
256 : }
257 :
258 : typedef llvm::DenseMap<const CXXMethodDecl *, const CXXMethodDecl*>
259 : ForwardUnique_t;
260 : ForwardUnique_t ForwardUnique;
261 : llvm::DenseMap<const CXXMethodDecl*, const CXXMethodDecl*> UniqueOverrider;
262 :
263 2435: void BuildUniqueOverrider(const CXXMethodDecl *U, const CXXMethodDecl *MD) {
264 2435: const CXXMethodDecl *PrevU = UniqueOverrider[MD];
0: branch 0 not taken
2435: branch 1 taken
265 2435: assert(U && "no unique overrider");
0: branch 0 not taken
2435: branch 1 taken
266 2435: if (PrevU == U)
267 0: return;
2435: branch 0 taken
0: branch 1 not taken
0: branch 2 not taken
2435: branch 3 taken
268 2435: if (PrevU != U && PrevU != 0) {
269 : // If already set, note the two sets as the same
270 : if (0)
271 : printf("%s::%s same as %s::%s\n",
272 : PrevU->getParent()->getNameAsCString(),
273 : PrevU->getNameAsCString(),
274 : U->getParent()->getNameAsCString(),
275 : U->getNameAsCString());
276 0: ForwardUnique[PrevU] = U;
277 0: return;
278 : }
279 :
280 : // Not set, set it now
281 : if (0)
282 : printf("marking %s::%s %p override as %s::%s\n",
283 : MD->getParent()->getNameAsCString(),
284 : MD->getNameAsCString(),
285 : (void*)MD,
286 : U->getParent()->getNameAsCString(),
287 : U->getNameAsCString());
288 2435: UniqueOverrider[MD] = U;
289 :
505: branch 1 taken
2435: branch 2 taken
290 5375: for (CXXMethodDecl::method_iterator mi = MD->begin_overridden_methods(),
291 2435: me = MD->end_overridden_methods(); mi != me; ++mi) {
292 505: BuildUniqueOverrider(U, *mi);
293 : }
294 : }
295 :
296 1931: void BuildUniqueOverriders(const CXXRecordDecl *RD) {
297 : if (0) printf("walking %s\n", RD->getNameAsCString());
10244: branch 3 taken
1931: branch 4 taken
298 14106: for (CXXRecordDecl::method_iterator i = RD->method_begin(),
299 1931: e = RD->method_end(); i != e; ++i) {
300 10244: const CXXMethodDecl *MD = *i;
7710: branch 1 taken
2534: branch 2 taken
301 10244: if (!MD->isVirtual())
302 7710: continue;
303 :
1930: branch 1 taken
604: branch 2 taken
304 2534: if (UniqueOverrider[MD] == 0) {
305 : // Only set this, if it hasn't been set yet.
306 1930: BuildUniqueOverrider(MD, MD);
307 : if (0)
308 : printf("top set is %s::%s %p\n",
309 : MD->getParent()->getNameAsCString(),
310 : MD->getNameAsCString(),
311 : (void*)MD);
312 1930: ForwardUnique[MD] = MD;
313 : }
314 : }
1279: branch 1 taken
1931: branch 2 taken
315 5141: for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
316 1931: e = RD->bases_end(); i != e; ++i) {
317 : const CXXRecordDecl *Base =
318 1279: cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
319 1279: BuildUniqueOverriders(Base);
320 : }
321 1931: }
322 :
323 3811: static int DclCmp(const void *p1, const void *p2) {
324 3811: const CXXMethodDecl *MD1 = (const CXXMethodDecl *)p1;
325 3811: const CXXMethodDecl *MD2 = (const CXXMethodDecl *)p2;
326 3811: return (MD1->getIdentifier() - MD2->getIdentifier());
327 : }
328 :
329 652: void MergeForwarding() {
330 : typedef llvm::SmallVector<const CXXMethodDecl *, 100> A_t;
331 652: A_t A;
1930: branch 4 taken
652: branch 5 taken
332 3234: for (ForwardUnique_t::iterator I = ForwardUnique.begin(),
333 652: E = ForwardUnique.end(); I != E; ++I) {
1930: branch 2 taken
0: branch 3 not taken
334 1930: if (I->first == I->second)
335 : // Only add the roots of all trees
336 1930: A.push_back(I->first);
337 : }
338 652: llvm::array_pod_sort(A.begin(), A.end(), DclCmp);
1930: branch 1 taken
652: branch 2 taken
339 3234: for (A_t::iterator I = A.begin(),
340 652: E = A.end(); I != E; ++I) {
341 1930: A_t::iterator J = I;
1316: branch 0 taken
614: branch 1 taken
0: branch 3 not taken
1316: branch 4 taken
0: branch 5 not taken
1930: branch 6 taken
342 3860: while (++J != E && DclCmp(*I, *J) == 0)
0: branch 1 not taken
0: branch 2 not taken
343 0: if (DclIsSame(*I, *J)) {
344 0: printf("connecting %s\n", (*I)->getNameAsCString());
345 0: ForwardUnique[*J] = *I;
346 : }
347 652: }
348 652: }
349 :
350 2306: const CXXMethodDecl *getUnique(const CXXMethodDecl *MD) {
351 2306: const CXXMethodDecl *U = UniqueOverrider[MD];
0: branch 0 not taken
2306: branch 1 taken
352 2306: assert(U && "unique overrider not found");
2306: branch 1 taken
0: branch 2 not taken
353 4612: while (ForwardUnique.count(U)) {
354 2306: const CXXMethodDecl *NU = ForwardUnique[U];
0: branch 0 not taken
2306: branch 1 taken
355 2306: if (NU == U) break;
356 0: U = NU;
357 : }
358 2306: return U;
359 : }
360 :
361 2306: GlobalDecl getUnique(GlobalDecl GD) {
362 2306: const CXXMethodDecl *Unique = getUnique(cast<CXXMethodDecl>(GD.getDecl()));
363 :
0: branch 1 not taken
2306: branch 2 taken
364 2306: if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(Unique))
365 0: return GlobalDecl(CD, GD.getCtorType());
366 :
92: branch 1 taken
2214: branch 2 taken
367 2306: if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(Unique))
368 92: return GlobalDecl(DD, GD.getDtorType());
369 :
370 2214: return Unique;
371 : }
372 :
373 : /// getPureVirtualFn - Return the __cxa_pure_virtual function.
374 4: llvm::Constant* getPureVirtualFn() {
4: branch 0 taken
0: branch 1 not taken
375 4: if (!PureVirtualFn) {
376 : const llvm::FunctionType *Ty =
377 : llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
378 4: /*isVarArg=*/false);
379 4: PureVirtualFn = wrap(CGM.CreateRuntimeFunction(Ty, "__cxa_pure_virtual"));
380 : }
381 :
382 4: return PureVirtualFn;
383 : }
384 :
385 : public:
386 : VtableBuilder(const CXXRecordDecl *MostDerivedClass,
387 : const CXXRecordDecl *l, uint64_t lo, CodeGenModule &cgm,
388 652: bool build, CGVtableInfo::AddressPointsMapTy& AddressPoints)
389 : : BuildVtable(build), MostDerivedClass(MostDerivedClass), LayoutClass(l),
390 : LayoutOffset(lo), BLayout(cgm.getContext().getASTRecordLayout(l)),
391 : rtti(0), VMContext(cgm.getModule().getContext()),CGM(cgm),
392 : PureVirtualFn(0),
393 : subAddressPoints(AllocAddressPoint(cgm, l, MostDerivedClass)),
394 : AddressPoints(AddressPoints),
395 652: LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0))
396 : {
397 652: Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
322: branch 0 taken
330: branch 1 taken
398 652: if (BuildVtable) {
399 322: QualType ClassType = CGM.getContext().getTagDeclType(MostDerivedClass);
400 322: rtti = CGM.GetAddrOfRTTIDescriptor(ClassType);
401 : }
402 652: BuildUniqueOverriders(MostDerivedClass);
403 652: MergeForwarding();
404 652: }
405 :
406 : // getVtableComponents - Returns a reference to the vtable components.
407 1054: const VtableComponentsVectorTy &getVtableComponents() const {
408 1054: return VtableComponents;
409 : }
410 :
411 166: llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getVBIndex()
412 166: { return VBIndex; }
413 :
414 318: SavedAdjustmentsVectorTy &getSavedAdjustments()
415 318: { return SavedAdjustments; }
416 :
417 1571: llvm::Constant *wrap(Index_t i) {
418 : llvm::Constant *m;
419 1571: m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), i);
420 1571: return llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty);
421 : }
422 :
423 1070: llvm::Constant *wrap(llvm::Constant *m) {
424 1070: return llvm::ConstantExpr::getBitCast(m, Ptr8Ty);
425 : }
426 :
427 : //#define D1(x)
428 : #define D1(X) do { if (getenv("DEBUG")) { X; } } while (0)
429 :
430 : void GenerateVBaseOffsets(const CXXRecordDecl *RD, uint64_t Offset,
431 3683: bool updateVBIndex, Index_t current_vbindex) {
2075: branch 1 taken
3683: branch 2 taken
432 9441: for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
433 3683: e = RD->bases_end(); i != e; ++i) {
434 : const CXXRecordDecl *Base =
435 2075: cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
436 2075: Index_t next_vbindex = current_vbindex;
1373: branch 1 taken
702: branch 2 taken
1031: branch 4 taken
342: branch 5 taken
1031: branch 6 taken
1044: branch 7 taken
437 2075: if (i->isVirtual() && !SeenVBase.count(Base)) {
438 1031: SeenVBase.insert(Base);
808: branch 0 taken
223: branch 1 taken
439 1031: if (updateVBIndex) {
440 : next_vbindex = (ssize_t)(-(VCalls.size()*LLVMPointerWidth/8)
441 808: - 3*LLVMPointerWidth/8);
442 808: VBIndex[Base] = next_vbindex;
443 : }
444 1031: int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8;
445 1031: VCalls.push_back((0?700:0) + BaseOffset);
0: branch 1 not taken
1031: branch 2 taken
446 1031: D1(printf(" vbase for %s at %d delta %d most derived %s\n",
447 : Base->getNameAsCString(),
448 : (int)-VCalls.size()-3, (int)BaseOffset,
449 : MostDerivedClass->getNameAsCString()));
450 : }
451 : // We also record offsets for non-virtual bases to closest enclosing
452 : // virtual base. We do this so that we don't have to search
453 : // for the nearst virtual base class when generating thunks.
1661: branch 0 taken
414: branch 1 taken
400: branch 3 taken
1261: branch 4 taken
400: branch 5 taken
1675: branch 6 taken
454 2075: if (updateVBIndex && VBIndex.count(Base) == 0)
455 400: VBIndex[Base] = next_vbindex;
456 2075: GenerateVBaseOffsets(Base, Offset, updateVBIndex, next_vbindex);
457 : }
458 3683: }
459 :
460 2368: void StartNewTable() {
461 2368: SeenVBase.clear();
462 2368: }
463 :
464 : Index_t getNVOffset_1(const CXXRecordDecl *D, const CXXRecordDecl *B,
465 1900: Index_t Offset = 0) {
466 :
654: branch 0 taken
1246: branch 1 taken
467 1900: if (B == D)
468 654: return Offset;
469 :
470 1246: const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(D);
1246: branch 1 taken
388: branch 2 taken
471 2880: for (CXXRecordDecl::base_class_const_iterator i = D->bases_begin(),
472 1246: e = D->bases_end(); i != e; ++i) {
473 : const CXXRecordDecl *Base =
474 1246: cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
475 1246: int64_t BaseOffset = 0;
803: branch 1 taken
443: branch 2 taken
476 1246: if (!i->isVirtual())
477 803: BaseOffset = Offset + Layout.getBaseClassOffset(Base);
478 1246: int64_t o = getNVOffset_1(Base, B, BaseOffset);
858: branch 0 taken
388: branch 1 taken
479 1246: if (o >= 0)
480 858: return o;
481 : }
482 :
483 388: return -1;
484 : }
485 :
486 : /// getNVOffset - Returns the non-virtual offset for the given (B) base of the
487 : /// derived class D.
488 654: Index_t getNVOffset(QualType qB, QualType qD) {
489 654: qD = qD->getPointeeType();
490 654: qB = qB->getPointeeType();
491 654: CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
492 654: CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
493 654: int64_t o = getNVOffset_1(D, B);
654: branch 0 taken
0: branch 1 not taken
494 654: if (o >= 0)
495 654: return o;
496 :
497 0: assert(false && "FIXME: non-virtual base not found");
498 : return 0;
499 : }
500 :
501 : /// getVbaseOffset - Returns the index into the vtable for the virtual base
502 : /// offset for the given (B) virtual base of the derived class D.
503 58: Index_t getVbaseOffset(QualType qB, QualType qD) {
504 58: qD = qD->getPointeeType();
505 58: qB = qB->getPointeeType();
506 58: CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
507 58: CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
6: branch 0 taken
52: branch 1 taken
508 58: if (D != MostDerivedClass)
509 6: return CGM.getVtableInfo().getVirtualBaseOffsetIndex(D, B);
510 52: llvm::DenseMap<const CXXRecordDecl *, Index_t>::iterator i;
511 52: i = VBIndex.find(B);
52: branch 3 taken
0: branch 4 not taken
512 52: if (i != VBIndex.end())
513 52: return i->second;
514 :
515 0: assert(false && "FIXME: Base not found");
516 : return 0;
517 : }
518 :
519 : bool OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
520 : Index_t OverrideOffset, Index_t Offset,
521 : int64_t CurrentVBaseOffset);
522 :
523 : /// AppendMethods - Append the current methods to the vtable.
524 : void AppendMethodsToVtable();
525 :
526 983: llvm::Constant *WrapAddrOf(GlobalDecl GD) {
527 983: const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
528 :
529 983: const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVtable(MD);
530 :
531 983: return wrap(CGM.GetAddrOfFunction(GD, Ty));
532 : }
533 :
534 : void OverrideMethods(Path_t *Path, bool MorallyVirtual, int64_t Offset,
535 473: int64_t CurrentVBaseOffset) {
734: branch 3 taken
473: branch 4 taken
536 1680: for (Path_t::reverse_iterator i = Path->rbegin(),
537 473: e = Path->rend(); i != e; ++i) {
538 734: const CXXRecordDecl *RD = i->first;
539 734: int64_t OverrideOffset = i->second;
3925: branch 4 taken
734: branch 5 taken
540 4659: for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
541 : ++mi) {
542 3925: const CXXMethodDecl *MD = *mi;
543 :
2942: branch 1 taken
983: branch 2 taken
544 3925: if (!MD->isVirtual())
545 2942: continue;
546 :
0: branch 1 not taken
983: branch 2 taken
547 983: if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
548 : // Override both the complete and the deleting destructor.
549 0: GlobalDecl CompDtor(DD, Dtor_Complete);
550 : OverrideMethod(CompDtor, MorallyVirtual, OverrideOffset, Offset,
551 0: CurrentVBaseOffset);
552 :
553 0: GlobalDecl DeletingDtor(DD, Dtor_Deleting);
554 : OverrideMethod(DeletingDtor, MorallyVirtual, OverrideOffset, Offset,
555 0: CurrentVBaseOffset);
556 : } else {
557 : OverrideMethod(MD, MorallyVirtual, OverrideOffset, Offset,
558 983: CurrentVBaseOffset);
559 : }
560 : }
561 : }
562 473: }
563 :
564 : void AddMethod(const GlobalDecl GD, bool MorallyVirtual, Index_t Offset,
565 2601: int64_t CurrentVBaseOffset) {
566 : // If we can find a previously allocated slot for this, reuse it.
331: branch 1 taken
2270: branch 2 taken
567 2601: if (OverrideMethod(GD, MorallyVirtual, Offset, Offset,
568 : CurrentVBaseOffset))
569 331: return;
570 :
0: branch 1 not taken
2270: branch 2 taken
571 2270: D1(printf(" vfn for %s at %d\n",
572 : dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsCString(),
573 : (int)Methods.size()));
574 :
575 : // We didn't find an entry in the vtable that we could use, add a new
576 : // entry.
577 2270: Methods.AddMethod(GD);
578 :
579 2270: VCallOffset[GD] = Offset/8 - CurrentVBaseOffset/8;
580 :
1114: branch 0 taken
1156: branch 1 taken
581 2270: if (MorallyVirtual) {
582 1114: GlobalDecl UGD = getUnique(GD);
583 1114: const CXXMethodDecl *UMD = cast<CXXMethodDecl>(UGD.getDecl());
584 :
0: branch 0 not taken
1114: branch 1 taken
585 1114: assert(UMD && "final overrider not found");
586 :
587 1114: Index_t &idx = VCall[UMD];
588 : // Allocate the first one, after that, we reuse the previous one.
1085: branch 0 taken
29: branch 1 taken
589 1114: if (idx == 0) {
590 1085: VCallOffsetForVCall[UGD] = Offset/8;
591 1085: NonVirtualOffset[UMD] = Offset/8 - CurrentVBaseOffset/8;
592 1085: idx = VCalls.size()+1;
593 1085: VCalls.push_back(Offset/8 - CurrentVBaseOffset/8);
0: branch 1 not taken
1085: branch 2 taken
594 1085: D1(printf(" vcall for %s at %d with delta %d\n",
595 : dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsCString(),
596 : (int)-VCalls.size()-3, (int)VCalls[idx-1]));
597 : }
598 : }
599 : }
600 :
601 : void AddMethods(const CXXRecordDecl *RD, bool MorallyVirtual,
602 1608: Index_t Offset, int64_t CurrentVBaseOffset) {
8945: branch 4 taken
1608: branch 5 taken
603 10553: for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
604 : ++mi) {
605 8945: const CXXMethodDecl *MD = *mi;
6418: branch 1 taken
2527: branch 2 taken
606 8945: if (!MD->isVirtual())
607 6418: continue;
608 :
74: branch 1 taken
2453: branch 2 taken
609 2527: if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
610 : // For destructors, add both the complete and the deleting destructor
611 : // to the vtable.
612 : AddMethod(GlobalDecl(DD, Dtor_Complete), MorallyVirtual, Offset,
613 74: CurrentVBaseOffset);
614 : AddMethod(GlobalDecl(DD, Dtor_Deleting), MorallyVirtual, Offset,
615 74: CurrentVBaseOffset);
616 : } else
617 2453: AddMethod(MD, MorallyVirtual, Offset, CurrentVBaseOffset);
618 : }
619 1608: }
620 :
621 : void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
622 : const CXXRecordDecl *PrimaryBase,
623 : bool PrimaryBaseWasVirtual, bool MorallyVirtual,
624 : int64_t Offset, int64_t CurrentVBaseOffset,
625 1370: Path_t *Path) {
626 1370: Path->push_back(std::make_pair(RD, Offset));
1127: branch 1 taken
1370: branch 2 taken
627 3867: for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
628 1370: e = RD->bases_end(); i != e; ++i) {
708: branch 1 taken
419: branch 2 taken
629 1127: if (i->isVirtual())
630 708: continue;
631 : const CXXRecordDecl *Base =
632 419: cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
633 419: uint64_t o = Offset + Layout.getBaseClassOffset(Base);
634 419: StartNewTable();
635 : GenerateVtableForBase(Base, o, MorallyVirtual, false,
636 : true, Base == PrimaryBase && !PrimaryBaseWasVirtual,
253: branch 0 taken
166: branch 1 taken
253: branch 2 taken
0: branch 3 not taken
637 419: CurrentVBaseOffset, Path);
638 : }
639 1370: Path->pop_back();
640 1370: }
641 :
642 : // #define D(X) do { X; } while (0)
643 : #define D(X)
644 :
645 1090: void insertVCalls(int InsertionPoint) {
0: branch 1 not taken
1090: branch 2 taken
646 1090: D1(printf("============= combining vbase/vcall\n"));
647 : D(VCalls.insert(VCalls.begin(), 673));
648 : D(VCalls.push_back(672));
649 :
650 : VtableComponents.insert(VtableComponents.begin() + InsertionPoint,
651 1090: VCalls.size(), 0);
543: branch 0 taken
547: branch 1 taken
652 1090: if (BuildVtable) {
653 : // The vcalls come first...
1014: branch 3 taken
543: branch 4 taken
654 2100: for (std::vector<Index_t>::reverse_iterator i = VCalls.rbegin(),
655 543: e = VCalls.rend();
656 : i != e; ++i)
657 1014: VtableComponents[InsertionPoint++] = wrap((0?600:0) + *i);
658 : }
659 1090: VCalls.clear();
660 1090: VCall.clear();
661 1090: VCallOffsetForVCall.clear();
662 1090: VCallOffset.clear();
663 1090: NonVirtualOffset.clear();
664 1090: }
665 :
666 : void AddAddressPoints(const CXXRecordDecl *RD, uint64_t Offset,
667 1125: Index_t AddressPoint) {
0: branch 1 not taken
1125: branch 2 taken
668 1125: D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n",
669 : RD->getNameAsCString(), MostDerivedClass->getNameAsCString(),
670 : LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
671 1125: subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
672 1125: AddressPoints[BaseSubobject(RD, Offset)] = AddressPoint;
673 :
674 : // Now also add the address point for all our primary bases.
675 483: while (1) {
676 1608: const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
677 1608: RD = Layout.getPrimaryBase();
678 1608: const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
679 : // FIXME: Double check this.
483: branch 0 taken
1125: branch 1 taken
680 1608: if (RD == 0)
681 1125: break;
204: branch 0 taken
279: branch 1 taken
0: branch 3 not taken
204: branch 4 taken
0: branch 5 not taken
483: branch 6 taken
682 483: if (PrimaryBaseWasVirtual &&
683 : BLayout.getVBaseClassOffset(RD) != Offset)
684 0: break;
0: branch 1 not taken
483: branch 2 taken
685 483: D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n",
686 : RD->getNameAsCString(), MostDerivedClass->getNameAsCString(),
687 : LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
688 483: subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
689 483: AddressPoints[BaseSubobject(RD, Offset)] = AddressPoint;
690 : }
691 1125: }
692 :
693 :
694 : void FinishGenerateVtable(const CXXRecordDecl *RD,
695 : const ASTRecordLayout &Layout,
696 : const CXXRecordDecl *PrimaryBase,
697 : bool ForNPNVBases, bool WasPrimaryBase,
698 : bool PrimaryBaseWasVirtual,
699 : bool MorallyVirtual, int64_t Offset,
700 : bool ForVirtualBase, int64_t CurrentVBaseOffset,
701 1370: Path_t *Path) {
702 1370: bool alloc = false;
652: branch 0 taken
718: branch 1 taken
703 1370: if (Path == 0) {
704 652: alloc = true;
705 652: Path = new Path_t;
706 : }
707 :
708 1370: StartNewTable();
709 1370: extra = 0;
710 1370: Index_t AddressPoint = 0;
711 1370: int VCallInsertionPoint = 0;
329: branch 0 taken
1041: branch 1 taken
84: branch 2 taken
245: branch 3 taken
712 1370: if (!ForNPNVBases || !WasPrimaryBase) {
701: branch 0 taken
424: branch 1 taken
0: branch 2 not taken
701: branch 3 taken
713 1125: bool DeferVCalls = MorallyVirtual || ForVirtualBase;
714 1125: VCallInsertionPoint = VtableComponents.size();
701: branch 0 taken
424: branch 1 taken
715 1125: if (!DeferVCalls) {
716 701: insertVCalls(VCallInsertionPoint);
717 : } else
718 : // FIXME: just for extra, or for all uses of VCalls.size post this?
719 424: extra = -VCalls.size();
720 :
721 : // Add the offset to top.
557: branch 0 taken
568: branch 1 taken
722 1125: VtableComponents.push_back(BuildVtable ? wrap(-((Offset-LayoutOffset)/8)) : 0);
723 :
724 : // Add the RTTI information.
725 1125: VtableComponents.push_back(rtti);
726 :
727 1125: AddressPoint = VtableComponents.size();
728 :
729 1125: AppendMethodsToVtable();
730 : }
731 :
732 : // and then the non-virtual bases.
733 : NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual,
734 1370: MorallyVirtual, Offset, CurrentVBaseOffset, Path);
735 :
389: branch 0 taken
981: branch 1 taken
736 1370: if (ForVirtualBase) {
737 : // FIXME: We're adding to VCalls in callers, we need to do the overrides
738 : // in the inner part, so that we know the complete set of vcalls during
739 : // the build and don't have to insert into methods. Saving out the
740 : // AddressPoint here, would need to be fixed, if we didn't do that. Also
741 : // retroactively adding vcalls for overrides later wind up in the wrong
742 : // place, the vcall slot has to be alloted during the walk of the base
743 : // when the function is first introduces.
744 389: AddressPoint += VCalls.size();
745 389: insertVCalls(VCallInsertionPoint);
746 : }
747 :
329: branch 0 taken
1041: branch 1 taken
84: branch 2 taken
245: branch 3 taken
748 1370: if (!ForNPNVBases || !WasPrimaryBase)
749 1125: AddAddressPoints(RD, Offset, AddressPoint);
750 :
652: branch 0 taken
718: branch 1 taken
751 1370: if (alloc) {
652: branch 0 taken
0: branch 1 not taken
752 652: delete Path;
753 : }
754 1370: }
755 :
756 : void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
757 : bool updateVBIndex, Index_t current_vbindex,
758 1608: int64_t CurrentVBaseOffset) {
0: branch 1 not taken
1608: branch 2 taken
759 1608: if (!RD->isDynamicClass())
760 0: return;
761 :
762 1608: const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
763 1608: const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
764 1608: const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
765 :
766 : // vtables are composed from the chain of primaries.
483: branch 0 taken
1125: branch 1 taken
279: branch 2 taken
204: branch 3 taken
767 1608: if (PrimaryBase && !PrimaryBaseWasVirtual) {
0: branch 1 not taken
279: branch 2 taken
768 279: D1(printf(" doing primaries for %s most derived %s\n",
769 : RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
770 : Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
771 279: updateVBIndex, current_vbindex, CurrentVBaseOffset);
772 : }
773 :
0: branch 1 not taken
1608: branch 2 taken
774 1608: D1(printf(" doing vcall entries for %s most derived %s\n",
775 : RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
776 :
777 : // And add the virtuals for the class to the primary vtable.
778 1608: AddMethods(RD, MorallyVirtual, Offset, CurrentVBaseOffset);
779 : }
780 :
781 : void VBPrimaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
782 : bool updateVBIndex, Index_t current_vbindex,
783 : bool RDisVirtualBase, int64_t CurrentVBaseOffset,
784 1608: bool bottom) {
0: branch 1 not taken
1608: branch 2 taken
785 1608: if (!RD->isDynamicClass())
786 0: return;
787 :
788 1608: const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
789 1608: const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
790 1608: const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
791 :
792 : // vtables are composed from the chain of primaries.
483: branch 0 taken
1125: branch 1 taken
793 1608: if (PrimaryBase) {
794 483: int BaseCurrentVBaseOffset = CurrentVBaseOffset;
204: branch 0 taken
279: branch 1 taken
795 483: if (PrimaryBaseWasVirtual) {
796 204: IndirectPrimary.insert(PrimaryBase);
797 204: BaseCurrentVBaseOffset = BLayout.getVBaseClassOffset(PrimaryBase);
798 : }
799 :
0: branch 1 not taken
483: branch 2 taken
800 483: D1(printf(" doing primaries for %s most derived %s\n",
801 : RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
802 :
803 : VBPrimaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
804 : updateVBIndex, current_vbindex, PrimaryBaseWasVirtual,
805 483: BaseCurrentVBaseOffset, false);
806 : }
807 :
0: branch 1 not taken
1608: branch 2 taken
808 1608: D1(printf(" doing vbase entries for %s most derived %s\n",
809 : RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
810 1608: GenerateVBaseOffsets(RD, Offset, updateVBIndex, current_vbindex);
811 :
1015: branch 0 taken
593: branch 1 taken
736: branch 2 taken
279: branch 3 taken
812 1608: if (RDisVirtualBase || bottom) {
813 : Primaries(RD, MorallyVirtual, Offset, updateVBIndex, current_vbindex,
814 1329: CurrentVBaseOffset);
815 : }
816 : }
817 :
818 : void GenerateVtableForBase(const CXXRecordDecl *RD, int64_t Offset = 0,
819 : bool MorallyVirtual = false,
820 : bool ForVirtualBase = false,
821 : bool ForNPNVBases = false,
822 : bool WasPrimaryBase = true,
823 : int CurrentVBaseOffset = 0,
824 1650: Path_t *Path = 0) {
268: branch 1 taken
1382: branch 2 taken
825 1650: if (!RD->isDynamicClass())
826 268: return;
827 :
828 : // Construction vtable don't need parts that have no virtual bases and
829 : // aren't morally virtual.
231: branch 0 taken
1151: branch 1 taken
84: branch 3 taken
147: branch 4 taken
12: branch 5 taken
72: branch 6 taken
12: branch 7 taken
1370: branch 8 taken
830 1382: if ((LayoutClass != MostDerivedClass) &&
831 : RD->getNumVBases() == 0 && !MorallyVirtual)
832 12: return;
833 :
834 1370: const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
835 1370: const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
836 1370: const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
837 :
838 1370: extra = 0;
0: branch 1 not taken
1370: branch 2 taken
839 1370: D1(printf("building entries for base %s most derived %s\n",
840 : RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
841 :
389: branch 0 taken
981: branch 1 taken
842 1370: if (ForVirtualBase)
843 389: extra = VCalls.size();
844 :
329: branch 0 taken
1041: branch 1 taken
84: branch 2 taken
245: branch 3 taken
845 1370: if (!ForNPNVBases || !WasPrimaryBase) {
846 : VBPrimaries(RD, MorallyVirtual, Offset, !ForVirtualBase, 0,
847 1125: ForVirtualBase, CurrentVBaseOffset, true);
848 :
473: branch 0 taken
652: branch 1 taken
849 1125: if (Path)
850 473: OverrideMethods(Path, MorallyVirtual, Offset, CurrentVBaseOffset);
851 : }
852 :
853 : FinishGenerateVtable(RD, Layout, PrimaryBase, ForNPNVBases, WasPrimaryBase,
854 : PrimaryBaseWasVirtual, MorallyVirtual, Offset,
855 1370: ForVirtualBase, CurrentVBaseOffset, Path);
856 : }
857 :
858 : void GenerateVtableForVBases(const CXXRecordDecl *RD,
859 : int64_t Offset = 0,
860 978: Path_t *Path = 0) {
861 978: bool alloc = false;
652: branch 0 taken
326: branch 1 taken
862 978: if (Path == 0) {
863 652: alloc = true;
864 652: Path = new Path_t;
865 : }
866 : // FIXME: We also need to override using all paths to a virtual base,
867 : // right now, we just process the first path
868 978: Path->push_back(std::make_pair(RD, Offset));
1181: branch 1 taken
978: branch 2 taken
869 3137: for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
870 978: e = RD->bases_end(); i != e; ++i) {
871 : const CXXRecordDecl *Base =
872 1181: cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
827: branch 1 taken
354: branch 2 taken
579: branch 4 taken
248: branch 5 taken
579: branch 6 taken
602: branch 7 taken
873 1181: if (i->isVirtual() && !IndirectPrimary.count(Base)) {
874 : // Mark it so we don't output it twice.
875 579: IndirectPrimary.insert(Base);
876 579: StartNewTable();
877 579: VCall.clear();
878 579: int64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
879 579: int64_t CurrentVBaseOffset = BaseOffset;
0: branch 1 not taken
579: branch 2 taken
880 579: D1(printf("vtable %s virtual base %s\n",
881 : MostDerivedClass->getNameAsCString(), Base->getNameAsCString()));
882 : GenerateVtableForBase(Base, BaseOffset, true, true, false,
883 579: true, CurrentVBaseOffset, Path);
884 : }
885 : int64_t BaseOffset;
827: branch 1 taken
354: branch 2 taken
886 1181: if (i->isVirtual())
887 827: BaseOffset = BLayout.getVBaseClassOffset(Base);
888 : else {
889 354: const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
890 354: BaseOffset = Offset + Layout.getBaseClassOffset(Base);
891 : }
892 :
326: branch 1 taken
855: branch 2 taken
893 1181: if (Base->getNumVBases()) {
894 326: GenerateVtableForVBases(Base, BaseOffset, Path);
895 : }
896 : }
897 978: Path->pop_back();
652: branch 0 taken
326: branch 1 taken
898 978: if (alloc)
652: branch 0 taken
0: branch 1 not taken
899 652: delete Path;
900 978: }
901 : };
902 : } // end anonymous namespace
903 :
904 : /// TypeConversionRequiresAdjustment - Returns whether conversion from a
905 : /// derived type to a base type requires adjustment.
906 : static bool
907 : TypeConversionRequiresAdjustment(ASTContext &Ctx,
908 : const CXXRecordDecl *DerivedDecl,
909 192: const CXXRecordDecl *BaseDecl) {
910 : CXXBasePaths Paths(/*FindAmbiguities=*/false,
911 192: /*RecordPaths=*/true, /*DetectVirtual=*/true);
0: branch 1 not taken
192: branch 2 taken
912 192: if (!const_cast<CXXRecordDecl *>(DerivedDecl)->
913 : isDerivedFrom(const_cast<CXXRecordDecl *>(BaseDecl), Paths)) {
914 0: assert(false && "Class must be derived from the passed in base class!");
915 : return false;
916 : }
917 :
918 : // If we found a virtual base we always want to require adjustment.
156: branch 1 taken
36: branch 2 taken
919 192: if (Paths.getDetectedVirtual())
920 156: return true;
921 :
922 36: const CXXBasePath &Path = Paths.front();
923 :
36: branch 1 taken
0: branch 2 not taken
924 36: for (size_t Start = 0, End = Path.size(); Start != End; ++Start) {
925 36: const CXXBasePathElement &Element = Path[Start];
926 :
927 : // Check the base class offset.
928 36: const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Element.Class);
929 :
930 36: const RecordType *BaseType = Element.Base->getType()->getAs<RecordType>();
931 36: const CXXRecordDecl *Base = cast<CXXRecordDecl>(BaseType->getDecl());
932 :
36: branch 1 taken
0: branch 2 not taken
933 36: if (Layout.getBaseClassOffset(Base) != 0) {
934 : // This requires an adjustment.
935 36: return true;
936 : }
937 : }
938 :
939 0: return false;
940 : }
941 :
942 : static bool
943 : TypeConversionRequiresAdjustment(ASTContext &Ctx,
944 600: QualType DerivedType, QualType BaseType) {
945 : // Canonicalize the types.
946 600: QualType CanDerivedType = Ctx.getCanonicalType(DerivedType);
947 600: QualType CanBaseType = Ctx.getCanonicalType(BaseType);
948 :
949 : assert(CanDerivedType->getTypeClass() == CanBaseType->getTypeClass() &&
600: branch 4 taken
0: branch 5 not taken
950 600: "Types must have same type class!");
951 :
408: branch 1 taken
192: branch 2 taken
952 600: if (CanDerivedType == CanBaseType) {
953 : // No adjustment needed.
954 408: return false;
955 : }
956 :
64: branch 1 taken
128: branch 2 taken
957 192: if (const ReferenceType *RT = dyn_cast<ReferenceType>(CanDerivedType)) {
958 64: CanDerivedType = RT->getPointeeType();
959 64: CanBaseType = cast<ReferenceType>(CanBaseType)->getPointeeType();
128: branch 1 taken
0: branch 2 not taken
960 128: } else if (const PointerType *PT = dyn_cast<PointerType>(CanDerivedType)) {
961 128: CanDerivedType = PT->getPointeeType();
962 128: CanBaseType = cast<PointerType>(CanBaseType)->getPointeeType();
963 : } else {
964 0: assert(false && "Unexpected return type!");
965 : }
966 :
0: branch 1 not taken
192: branch 2 taken
967 192: if (CanDerivedType == CanBaseType) {
968 : // No adjustment needed.
969 0: return false;
970 : }
971 :
972 : const CXXRecordDecl *DerivedDecl =
973 192: cast<CXXRecordDecl>(cast<RecordType>(CanDerivedType)->getDecl());
974 :
975 : const CXXRecordDecl *BaseDecl =
976 192: cast<CXXRecordDecl>(cast<RecordType>(CanBaseType)->getDecl());
977 :
978 192: return TypeConversionRequiresAdjustment(Ctx, DerivedDecl, BaseDecl);
979 : }
980 :
981 : bool VtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
982 : Index_t OverrideOffset, Index_t Offset,
983 3584: int64_t CurrentVBaseOffset) {
984 3584: const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
985 :
986 3584: const bool isPure = MD->isPure();
987 :
988 : // FIXME: Should OverrideOffset's be Offset?
989 :
856: branch 1 taken
2988: branch 2 taken
990 7428: for (CXXMethodDecl::method_iterator mi = MD->begin_overridden_methods(),
991 3584: e = MD->end_overridden_methods(); mi != e; ++mi) {
992 856: GlobalDecl OGD;
993 856: GlobalDecl OGD2;
994 :
995 856: const CXXMethodDecl *OMD = *mi;
46: branch 1 taken
810: branch 2 taken
996 856: if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(OMD))
997 46: OGD = GlobalDecl(DD, GD.getDtorType());
998 : else
999 810: OGD = OMD;
1000 :
1001 : // Check whether this is the method being overridden in this section of
1002 : // the vtable.
1003 : uint64_t Index;
596: branch 1 taken
260: branch 2 taken
1004 856: if (!Methods.getIndex(OGD, Index))
1005 260: continue;
1006 :
1007 596: OGD2 = OGD;
1008 :
1009 : // Get the original method, which we should be computing thunks, etc,
1010 : // against.
1011 596: OGD = Methods.getOrigMethod(Index);
1012 596: OMD = cast<CXXMethodDecl>(OGD.getDecl());
1013 :
1014 : QualType ReturnType =
1015 596: MD->getType()->getAs<FunctionType>()->getResultType();
1016 : QualType OverriddenReturnType =
1017 596: OMD->getType()->getAs<FunctionType>()->getResultType();
1018 :
1019 : // Check if we need a return type adjustment.
192: branch 2 taken
404: branch 3 taken
1020 596: if (TypeConversionRequiresAdjustment(CGM.getContext(), ReturnType,
1021 : OverriddenReturnType)) {
1022 192: CanQualType &BaseReturnType = BaseReturnTypes[Index];
1023 :
1024 : // Insert the base return type.
134: branch 1 taken
58: branch 2 taken
1025 192: if (BaseReturnType.isNull())
1026 : BaseReturnType =
1027 134: CGM.getContext().getCanonicalType(OverriddenReturnType);
1028 : }
1029 :
1030 596: Methods.OverrideMethod(OGD, GD);
1031 :
1032 596: GlobalDecl UGD = getUnique(GD);
1033 596: const CXXMethodDecl *UMD = cast<CXXMethodDecl>(UGD.getDecl());
596: branch 1 taken
0: branch 2 not taken
1034 596: assert(UGD.getDecl() && "unique overrider not found");
596: branch 2 taken
0: branch 3 not taken
1035 596: assert(UGD == getUnique(OGD) && "unique overrider not unique");
1036 :
1037 596: ThisAdjustments.erase(Index);
260: branch 0 taken
336: branch 1 taken
96: branch 3 taken
164: branch 4 taken
432: branch 5 taken
164: branch 6 taken
1038 856: if (MorallyVirtual || VCall.count(UMD)) {
1039 :
1040 432: Index_t &idx = VCall[UMD];
0: branch 0 not taken
432: branch 1 taken
1041 432: if (idx == 0) {
1042 0: VCallOffset[GD] = VCallOffset[OGD];
1043 : // NonVirtualOffset[UMD] = CurrentVBaseOffset/8 - OverrideOffset/8;
1044 0: NonVirtualOffset[UMD] = VCallOffset[OGD];
1045 0: VCallOffsetForVCall[UMD] = OverrideOffset/8;
1046 0: idx = VCalls.size()+1;
1047 0: VCalls.push_back(OverrideOffset/8 - CurrentVBaseOffset/8);
0: branch 1 not taken
0: branch 2 not taken
1048 0: D1(printf(" vcall for %s at %d with delta %d most derived %s\n",
1049 : MD->getNameAsString().c_str(), (int)-idx-3,
1050 : (int)VCalls[idx-1], MostDerivedClass->getNameAsCString()));
1051 : } else {
1052 432: VCallOffset[GD] = NonVirtualOffset[UMD];
1053 432: VCalls[idx-1] = -VCallOffsetForVCall[UGD] + OverrideOffset/8;
0: branch 1 not taken
432: branch 2 taken
1054 432: D1(printf(" vcall patch for %s at %d with delta %d most derived %s\n",
1055 : MD->getNameAsString().c_str(), (int)-idx-3,
1056 : (int)VCalls[idx-1], MostDerivedClass->getNameAsCString()));
1057 : }
1058 432: int64_t NonVirtualAdjustment = -VCallOffset[OGD];
1059 432: QualType DerivedType = MD->getThisType(CGM.getContext());
1060 432: QualType BaseType = cast<const CXXMethodDecl>(OGD.getDecl())->getThisType(CGM.getContext());
1061 432: int64_t NonVirtualAdjustment2 = -(getNVOffset(BaseType, DerivedType)/8);
0: branch 0 not taken
432: branch 1 taken
1062 432: if (NonVirtualAdjustment2 != NonVirtualAdjustment) {
1063 0: NonVirtualAdjustment = NonVirtualAdjustment2;
1064 : }
1065 : int64_t VirtualAdjustment =
1066 432: -((idx + extra + 2) * LLVMPointerWidth / 8);
1067 :
1068 : // Optimize out virtual adjustments of 0.
216: branch 1 taken
216: branch 2 taken
1069 432: if (VCalls[idx-1] == 0)
1070 216: VirtualAdjustment = 0;
1071 :
1072 : ThunkAdjustment ThisAdjustment(NonVirtualAdjustment,
1073 432: VirtualAdjustment);
1074 :
432: branch 0 taken
0: branch 1 not taken
245: branch 3 taken
187: branch 4 taken
245: branch 5 taken
187: branch 6 taken
1075 432: if (!isPure && !ThisAdjustment.isEmpty()) {
1076 245: ThisAdjustments[Index] = ThisAdjustment;
1077 : SavedAdjustments.push_back(
1078 245: std::make_pair(GD, std::make_pair(OGD, ThisAdjustment)));
1079 : }
1080 432: return true;
1081 : }
1082 :
1083 164: VCallOffset[GD] = VCallOffset[OGD2] - OverrideOffset/8;
1084 :
1085 164: int64_t NonVirtualAdjustment = -VCallOffset[GD];
1086 164: QualType DerivedType = MD->getThisType(CGM.getContext());
1087 164: QualType BaseType = cast<const CXXMethodDecl>(OGD.getDecl())->getThisType(CGM.getContext());
1088 164: int64_t NonVirtualAdjustment2 = -(getNVOffset(BaseType, DerivedType)/8);
0: branch 0 not taken
164: branch 1 taken
1089 164: if (NonVirtualAdjustment2 != NonVirtualAdjustment) {
1090 0: NonVirtualAdjustment = NonVirtualAdjustment2;
1091 : }
1092 :
20: branch 0 taken
144: branch 1 taken
1093 164: if (NonVirtualAdjustment) {
1094 20: ThunkAdjustment ThisAdjustment(NonVirtualAdjustment, 0);
1095 :
20: branch 0 taken
0: branch 1 not taken
1096 20: if (!isPure) {
1097 20: ThisAdjustments[Index] = ThisAdjustment;
1098 : SavedAdjustments.push_back(
1099 20: std::make_pair(GD, std::make_pair(OGD, ThisAdjustment)));
1100 : }
1101 : }
1102 164: return true;
1103 : }
1104 :
1105 2988: return false;
1106 : }
1107 :
1108 1125: void VtableBuilder::AppendMethodsToVtable() {
568: branch 0 taken
557: branch 1 taken
1109 1125: if (!BuildVtable) {
1110 : VtableComponents.insert(VtableComponents.end(), Methods.size(),
1111 568: (llvm::Constant *)0);
1112 568: ThisAdjustments.clear();
1113 568: BaseReturnTypes.clear();
1114 568: Methods.clear();
1115 568: return;
1116 : }
1117 :
1118 : // Reserve room in the vtable for our new methods.
1119 557: VtableComponents.reserve(VtableComponents.size() + Methods.size());
1120 :
1070: branch 1 taken
557: branch 2 taken
1121 1627: for (unsigned i = 0, e = Methods.size(); i != e; ++i) {
1122 1070: GlobalDecl GD = Methods[i];
1123 1070: const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
1124 :
1125 : // Get the 'this' pointer adjustment.
1126 1070: ThunkAdjustment ThisAdjustment = ThisAdjustments.lookup(i);
1127 :
1128 : // Construct the return type adjustment.
1129 1070: ThunkAdjustment ReturnAdjustment;
1130 :
1131 1070: QualType BaseReturnType = BaseReturnTypes.lookup(i);
58: branch 1 taken
1012: branch 2 taken
58: branch 4 taken
0: branch 5 not taken
58: branch 6 taken
1012: branch 7 taken
1132 1070: if (!BaseReturnType.isNull() && !MD->isPure()) {
1133 : QualType DerivedType =
1134 58: MD->getType()->getAs<FunctionType>()->getResultType();
1135 :
1136 : int64_t NonVirtualAdjustment =
1137 58: getNVOffset(BaseReturnType, DerivedType) / 8;
1138 :
1139 : int64_t VirtualAdjustment =
1140 58: getVbaseOffset(BaseReturnType, DerivedType);
1141 :
1142 : ReturnAdjustment = ThunkAdjustment(NonVirtualAdjustment,
1143 58: VirtualAdjustment);
1144 : }
1145 :
1146 1070: llvm::Constant *Method = 0;
58: branch 1 taken
1012: branch 2 taken
1147 1070: if (!ReturnAdjustment.isEmpty()) {
1148 : // Build a covariant thunk.
1149 58: CovariantThunkAdjustment Adjustment(ThisAdjustment, ReturnAdjustment);
1150 58: Method = wrap(CGM.GetAddrOfCovariantThunk(GD, Adjustment));
25: branch 1 taken
987: branch 2 taken
1151 1012: } else if (!ThisAdjustment.isEmpty()) {
1152 : // Build a "regular" thunk.
1153 25: Method = wrap(CGM.GetAddrOfThunk(GD, ThisAdjustment));
4: branch 1 taken
983: branch 2 taken
1154 987: } else if (MD->isPure()) {
1155 : // We have a pure virtual method.
1156 4: Method = getPureVirtualFn();
1157 : } else {
1158 : // We have a good old regular method.
1159 983: Method = WrapAddrOf(GD);
1160 : }
1161 :
1162 : // Add the method to the vtable.
1163 1070: VtableComponents.push_back(Method);
1164 : }
1165 :
1166 :
1167 557: ThisAdjustments.clear();
1168 557: BaseReturnTypes.clear();
1169 :
1170 557: Methods.clear();
1171 : }
1172 :
1173 21: void CGVtableInfo::ComputeMethodVtableIndices(const CXXRecordDecl *RD) {
1174 :
1175 : // Itanium C++ ABI 2.5.2:
1176 : // The order of the virtual function pointers in a virtual table is the
1177 : // order of declaration of the corresponding member functions in the class.
1178 : //
1179 : // There is an entry for any virtual function declared in a class,
1180 : // whether it is a new function or overrides a base class function,
1181 : // unless it overrides a function from the primary base, and conversion
1182 : // between their return types does not require an adjustment.
1183 :
1184 21: int64_t CurrentIndex = 0;
1185 :
1186 21: const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1187 21: const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1188 :
6: branch 0 taken
15: branch 1 taken
1189 21: if (PrimaryBase) {
1190 : assert(PrimaryBase->isDefinition() &&
6: branch 1 taken
0: branch 2 not taken
1191 6: "Should have the definition decl of the primary base!");
1192 :
1193 : // Since the record decl shares its vtable pointer with the primary base
1194 : // we need to start counting at the end of the primary base's vtable.
1195 6: CurrentIndex = getNumVirtualFunctionPointers(PrimaryBase);
1196 : }
1197 :
1198 : // Collect all the primary bases, so we can check whether methods override
1199 : // a method from the base.
1200 21: llvm::SmallPtrSet<const CXXRecordDecl *, 5> PrimaryBases;
7: branch 2 taken
21: branch 3 taken
1201 28: for (ASTRecordLayout::primary_base_info_iterator
1202 21: I = Layout.primary_base_begin(), E = Layout.primary_base_end();
1203 : I != E; ++I)
1204 7: PrimaryBases.insert((*I).getBase());
1205 :
1206 21: const CXXDestructorDecl *ImplicitVirtualDtor = 0;
1207 :
111: branch 3 taken
21: branch 4 taken
1208 153: for (CXXRecordDecl::method_iterator i = RD->method_begin(),
1209 21: e = RD->method_end(); i != e; ++i) {
1210 111: const CXXMethodDecl *MD = *i;
1211 :
1212 : // We only want virtual methods.
87: branch 1 taken
24: branch 2 taken
1213 111: if (!MD->isVirtual())
1214 87: continue;
1215 :
1216 24: bool ShouldAddEntryForMethod = true;
1217 :
1218 : // Check if this method overrides a method in the primary base.
4: branch 1 taken
20: branch 2 taken
1219 48: for (CXXMethodDecl::method_iterator i = MD->begin_overridden_methods(),
1220 24: e = MD->end_overridden_methods(); i != e; ++i) {
1221 4: const CXXMethodDecl *OverriddenMD = *i;
1222 4: const CXXRecordDecl *OverriddenRD = OverriddenMD->getParent();
1223 : assert(OverriddenMD->isCanonicalDecl() &&
4: branch 1 taken
0: branch 2 not taken
1224 4: "Should have the canonical decl of the overridden RD!");
1225 :
4: branch 1 taken
0: branch 2 not taken
1226 4: if (PrimaryBases.count(OverriddenRD)) {
1227 : // Check if converting from the return type of the method to the
1228 : // return type of the overridden method requires conversion.
1229 : QualType ReturnType =
1230 4: MD->getType()->getAs<FunctionType>()->getResultType();
1231 : QualType OverriddenReturnType =
1232 4: OverriddenMD->getType()->getAs<FunctionType>()->getResultType();
1233 :
4: branch 2 taken
0: branch 3 not taken
1234 4: if (!TypeConversionRequiresAdjustment(CGM.getContext(),
1235 : ReturnType, OverriddenReturnType)) {
1236 : // This index is shared between the index in the vtable of the primary
1237 : // base class.
0: branch 1 not taken
4: branch 2 taken
1238 4: if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1239 : const CXXDestructorDecl *OverriddenDD =
1240 0: cast<CXXDestructorDecl>(OverriddenMD);
1241 :
1242 : // Add both the complete and deleting entries.
1243 : MethodVtableIndices[GlobalDecl(DD, Dtor_Complete)] =
1244 0: getMethodVtableIndex(GlobalDecl(OverriddenDD, Dtor_Complete));
1245 : MethodVtableIndices[GlobalDecl(DD, Dtor_Deleting)] =
1246 0: getMethodVtableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting));
1247 : } else {
1248 4: MethodVtableIndices[MD] = getMethodVtableIndex(OverriddenMD);
1249 : }
1250 :
1251 : // We don't need to add an entry for this method.
1252 4: ShouldAddEntryForMethod = false;
1253 4: break;
1254 : }
1255 : }
1256 : }
1257 :
4: branch 0 taken
20: branch 1 taken
1258 24: if (!ShouldAddEntryForMethod)
1259 4: continue;
1260 :
1: branch 1 taken
19: branch 2 taken
1261 20: if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
0: branch 1 not taken
1: branch 2 taken
1262 1: if (MD->isImplicit()) {
1263 : assert(!ImplicitVirtualDtor &&
0: branch 0 not taken
0: branch 1 not taken
1264 0: "Did already see an implicit virtual dtor!");
1265 0: ImplicitVirtualDtor = DD;
1266 0: continue;
1267 : }
1268 :
1269 : // Add the complete dtor.
1270 1: MethodVtableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++;
1271 :
1272 : // Add the deleting dtor.
1273 1: MethodVtableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++;
1274 : } else {
1275 : // Add the entry.
1276 19: MethodVtableIndices[MD] = CurrentIndex++;
1277 : }
1278 : }
1279 :
0: branch 0 not taken
21: branch 1 taken
1280 21: if (ImplicitVirtualDtor) {
1281 : // Itanium C++ ABI 2.5.2:
1282 : // If a class has an implicitly-defined virtual destructor,
1283 : // its entries come after the declared virtual function pointers.
1284 :
1285 : // Add the complete dtor.
1286 : MethodVtableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Complete)] =
1287 0: CurrentIndex++;
1288 :
1289 : // Add the deleting dtor.
1290 : MethodVtableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Deleting)] =
1291 0: CurrentIndex++;
1292 : }
1293 :
1294 21: NumVirtualFunctionPointers[RD] = CurrentIndex;
1295 21: }
1296 :
1297 6: uint64_t CGVtableInfo::getNumVirtualFunctionPointers(const CXXRecordDecl *RD) {
1298 : llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
1299 6: NumVirtualFunctionPointers.find(RD);
3: branch 3 taken
3: branch 4 taken
1300 6: if (I != NumVirtualFunctionPointers.end())
1301 3: return I->second;
1302 :
1303 3: ComputeMethodVtableIndices(RD);
1304 :
1305 3: I = NumVirtualFunctionPointers.find(RD);
3: branch 3 taken
0: branch 4 not taken
1306 3: assert(I != NumVirtualFunctionPointers.end() && "Did not find entry!");
1307 3: return I->second;
1308 : }
1309 :
1310 37: uint64_t CGVtableInfo::getMethodVtableIndex(GlobalDecl GD) {
1311 37: MethodVtableIndicesTy::iterator I = MethodVtableIndices.find(GD);
19: branch 3 taken
18: branch 4 taken
1312 37: if (I != MethodVtableIndices.end())
1313 19: return I->second;
1314 :
1315 18: const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
1316 :
1317 18: ComputeMethodVtableIndices(RD);
1318 :
1319 18: I = MethodVtableIndices.find(GD);
18: branch 3 taken
0: branch 4 not taken
1320 18: assert(I != MethodVtableIndices.end() && "Did not find index!");
1321 18: return I->second;
1322 : }
1323 :
1324 : CGVtableInfo::AdjustmentVectorTy*
1325 943: CGVtableInfo::getAdjustments(GlobalDecl GD) {
1326 943: SavedAdjustmentsTy::iterator I = SavedAdjustments.find(GD);
125: branch 3 taken
818: branch 4 taken
1327 943: if (I != SavedAdjustments.end())
1328 125: return &I->second;
1329 :
1330 818: const CXXRecordDecl *RD = cast<CXXRecordDecl>(GD.getDecl()->getDeclContext());
659: branch 1 taken
159: branch 2 taken
1331 818: if (!SavedAdjustmentRecords.insert(RD).second)
1332 659: return 0;
1333 :
1334 159: AddressPointsMapTy AddressPoints;
1335 159: VtableBuilder b(RD, RD, 0, CGM, false, AddressPoints);
0: branch 1 not taken
159: branch 2 taken
1336 159: D1(printf("vtable %s\n", RD->getNameAsCString()));
1337 159: b.GenerateVtableForBase(RD);
1338 159: b.GenerateVtableForVBases(RD);
1339 :
77: branch 2 taken
159: branch 3 taken
1340 236: for (VtableBuilder::SavedAdjustmentsVectorTy::iterator
1341 159: i = b.getSavedAdjustments().begin(),
1342 159: e = b.getSavedAdjustments().end(); i != e; i++)
1343 77: SavedAdjustments[i->first].push_back(i->second);
1344 :
1345 159: I = SavedAdjustments.find(GD);
8: branch 3 taken
151: branch 4 taken
1346 159: if (I != SavedAdjustments.end())
1347 8: return &I->second;
1348 :
1349 151: return 0;
1350 : }
1351 :
1352 : int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
1353 255: const CXXRecordDecl *VBase) {
1354 255: ClassPairTy ClassPair(RD, VBase);
1355 :
1356 : VirtualBaseClassIndiciesTy::iterator I =
1357 255: VirtualBaseClassIndicies.find(ClassPair);
172: branch 3 taken
83: branch 4 taken
1358 255: if (I != VirtualBaseClassIndicies.end())
1359 172: return I->second;
1360 :
1361 : // FIXME: This seems expensive. Can we do a partial job to get
1362 : // just this data.
1363 83: AddressPointsMapTy AddressPoints;
1364 83: VtableBuilder b(RD, RD, 0, CGM, false, AddressPoints);
0: branch 1 not taken
83: branch 2 taken
1365 83: D1(printf("vtable %s\n", RD->getNameAsCString()));
1366 83: b.GenerateVtableForBase(RD);
1367 83: b.GenerateVtableForVBases(RD);
1368 :
256: branch 3 taken
83: branch 4 taken
1369 339: for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
1370 83: b.getVBIndex().begin(), E = b.getVBIndex().end(); I != E; ++I) {
1371 : // Insert all types.
1372 256: ClassPairTy ClassPair(RD, I->first);
1373 :
1374 256: VirtualBaseClassIndicies.insert(std::make_pair(ClassPair, I->second));
1375 : }
1376 :
1377 83: I = VirtualBaseClassIndicies.find(ClassPair);
83: branch 3 taken
0: branch 4 not taken
1378 83: assert(I != VirtualBaseClassIndicies.end() && "Did not find index!");
1379 :
1380 83: return I->second;
1381 : }
1382 :
1383 0: uint64_t CGVtableInfo::getVtableAddressPoint(const CXXRecordDecl *RD) {
1384 : uint64_t AddressPoint =
1385 0: (*(*(CGM.getVtableInfo().AddressPoints[RD]))[RD])[std::make_pair(RD, 0)];
1386 :
1387 0: return AddressPoint;
1388 : }
1389 :
1390 : llvm::GlobalVariable *
1391 : CGVtableInfo::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
1392 : bool GenerateDefinition,
1393 : const CXXRecordDecl *LayoutClass,
1394 : const CXXRecordDecl *RD, uint64_t Offset,
1395 410: AddressPointsMapTy& AddressPoints) {
1396 410: llvm::SmallString<256> OutName;
111: branch 0 taken
299: branch 1 taken
1397 410: if (LayoutClass != RD)
1398 : CGM.getMangleContext().mangleCXXCtorVtable(LayoutClass, Offset / 8,
1399 111: RD, OutName);
1400 : else
1401 299: CGM.getMangleContext().mangleCXXVtable(RD, OutName);
1402 410: llvm::StringRef Name = OutName.str();
1403 :
1404 410: llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
7: branch 0 taken
403: branch 1 taken
7: branch 4 taken
0: branch 5 not taken
7: branch 7 taken
0: branch 8 not taken
410: branch 9 taken
0: branch 10 not taken
1405 410: if (GV == 0 || CGM.getVtableInfo().AddressPoints[LayoutClass] == 0 ||
1406 : GV->isDeclaration()) {
1407 : VtableBuilder b(RD, LayoutClass, Offset, CGM, GenerateDefinition,
1408 410: AddressPoints);
1409 :
0: branch 1 not taken
410: branch 2 taken
1410 410: D1(printf("vtable %s\n", RD->getNameAsCString()));
1411 : // First comes the vtables for all the non-virtual bases...
1412 410: b.GenerateVtableForBase(RD, Offset);
1413 :
1414 : // then the vtables for all the virtual bases.
1415 410: b.GenerateVtableForVBases(RD, Offset);
1416 :
1417 410: llvm::Constant *Init = 0;
1418 410: const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
1419 : llvm::ArrayType *ArrayType =
1420 410: llvm::ArrayType::get(Int8PtrTy, b.getVtableComponents().size());
1421 :
322: branch 0 taken
88: branch 1 taken
1422 410: if (GenerateDefinition)
1423 : Init = llvm::ConstantArray::get(ArrayType, &b.getVtableComponents()[0],
1424 322: b.getVtableComponents().size());
1425 :
1426 410: llvm::GlobalVariable *OGV = GV;
1427 :
1428 : GV = new llvm::GlobalVariable(CGM.getModule(), ArrayType,
1429 410: /*isConstant=*/true, Linkage, Init, Name);
1430 410: CGM.setGlobalVisibility(GV, RD);
1431 :
7: branch 0 taken
403: branch 1 taken
1432 410: if (OGV) {
1433 7: GV->takeName(OGV);
1434 : llvm::Constant *NewPtr =
1435 7: llvm::ConstantExpr::getBitCast(GV, OGV->getType());
1436 7: OGV->replaceAllUsesWith(NewPtr);
1437 7: OGV->eraseFromParent();
1438 410: }
1439 : }
1440 :
1441 410: return GV;
1442 : }
1443 :
1444 : void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
1445 485: const CXXRecordDecl *RD) {
1446 485: llvm::GlobalVariable *&Vtable = Vtables[RD];
274: branch 0 taken
211: branch 1 taken
1447 485: if (Vtable) {
274: branch 1 taken
0: branch 2 not taken
1448 274: assert(Vtable->getInitializer() && "Vtable doesn't have a definition!");
1449 274: return;
1450 : }
1451 :
1452 211: AddressPointsMapTy AddressPoints;
1453 : Vtable = GenerateVtable(Linkage, /*GenerateDefinition=*/true, RD, RD, 0,
1454 211: AddressPoints);
1455 211: GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD);
1456 : }
1457 :
1458 434: llvm::GlobalVariable *CGVtableInfo::getVtable(const CXXRecordDecl *RD) {
1459 434: llvm::GlobalVariable *Vtable = Vtables.lookup(RD);
1460 :
88: branch 0 taken
346: branch 1 taken
1461 434: if (!Vtable) {
1462 88: AddressPointsMapTy AddressPoints;
1463 : Vtable = GenerateVtable(llvm::GlobalValue::ExternalLinkage,
1464 : /*GenerateDefinition=*/false, RD, RD, 0,
1465 88: AddressPoints);
1466 : }
1467 :
1468 434: return Vtable;
1469 : }
1470 :
1471 984: void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
1472 984: const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
1473 984: const CXXRecordDecl *RD = MD->getParent();
1474 :
1475 : // If the class doesn't have a vtable we don't need to emit one.
360: branch 1 taken
624: branch 2 taken
1476 984: if (!RD->isDynamicClass())
1477 360: return;
1478 :
1479 : // Get the key function.
1480 624: const CXXMethodDecl *KeyFunction = CGM.getContext().getKeyFunction(RD);
1481 :
197: branch 0 taken
427: branch 1 taken
1482 624: if (KeyFunction) {
1483 : // We don't have the right key function.
139: branch 2 taken
58: branch 3 taken
1484 197: if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl())
1485 139: return;
1486 : }
1487 :
1488 : // Emit the data.
1489 485: GenerateClassData(CGM.getVtableLinkage(RD), RD);
1490 :
3030: branch 3 taken
485: branch 4 taken
1491 4000: for (CXXRecordDecl::method_iterator i = RD->method_begin(),
1492 485: e = RD->method_end(); i != e; ++i) {
938: branch 2 taken
2092: branch 3 taken
102: branch 6 taken
836: branch 7 taken
15: branch 10 taken
87: branch 11 taken
851: branch 12 taken
2179: branch 13 taken
1493 3030: if ((*i)->isVirtual() && ((*i)->hasInlineBody() || (*i)->isImplicit())) {
34: branch 2 taken
817: branch 3 taken
1494 851: if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(*i)) {
1495 34: CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Complete));
1496 34: CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Deleting));
1497 : } else {
1498 817: CGM.BuildThunksForVirtual(GlobalDecl(*i));
1499 : }
1500 : }
1501 : }
1502 : }
1503 :
Generated: 2010-02-10 01:31 by zcov