 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
91.0% |
91 / 100 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
100.0% |
100 / 100 |
| |
|
Line Coverage: |
92.5% |
148 / 160 |
| |
 |
|
 |
1 : //===--- CGVTT.cpp - Emit LLVM Code for C++ VTTs --------------------------===//
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 VTTs (vtable tables).
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "CodeGenModule.h"
15 : #include "clang/AST/RecordLayout.h"
16 : using namespace clang;
17 : using namespace CodeGen;
18 :
19 : #define D1(x)
20 :
21 : namespace {
22 134: class VTTBuilder {
23 : /// Inits - The list of values built for the VTT.
24 : std::vector<llvm::Constant *> &Inits;
25 : /// Class - The most derived class that this vtable is being built for.
26 : const CXXRecordDecl *Class;
27 : CodeGenModule &CGM; // Per-module state.
28 : llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase;
29 : /// BLayout - Layout for the most derived class that this vtable is being
30 : /// built for.
31 : const ASTRecordLayout &BLayout;
32 : CGVtableInfo::AddrMap_t &AddressPoints;
33 : // vtbl - A pointer to the vtable for Class.
34 : llvm::Constant *ClassVtbl;
35 : llvm::LLVMContext &VMContext;
36 :
37 : /// SeenVBasesInSecondary - The seen virtual bases when building the
38 : /// secondary virtual pointers.
39 : llvm::SmallPtrSet<const CXXRecordDecl *, 32> SeenVBasesInSecondary;
40 :
41 : llvm::DenseMap<const CXXRecordDecl *, uint64_t> SubVTTIndicies;
42 :
43 : bool GenerateDefinition;
44 :
45 : llvm::DenseMap<BaseSubobject, llvm::Constant *> CtorVtables;
46 : llvm::DenseMap<std::pair<const CXXRecordDecl *, BaseSubobject>, uint64_t>
47 : CtorVtableAddressPoints;
48 :
49 209: llvm::Constant *getCtorVtable(const BaseSubobject &Base) {
98: branch 0 taken
111: branch 1 taken
50 209: if (!GenerateDefinition)
51 98: return 0;
52 :
53 111: llvm::Constant *&CtorVtable = CtorVtables[Base];
111: branch 0 taken
0: branch 1 not taken
54 111: if (!CtorVtable) {
55 : // Build the vtable.
56 : CGVtableInfo::CtorVtableInfo Info
57 111: = CGM.getVtableInfo().getCtorVtable(Class, Base);
58 :
59 111: CtorVtable = Info.Vtable;
60 :
61 : // Add the address points for this base.
275: branch 2 taken
111: branch 3 taken
62 386: for (CGVtableInfo::AddressPointsMapTy::const_iterator I =
63 111: Info.AddressPoints.begin(), E = Info.AddressPoints.end();
64 : I != E; ++I) {
65 : uint64_t &AddressPoint =
66 275: CtorVtableAddressPoints[std::make_pair(Base.getBase(), I->first)];
67 :
68 : // Check if we already have the address points for this base.
0: branch 0 not taken
275: branch 1 taken
69 275: if (AddressPoint)
70 0: break;
71 :
72 : // Otherwise, insert it.
73 275: AddressPoint = I->second;
74 111: }
75 : }
76 :
77 111: return CtorVtable;
78 : }
79 :
80 :
81 : /// BuildVtablePtr - Build up a referene to the given secondary vtable
82 : llvm::Constant *BuildVtablePtr(llvm::Constant *Vtable,
83 : const CXXRecordDecl *VtableClass,
84 : const CXXRecordDecl *RD,
85 914: uint64_t Offset) {
396: branch 0 taken
518: branch 1 taken
86 914: if (!GenerateDefinition)
87 396: return 0;
88 :
89 : uint64_t AddressPoint;
90 :
241: branch 0 taken
277: branch 1 taken
91 518: if (VtableClass != Class) {
92 : // We have a ctor vtable, look for the address point in the ctor vtable
93 : // address points.
94 : AddressPoint =
95 : CtorVtableAddressPoints[std::make_pair(VtableClass,
96 241: BaseSubobject(RD, Offset))];
97 : } else {
98 : AddressPoint =
99 277: (*AddressPoints[VtableClass])[std::make_pair(RD, Offset)];
100 : }
101 :
102 : // FIXME: We can never have 0 address point. Do this for now so gepping
103 : // retains the same structure. Later we'll just assert.
0: branch 0 not taken
518: branch 1 taken
104 518: if (AddressPoint == 0)
105 0: AddressPoint = 1;
106 : D1(printf("XXX address point for %s in %s layout %s at offset %d was %d\n",
107 : RD->getNameAsCString(), VtblClass->getNameAsCString(),
108 : Class->getNameAsCString(), (int)Offset, (int)AddressPoint));
109 :
110 : llvm::Value *Idxs[] = {
111 : llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 0),
112 : llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), AddressPoint)
113 518: };
114 :
115 : llvm::Constant *Init =
116 518: llvm::ConstantExpr::getInBoundsGetElementPtr(Vtable, Idxs, 2);
117 :
118 518: const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
119 518: return llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
120 : }
121 :
122 : /// Secondary - Add the secondary vtable pointers to Inits. Offset is the
123 : /// current offset in bits to the object we're working on.
124 : void Secondary(const CXXRecordDecl *RD, llvm::Constant *vtbl,
125 : const CXXRecordDecl *VtblClass, uint64_t Offset=0,
126 1128: bool MorallyVirtual=false) {
467: branch 1 taken
661: branch 2 taken
74: branch 3 taken
393: branch 4 taken
74: branch 5 taken
1054: branch 6 taken
127 1128: if (RD->getNumVBases() == 0 && ! MorallyVirtual)
128 74: return;
129 :
1102: branch 1 taken
1054: branch 2 taken
130 3210: for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
131 1054: e = RD->bases_end(); i != e; ++i) {
132 : const CXXRecordDecl *Base =
133 1102: cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
134 :
135 : // We only want to visit each virtual base once.
771: branch 1 taken
331: branch 2 taken
4: branch 4 taken
767: branch 5 taken
4: branch 6 taken
1098: branch 7 taken
136 1102: if (i->isVirtual() && SeenVBasesInSecondary.count(Base))
137 4: continue;
138 :
139 : // Itanium C++ ABI 2.6.2:
140 : // Secondary virtual pointers are present for all bases with either
141 : // virtual bases or virtual function declarations overridden along a
142 : // virtual path.
143 : //
144 : // If the base class is not dynamic, we don't want to add it, nor any
145 : // of its base classes.
313: branch 1 taken
785: branch 2 taken
146 1098: if (!Base->isDynamicClass())
147 313: continue;
148 :
149 785: const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
150 785: const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
151 785: const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
152 : bool NonVirtualPrimaryBase;
562: branch 0 taken
223: branch 1 taken
192: branch 2 taken
370: branch 3 taken
153 785: NonVirtualPrimaryBase = !PrimaryBaseWasVirtual && Base == PrimaryBase;
154 785: bool BaseMorallyVirtual = MorallyVirtual | i->isVirtual();
155 : uint64_t BaseOffset;
260: branch 1 taken
525: branch 2 taken
156 785: if (!i->isVirtual()) {
157 260: const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
158 260: BaseOffset = Offset + Layout.getBaseClassOffset(Base);
159 : } else
160 525: BaseOffset = BLayout.getVBaseClassOffset(Base);
161 785: llvm::Constant *subvtbl = vtbl;
162 785: const CXXRecordDecl *subVtblClass = VtblClass;
467: branch 1 taken
318: branch 2 taken
393: branch 3 taken
74: branch 4 taken
571: branch 5 taken
140: branch 6 taken
571: branch 7 taken
214: branch 8 taken
163 785: if ((Base->getNumVBases() || BaseMorallyVirtual)
164 : && !NonVirtualPrimaryBase) {
165 : llvm::Constant *init;
22: branch 0 taken
549: branch 1 taken
22: branch 2 taken
0: branch 3 not taken
166 1142: if (BaseMorallyVirtual || VtblClass == Class)
167 571: init = BuildVtablePtr(vtbl, VtblClass, Base, BaseOffset);
168 : else {
169 0: init = getCtorVtable(BaseSubobject(Base, BaseOffset));
170 :
171 0: subvtbl = init;
172 0: subVtblClass = Base;
173 :
174 0: init = BuildVtablePtr(init, Class, Base, BaseOffset);
175 : }
176 :
177 571: Inits.push_back(init);
178 : }
179 :
525: branch 1 taken
260: branch 2 taken
180 785: if (i->isVirtual())
181 525: SeenVBasesInSecondary.insert(Base);
182 :
183 785: Secondary(Base, subvtbl, subVtblClass, BaseOffset, BaseMorallyVirtual);
184 : }
185 : }
186 :
187 : /// BuiltVTT - Add the VTT to Inits. Offset is the offset in bits to the
188 : /// currnet object we're working on.
189 531: void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool MorallyVirtual) {
190 : // Itanium C++ ABI 2.6.2:
191 : // An array of virtual table addresses, called the VTT, is declared for
192 : // each class type that has indirect or direct virtual base classes.
322: branch 1 taken
209: branch 2 taken
193 531: if (RD->getNumVBases() == 0)
194 322: return;
195 :
196 : // Remember the sub-VTT index.
197 209: SubVTTIndicies[RD] = Inits.size();
198 :
199 : llvm::Constant *Vtable;
200 : const CXXRecordDecl *VtableClass;
201 :
202 : // First comes the primary virtual table pointer...
0: branch 0 not taken
209: branch 1 taken
203 209: if (MorallyVirtual) {
204 0: Vtable = ClassVtbl;
205 0: VtableClass = Class;
206 : } else {
207 209: Vtable = getCtorVtable(BaseSubobject(RD, Offset));
208 209: VtableClass = RD;
209 : }
210 :
211 209: llvm::Constant *Init = BuildVtablePtr(Vtable, VtableClass, RD, Offset);
212 209: Inits.push_back(Init);
213 :
214 : // then the secondary VTTs....
215 209: SecondaryVTTs(RD, Offset, MorallyVirtual);
216 :
217 : // Make sure to clear the set of seen virtual bases.
218 209: SeenVBasesInSecondary.clear();
219 :
220 : // and last the secondary vtable pointers.
221 209: Secondary(RD, Vtable, VtableClass, Offset, MorallyVirtual);
222 : }
223 :
224 : /// SecondaryVTTs - Add the secondary VTTs to Inits. The secondary VTTs are
225 : /// built from each direct non-virtual proper base that requires a VTT in
226 : /// declaration order.
227 : void SecondaryVTTs(const CXXRecordDecl *RD, uint64_t Offset=0,
228 343: bool MorallyVirtual=false) {
561: branch 1 taken
343: branch 2 taken
229 1247: for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
230 343: e = RD->bases_end(); i != e; ++i) {
231 : const CXXRecordDecl *Base =
232 561: cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
385: branch 1 taken
176: branch 2 taken
233 561: if (i->isVirtual())
234 385: continue;
235 176: const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
236 176: uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base);
237 :
238 176: BuildVTT(Base, BaseOffset, MorallyVirtual);
239 : }
240 343: }
241 :
242 : /// VirtualVTTs - Add the VTT for each proper virtual base in inheritance
243 : /// graph preorder.
244 742: void VirtualVTTs(const CXXRecordDecl *RD) {
608: branch 1 taken
742: branch 2 taken
245 2092: for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
246 742: e = RD->bases_end(); i != e; ++i) {
247 : const CXXRecordDecl *Base =
248 608: cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
387: branch 1 taken
221: branch 2 taken
355: branch 4 taken
32: branch 5 taken
355: branch 6 taken
253: branch 7 taken
249 608: if (i->isVirtual() && !SeenVBase.count(Base)) {
250 355: SeenVBase.insert(Base);
251 355: uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
252 355: BuildVTT(Base, BaseOffset, false);
253 : }
254 608: VirtualVTTs(Base);
255 : }
256 742: }
257 :
258 : public:
259 : VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c,
260 134: CodeGenModule &cgm, bool GenerateDefinition)
261 : : Inits(inits), Class(c), CGM(cgm),
262 : BLayout(cgm.getContext().getASTRecordLayout(c)),
263 : AddressPoints(*cgm.getVtableInfo().AddressPoints[c]),
264 : VMContext(cgm.getModule().getContext()),
265 134: GenerateDefinition(GenerateDefinition) {
266 :
267 : // First comes the primary virtual table pointer for the complete class...
92: branch 0 taken
42: branch 1 taken
268 134: ClassVtbl = GenerateDefinition ? CGM.getVtableInfo().getVtable(Class) : 0;
269 :
270 134: llvm::Constant *Init = BuildVtablePtr(ClassVtbl, Class, Class, 0);
271 134: Inits.push_back(Init);
272 :
273 : // then the secondary VTTs...
274 134: SecondaryVTTs(Class);
275 :
276 : // Make sure to clear the set of seen virtual bases.
277 134: SeenVBasesInSecondary.clear();
278 :
279 : // then the secondary vtable pointers...
280 134: Secondary(Class, ClassVtbl, Class);
281 :
282 : // and last, the virtual VTTs.
283 134: VirtualVTTs(Class);
284 134: }
285 :
286 84: llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getSubVTTIndicies() {
287 84: return SubVTTIndicies;
288 : }
289 : };
290 : }
291 :
292 : llvm::GlobalVariable *
293 : CGVtableInfo::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
294 : bool GenerateDefinition,
295 287: const CXXRecordDecl *RD) {
296 : // Only classes that have virtual bases need a VTT.
119: branch 1 taken
168: branch 2 taken
297 287: if (RD->getNumVBases() == 0)
298 119: return 0;
299 :
300 168: llvm::SmallString<256> OutName;
301 168: CGM.getMangleContext().mangleCXXVTT(RD, OutName);
302 168: llvm::StringRef Name = OutName.str();
303 :
304 : D1(printf("vtt %s\n", RD->getNameAsCString()));
305 :
306 168: llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
76: branch 0 taken
92: branch 1 taken
0: branch 3 not taken
76: branch 4 taken
92: branch 5 taken
76: branch 6 taken
307 168: if (GV == 0 || GV->isDeclaration()) {
308 : const llvm::Type *Int8PtrTy =
309 92: llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
310 :
311 92: std::vector<llvm::Constant *> inits;
312 92: VTTBuilder b(inits, RD, CGM, GenerateDefinition);
313 :
314 92: const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size());
315 92: llvm::Constant *Init = 0;
92: branch 0 taken
0: branch 1 not taken
316 92: if (GenerateDefinition)
317 92: Init = llvm::ConstantArray::get(Type, inits);
318 :
319 92: llvm::GlobalVariable *OldGV = GV;
320 : GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true,
321 92: Linkage, Init, Name);
322 92: CGM.setGlobalVisibility(GV, RD);
323 :
0: branch 0 not taken
92: branch 1 taken
324 92: if (OldGV) {
325 0: GV->takeName(OldGV);
326 : llvm::Constant *NewPtr =
327 0: llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
328 0: OldGV->replaceAllUsesWith(NewPtr);
329 0: OldGV->eraseFromParent();
330 92: }
331 : }
332 :
333 168: return GV;
334 : }
335 :
336 : CGVtableInfo::CtorVtableInfo
337 : CGVtableInfo::getCtorVtable(const CXXRecordDecl *RD,
338 111: const BaseSubobject &Base) {
339 111: CtorVtableInfo Info;
340 :
341 : Info.Vtable = GenerateVtable(llvm::GlobalValue::InternalLinkage,
342 : /*GenerateDefinition=*/true,
343 : RD, Base.getBase(), Base.getBaseOffset(),
344 111: Info.AddressPoints);
345 : return Info;
346 : }
347 :
348 76: llvm::GlobalVariable *CGVtableInfo::getVTT(const CXXRecordDecl *RD) {
349 : return GenerateVTT(llvm::GlobalValue::ExternalLinkage,
350 76: /*GenerateDefinition=*/false, RD);
351 :
352 : }
353 :
354 :
355 1955: bool CGVtableInfo::needsVTTParameter(GlobalDecl GD) {
356 1955: const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
357 :
358 : // We don't have any virtual bases, just return early.
1499: branch 2 taken
456: branch 3 taken
359 1955: if (!MD->getParent()->getNumVBases())
360 1499: return false;
361 :
362 : // Check if we have a base constructor.
336: branch 1 taken
120: branch 2 taken
174: branch 4 taken
162: branch 5 taken
174: branch 6 taken
282: branch 7 taken
363 456: if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
364 174: return true;
365 :
366 : // Check if we have a base destructor.
9: branch 1 taken
273: branch 2 taken
3: branch 4 taken
6: branch 5 taken
3: branch 6 taken
279: branch 7 taken
367 282: if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
368 3: return true;
369 :
370 279: return false;
371 : }
372 :
373 : uint64_t CGVtableInfo::getSubVTTIndex(const CXXRecordDecl *RD,
374 84: const CXXRecordDecl *Base) {
375 84: ClassPairTy ClassPair(RD, Base);
376 :
377 : SubVTTIndiciesTy::iterator I =
378 84: SubVTTIndicies.find(ClassPair);
42: branch 3 taken
42: branch 4 taken
379 84: if (I != SubVTTIndicies.end())
380 42: return I->second;
381 :
382 42: std::vector<llvm::Constant *> inits;
383 42: VTTBuilder Builder(inits, RD, CGM, /*GenerateDefinition=*/false);
384 :
98: branch 3 taken
42: branch 4 taken
385 140: for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
386 42: Builder.getSubVTTIndicies().begin(),
387 42: E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
388 : // Insert all indices.
389 98: ClassPairTy ClassPair(RD, I->first);
390 :
391 98: SubVTTIndicies.insert(std::make_pair(ClassPair, I->second));
392 : }
393 :
394 42: I = SubVTTIndicies.find(ClassPair);
42: branch 3 taken
0: branch 4 not taken
395 42: assert(I != SubVTTIndicies.end() && "Did not find index!");
396 :
397 42: return I->second;
398 : }
Generated: 2010-02-10 01:31 by zcov