blob: e820bef0837a94ce4cc3d997392e9519cf4e42d8 [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;
Anders Carlssonaf440352010-03-23 04:11:45 +000032 CodeGenVTables::AddrMap_t &AddressPoints;
Anders Carlsson58b7eee2010-01-21 16:50:45 +000033 // 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) {
Anders Carlssonff143f82010-03-25 00:35:49 +000056 // Get the vtable.
57 CtorVtable =
58 CGM.getVTables().GenerateConstructionVTable(Class, Base, BaseIsVirtual,
59 CtorVtableAddressPoints);
Anders Carlsson58b7eee2010-01-21 16:50:45 +000060 }
61
62 return CtorVtable;
63 }
64
65
66 /// BuildVtablePtr - Build up a referene to the given secondary vtable
67 llvm::Constant *BuildVtablePtr(llvm::Constant *Vtable,
68 const CXXRecordDecl *VtableClass,
69 const CXXRecordDecl *RD,
70 uint64_t Offset) {
71 if (!GenerateDefinition)
72 return 0;
73
74 uint64_t AddressPoint;
75
76 if (VtableClass != Class) {
77 // We have a ctor vtable, look for the address point in the ctor vtable
78 // address points.
79 AddressPoint =
80 CtorVtableAddressPoints[std::make_pair(VtableClass,
81 BaseSubobject(RD, Offset))];
82 } else {
83 AddressPoint =
84 (*AddressPoints[VtableClass])[std::make_pair(RD, Offset)];
85 }
86
87 // FIXME: We can never have 0 address point. Do this for now so gepping
88 // retains the same structure. Later we'll just assert.
89 if (AddressPoint == 0)
90 AddressPoint = 1;
91 D1(printf("XXX address point for %s in %s layout %s at offset %d was %d\n",
92 RD->getNameAsCString(), VtblClass->getNameAsCString(),
93 Class->getNameAsCString(), (int)Offset, (int)AddressPoint));
94
95 llvm::Value *Idxs[] = {
96 llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 0),
97 llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), AddressPoint)
98 };
99
100 llvm::Constant *Init =
101 llvm::ConstantExpr::getInBoundsGetElementPtr(Vtable, Idxs, 2);
102
103 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
104 return llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
105 }
106
107 /// Secondary - Add the secondary vtable pointers to Inits. Offset is the
108 /// current offset in bits to the object we're working on.
109 void Secondary(const CXXRecordDecl *RD, llvm::Constant *vtbl,
Anders Carlsson18222542010-03-26 00:11:51 +0000110 const CXXRecordDecl *VtblClass, uint64_t Offset,
111 bool MorallyVirtual) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000112 if (RD->getNumVBases() == 0 && ! MorallyVirtual)
113 return;
114
115 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
116 e = RD->bases_end(); i != e; ++i) {
117 const CXXRecordDecl *Base =
118 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
119
120 // We only want to visit each virtual base once.
121 if (i->isVirtual() && SeenVBasesInSecondary.count(Base))
122 continue;
123
124 // Itanium C++ ABI 2.6.2:
125 // Secondary virtual pointers are present for all bases with either
126 // virtual bases or virtual function declarations overridden along a
127 // virtual path.
128 //
129 // If the base class is not dynamic, we don't want to add it, nor any
130 // of its base classes.
131 if (!Base->isDynamicClass())
132 continue;
133
134 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
135 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
136 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
137 bool NonVirtualPrimaryBase;
138 NonVirtualPrimaryBase = !PrimaryBaseWasVirtual && Base == PrimaryBase;
139 bool BaseMorallyVirtual = MorallyVirtual | i->isVirtual();
140 uint64_t BaseOffset;
141 if (!i->isVirtual()) {
142 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
143 BaseOffset = Offset + Layout.getBaseClassOffset(Base);
144 } else
145 BaseOffset = BLayout.getVBaseClassOffset(Base);
146 llvm::Constant *subvtbl = vtbl;
147 const CXXRecordDecl *subVtblClass = VtblClass;
148 if ((Base->getNumVBases() || BaseMorallyVirtual)
149 && !NonVirtualPrimaryBase) {
150 llvm::Constant *init;
151 if (BaseMorallyVirtual || VtblClass == Class)
152 init = BuildVtablePtr(vtbl, VtblClass, Base, BaseOffset);
153 else {
Anders Carlsson5d7af6b2010-02-28 00:36:23 +0000154 init = getCtorVtable(BaseSubobject(Base, BaseOffset), i->isVirtual());
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000155
156 subvtbl = init;
157 subVtblClass = Base;
158
159 init = BuildVtablePtr(init, Class, Base, BaseOffset);
160 }
161
162 Inits.push_back(init);
163 }
164
165 if (i->isVirtual())
166 SeenVBasesInSecondary.insert(Base);
167
168 Secondary(Base, subvtbl, subVtblClass, BaseOffset, BaseMorallyVirtual);
169 }
170 }
171
172 /// BuiltVTT - Add the VTT to Inits. Offset is the offset in bits to the
173 /// currnet object we're working on.
Anders Carlsson18222542010-03-26 00:11:51 +0000174 void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool BaseIsVirtual) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000175 // Itanium C++ ABI 2.6.2:
176 // An array of virtual table addresses, called the VTT, is declared for
177 // each class type that has indirect or direct virtual base classes.
178 if (RD->getNumVBases() == 0)
179 return;
180
181 // Remember the sub-VTT index.
182 SubVTTIndicies[RD] = Inits.size();
183
184 llvm::Constant *Vtable;
185 const CXXRecordDecl *VtableClass;
186
187 // First comes the primary virtual table pointer...
Anders Carlsson18222542010-03-26 00:11:51 +0000188 Vtable = getCtorVtable(BaseSubobject(RD, Offset),
189 /*IsVirtual=*/BaseIsVirtual);
190 VtableClass = RD;
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000191
192 llvm::Constant *Init = BuildVtablePtr(Vtable, VtableClass, RD, Offset);
193 Inits.push_back(Init);
194
195 // then the secondary VTTs....
Anders Carlsson18222542010-03-26 00:11:51 +0000196 SecondaryVTTs(RD, Offset);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000197
198 // Make sure to clear the set of seen virtual bases.
199 SeenVBasesInSecondary.clear();
200
201 // and last the secondary vtable pointers.
Anders Carlsson18222542010-03-26 00:11:51 +0000202 Secondary(RD, Vtable, VtableClass, Offset, false);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000203 }
204
205 /// SecondaryVTTs - Add the secondary VTTs to Inits. The secondary VTTs are
206 /// built from each direct non-virtual proper base that requires a VTT in
207 /// declaration order.
Anders Carlsson18222542010-03-26 00:11:51 +0000208 void SecondaryVTTs(const CXXRecordDecl *RD, uint64_t Offset) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000209 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
210 e = RD->bases_end(); i != e; ++i) {
211 const CXXRecordDecl *Base =
212 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
213 if (i->isVirtual())
214 continue;
215 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
216 uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base);
217
Anders Carlsson18222542010-03-26 00:11:51 +0000218 BuildVTT(Base, BaseOffset, /*BaseIsVirtual=*/false);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000219 }
220 }
221
222 /// VirtualVTTs - Add the VTT for each proper virtual base in inheritance
223 /// graph preorder.
224 void VirtualVTTs(const CXXRecordDecl *RD) {
225 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
226 e = RD->bases_end(); i != e; ++i) {
227 const CXXRecordDecl *Base =
228 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
229 if (i->isVirtual() && !SeenVBase.count(Base)) {
230 SeenVBase.insert(Base);
231 uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
Anders Carlsson18222542010-03-26 00:11:51 +0000232 BuildVTT(Base, BaseOffset, /*BaseIsVirtual=*/true);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000233 }
234 VirtualVTTs(Base);
235 }
236 }
237
238public:
239 VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c,
240 CodeGenModule &cgm, bool GenerateDefinition)
241 : Inits(inits), Class(c), CGM(cgm),
242 BLayout(cgm.getContext().getASTRecordLayout(c)),
Anders Carlsson66d567d2010-03-25 00:51:13 +0000243 AddressPoints(*cgm.getVTables().OldAddressPoints[c]),
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000244 VMContext(cgm.getModule().getContext()),
245 GenerateDefinition(GenerateDefinition) {
246
247 // First comes the primary virtual table pointer for the complete class...
Anders Carlsson5eea8762010-03-24 05:32:05 +0000248 ClassVtbl = GenerateDefinition ? CGM.getVTables().GetAddrOfVTable(Class) :0;
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000249
250 llvm::Constant *Init = BuildVtablePtr(ClassVtbl, Class, Class, 0);
251 Inits.push_back(Init);
252
253 // then the secondary VTTs...
Anders Carlsson18222542010-03-26 00:11:51 +0000254 SecondaryVTTs(Class, 0);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000255
256 // Make sure to clear the set of seen virtual bases.
257 SeenVBasesInSecondary.clear();
258
259 // then the secondary vtable pointers...
Anders Carlsson18222542010-03-26 00:11:51 +0000260 Secondary(Class, ClassVtbl, Class, 0, false);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000261
262 // and last, the virtual VTTs.
263 VirtualVTTs(Class);
264 }
265
266 llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getSubVTTIndicies() {
267 return SubVTTIndicies;
268 }
269};
270}
271
272llvm::GlobalVariable *
Anders Carlssonaf440352010-03-23 04:11:45 +0000273CodeGenVTables::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
274 bool GenerateDefinition,
275 const CXXRecordDecl *RD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000276 // Only classes that have virtual bases need a VTT.
277 if (RD->getNumVBases() == 0)
278 return 0;
279
280 llvm::SmallString<256> OutName;
281 CGM.getMangleContext().mangleCXXVTT(RD, OutName);
282 llvm::StringRef Name = OutName.str();
283
284 D1(printf("vtt %s\n", RD->getNameAsCString()));
285
286 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
287 if (GV == 0 || GV->isDeclaration()) {
288 const llvm::Type *Int8PtrTy =
289 llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
290
291 std::vector<llvm::Constant *> inits;
292 VTTBuilder b(inits, RD, CGM, GenerateDefinition);
293
294 const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size());
295 llvm::Constant *Init = 0;
296 if (GenerateDefinition)
297 Init = llvm::ConstantArray::get(Type, inits);
298
299 llvm::GlobalVariable *OldGV = GV;
300 GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true,
301 Linkage, Init, Name);
302 CGM.setGlobalVisibility(GV, RD);
303
304 if (OldGV) {
305 GV->takeName(OldGV);
306 llvm::Constant *NewPtr =
307 llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
308 OldGV->replaceAllUsesWith(NewPtr);
309 OldGV->eraseFromParent();
310 }
311 }
312
313 return GV;
314}
315
Anders Carlssonaf440352010-03-23 04:11:45 +0000316llvm::GlobalVariable *CodeGenVTables::getVTT(const CXXRecordDecl *RD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000317 return GenerateVTT(llvm::GlobalValue::ExternalLinkage,
318 /*GenerateDefinition=*/false, RD);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000319}
320
Anders Carlssonaf440352010-03-23 04:11:45 +0000321bool CodeGenVTables::needsVTTParameter(GlobalDecl GD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000322 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
323
324 // We don't have any virtual bases, just return early.
325 if (!MD->getParent()->getNumVBases())
326 return false;
327
328 // Check if we have a base constructor.
329 if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
330 return true;
331
332 // Check if we have a base destructor.
333 if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
334 return true;
335
336 return false;
337}
338
Anders Carlssonaf440352010-03-23 04:11:45 +0000339uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD,
340 const CXXRecordDecl *Base) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000341 ClassPairTy ClassPair(RD, Base);
342
343 SubVTTIndiciesTy::iterator I =
344 SubVTTIndicies.find(ClassPair);
345 if (I != SubVTTIndicies.end())
346 return I->second;
347
348 std::vector<llvm::Constant *> inits;
349 VTTBuilder Builder(inits, RD, CGM, /*GenerateDefinition=*/false);
350
351 for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
352 Builder.getSubVTTIndicies().begin(),
353 E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
354 // Insert all indices.
355 ClassPairTy ClassPair(RD, I->first);
356
357 SubVTTIndicies.insert(std::make_pair(ClassPair, I->second));
358 }
359
360 I = SubVTTIndicies.find(ClassPair);
361 assert(I != SubVTTIndicies.end() && "Did not find index!");
362
363 return I->second;
364}