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