blob: 1989d6c19b270dc562125cbd001e149e44f89dec [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
Anders Carlssonc1246c82010-03-26 00:35:45 +0000172 /// LayoutVTT - Will lay out the VTT for the given subobject, including any
173 /// secondary VTTs, secondary virtual pointers and virtual VTTs.
174 void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000175
Anders Carlssonc1246c82010-03-26 00:35:45 +0000176 /// LayoutSecondaryVTTs - Lay out the secondary VTTs of the given base
177 /// subobject.
178 void LayoutSecondaryVTTs(BaseSubobject Base);
179
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000180 /// VirtualVTTs - Add the VTT for each proper virtual base in inheritance
181 /// graph preorder.
182 void VirtualVTTs(const CXXRecordDecl *RD) {
183 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
184 e = RD->bases_end(); i != e; ++i) {
185 const CXXRecordDecl *Base =
186 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
187 if (i->isVirtual() && !SeenVBase.count(Base)) {
188 SeenVBase.insert(Base);
189 uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
Anders Carlssonc1246c82010-03-26 00:35:45 +0000190
191 LayoutVTT(BaseSubobject(Base, BaseOffset), /*BaseIsVirtual=*/true);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000192 }
193 VirtualVTTs(Base);
194 }
195 }
196
197public:
198 VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c,
199 CodeGenModule &cgm, bool GenerateDefinition)
200 : Inits(inits), Class(c), CGM(cgm),
201 BLayout(cgm.getContext().getASTRecordLayout(c)),
Anders Carlsson66d567d2010-03-25 00:51:13 +0000202 AddressPoints(*cgm.getVTables().OldAddressPoints[c]),
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000203 VMContext(cgm.getModule().getContext()),
204 GenerateDefinition(GenerateDefinition) {
205
206 // First comes the primary virtual table pointer for the complete class...
Anders Carlsson5eea8762010-03-24 05:32:05 +0000207 ClassVtbl = GenerateDefinition ? CGM.getVTables().GetAddrOfVTable(Class) :0;
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000208
209 llvm::Constant *Init = BuildVtablePtr(ClassVtbl, Class, Class, 0);
210 Inits.push_back(Init);
211
212 // then the secondary VTTs...
Anders Carlssonc1246c82010-03-26 00:35:45 +0000213 LayoutSecondaryVTTs(BaseSubobject(Class, 0));
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000214
215 // Make sure to clear the set of seen virtual bases.
216 SeenVBasesInSecondary.clear();
217
218 // then the secondary vtable pointers...
Anders Carlsson18222542010-03-26 00:11:51 +0000219 Secondary(Class, ClassVtbl, Class, 0, false);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000220
221 // and last, the virtual VTTs.
222 VirtualVTTs(Class);
223 }
224
225 llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getSubVTTIndicies() {
226 return SubVTTIndicies;
227 }
228};
Anders Carlssonc1246c82010-03-26 00:35:45 +0000229
230void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) {
231 const CXXRecordDecl *RD = Base.getBase();
232
233 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
234 E = RD->bases_end(); I != E; ++I) {
235
236 // Don't layout virtual bases.
237 if (I->isVirtual())
238 continue;
239
240 const CXXRecordDecl *BaseDecl =
241 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
242
243 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
244 uint64_t BaseOffset = Base.getBaseOffset() +
245 Layout.getBaseClassOffset(BaseDecl);
246
247 // Layout the VTT for this base.
248 LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false);
249 }
250}
251
252void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) {
253 const CXXRecordDecl *RD = Base.getBase();
254
255 // Itanium C++ ABI 2.6.2:
256 // An array of virtual table addresses, called the VTT, is declared for
257 // each class type that has indirect or direct virtual base classes.
258 if (RD->getNumVBases() == 0)
259 return;
260
261 // Remember the sub-VTT index.
262 SubVTTIndicies[RD] = Inits.size();
263
264 llvm::Constant *Vtable;
265 const CXXRecordDecl *VtableClass;
266
267 // First comes the primary virtual table pointer...
268 Vtable = getCtorVtable(Base, /*IsVirtual=*/BaseIsVirtual);
269 VtableClass = RD;
270
271 llvm::Constant *Init = BuildVtablePtr(Vtable, VtableClass, RD,
272 Base.getBaseOffset());
273 Inits.push_back(Init);
274
275 // then the secondary VTTs....
276 LayoutSecondaryVTTs(Base);
277
278 // Make sure to clear the set of seen virtual bases.
279 SeenVBasesInSecondary.clear();
280
281 // and last the secondary vtable pointers.
282 Secondary(RD, Vtable, VtableClass, Base.getBaseOffset(), false);
283}
284
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000285}
286
287llvm::GlobalVariable *
Anders Carlssonaf440352010-03-23 04:11:45 +0000288CodeGenVTables::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
289 bool GenerateDefinition,
290 const CXXRecordDecl *RD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000291 // Only classes that have virtual bases need a VTT.
292 if (RD->getNumVBases() == 0)
293 return 0;
294
295 llvm::SmallString<256> OutName;
296 CGM.getMangleContext().mangleCXXVTT(RD, OutName);
297 llvm::StringRef Name = OutName.str();
298
299 D1(printf("vtt %s\n", RD->getNameAsCString()));
300
301 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
302 if (GV == 0 || GV->isDeclaration()) {
303 const llvm::Type *Int8PtrTy =
304 llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
305
306 std::vector<llvm::Constant *> inits;
307 VTTBuilder b(inits, RD, CGM, GenerateDefinition);
308
309 const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size());
310 llvm::Constant *Init = 0;
311 if (GenerateDefinition)
312 Init = llvm::ConstantArray::get(Type, inits);
313
314 llvm::GlobalVariable *OldGV = GV;
315 GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true,
316 Linkage, Init, Name);
317 CGM.setGlobalVisibility(GV, RD);
318
319 if (OldGV) {
320 GV->takeName(OldGV);
321 llvm::Constant *NewPtr =
322 llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
323 OldGV->replaceAllUsesWith(NewPtr);
324 OldGV->eraseFromParent();
325 }
326 }
327
328 return GV;
329}
330
Anders Carlssonaf440352010-03-23 04:11:45 +0000331llvm::GlobalVariable *CodeGenVTables::getVTT(const CXXRecordDecl *RD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000332 return GenerateVTT(llvm::GlobalValue::ExternalLinkage,
333 /*GenerateDefinition=*/false, RD);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000334}
335
Anders Carlssonaf440352010-03-23 04:11:45 +0000336bool CodeGenVTables::needsVTTParameter(GlobalDecl GD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000337 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
338
339 // We don't have any virtual bases, just return early.
340 if (!MD->getParent()->getNumVBases())
341 return false;
342
343 // Check if we have a base constructor.
344 if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
345 return true;
346
347 // Check if we have a base destructor.
348 if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
349 return true;
350
351 return false;
352}
353
Anders Carlssonaf440352010-03-23 04:11:45 +0000354uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD,
355 const CXXRecordDecl *Base) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000356 ClassPairTy ClassPair(RD, Base);
357
358 SubVTTIndiciesTy::iterator I =
359 SubVTTIndicies.find(ClassPair);
360 if (I != SubVTTIndicies.end())
361 return I->second;
362
363 std::vector<llvm::Constant *> inits;
364 VTTBuilder Builder(inits, RD, CGM, /*GenerateDefinition=*/false);
365
366 for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
367 Builder.getSubVTTIndicies().begin(),
368 E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
369 // Insert all indices.
370 ClassPairTy ClassPair(RD, I->first);
371
372 SubVTTIndicies.insert(std::make_pair(ClassPair, I->second));
373 }
374
375 I = SubVTTIndicies.find(ClassPair);
376 assert(I != SubVTTIndicies.end() && "Did not find index!");
377
378 return I->second;
379}