blob: 09cb5a88b757857dac05c8c18b3283f924d3665e [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
Anders Carlsson9f17d412010-03-26 00:50:17 +000037 typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
38
Anders Carlsson58b7eee2010-01-21 16:50:45 +000039 /// SeenVBasesInSecondary - The seen virtual bases when building the
40 /// secondary virtual pointers.
41 llvm::SmallPtrSet<const CXXRecordDecl *, 32> SeenVBasesInSecondary;
42
43 llvm::DenseMap<const CXXRecordDecl *, uint64_t> SubVTTIndicies;
44
45 bool GenerateDefinition;
46
47 llvm::DenseMap<BaseSubobject, llvm::Constant *> CtorVtables;
48 llvm::DenseMap<std::pair<const CXXRecordDecl *, BaseSubobject>, uint64_t>
49 CtorVtableAddressPoints;
50
Anders Carlsson5d7af6b2010-02-28 00:36:23 +000051 llvm::Constant *getCtorVtable(const BaseSubobject &Base,
52 bool BaseIsVirtual) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +000053 if (!GenerateDefinition)
54 return 0;
55
56 llvm::Constant *&CtorVtable = CtorVtables[Base];
57 if (!CtorVtable) {
Anders Carlssonff143f82010-03-25 00:35:49 +000058 // Get the vtable.
59 CtorVtable =
60 CGM.getVTables().GenerateConstructionVTable(Class, Base, BaseIsVirtual,
61 CtorVtableAddressPoints);
Anders Carlsson58b7eee2010-01-21 16:50:45 +000062 }
63
64 return CtorVtable;
65 }
66
67
68 /// BuildVtablePtr - Build up a referene to the given secondary vtable
69 llvm::Constant *BuildVtablePtr(llvm::Constant *Vtable,
70 const CXXRecordDecl *VtableClass,
71 const CXXRecordDecl *RD,
72 uint64_t Offset) {
73 if (!GenerateDefinition)
74 return 0;
75
76 uint64_t AddressPoint;
77
78 if (VtableClass != Class) {
79 // We have a ctor vtable, look for the address point in the ctor vtable
80 // address points.
81 AddressPoint =
82 CtorVtableAddressPoints[std::make_pair(VtableClass,
83 BaseSubobject(RD, Offset))];
84 } else {
85 AddressPoint =
86 (*AddressPoints[VtableClass])[std::make_pair(RD, Offset)];
87 }
88
89 // FIXME: We can never have 0 address point. Do this for now so gepping
90 // retains the same structure. Later we'll just assert.
91 if (AddressPoint == 0)
92 AddressPoint = 1;
93 D1(printf("XXX address point for %s in %s layout %s at offset %d was %d\n",
94 RD->getNameAsCString(), VtblClass->getNameAsCString(),
95 Class->getNameAsCString(), (int)Offset, (int)AddressPoint));
96
97 llvm::Value *Idxs[] = {
98 llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 0),
99 llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), AddressPoint)
100 };
101
102 llvm::Constant *Init =
103 llvm::ConstantExpr::getInBoundsGetElementPtr(Vtable, Idxs, 2);
104
105 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
106 return llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
107 }
108
109 /// Secondary - Add the secondary vtable pointers to Inits. Offset is the
110 /// current offset in bits to the object we're working on.
111 void Secondary(const CXXRecordDecl *RD, llvm::Constant *vtbl,
Anders Carlsson18222542010-03-26 00:11:51 +0000112 const CXXRecordDecl *VtblClass, uint64_t Offset,
113 bool MorallyVirtual) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000114 if (RD->getNumVBases() == 0 && ! MorallyVirtual)
115 return;
116
117 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
118 e = RD->bases_end(); i != e; ++i) {
119 const CXXRecordDecl *Base =
120 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
121
122 // We only want to visit each virtual base once.
123 if (i->isVirtual() && SeenVBasesInSecondary.count(Base))
124 continue;
125
126 // Itanium C++ ABI 2.6.2:
127 // Secondary virtual pointers are present for all bases with either
128 // virtual bases or virtual function declarations overridden along a
129 // virtual path.
130 //
131 // If the base class is not dynamic, we don't want to add it, nor any
132 // of its base classes.
133 if (!Base->isDynamicClass())
134 continue;
135
136 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
137 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
138 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
139 bool NonVirtualPrimaryBase;
140 NonVirtualPrimaryBase = !PrimaryBaseWasVirtual && Base == PrimaryBase;
141 bool BaseMorallyVirtual = MorallyVirtual | i->isVirtual();
142 uint64_t BaseOffset;
143 if (!i->isVirtual()) {
144 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
145 BaseOffset = Offset + Layout.getBaseClassOffset(Base);
146 } else
147 BaseOffset = BLayout.getVBaseClassOffset(Base);
148 llvm::Constant *subvtbl = vtbl;
149 const CXXRecordDecl *subVtblClass = VtblClass;
150 if ((Base->getNumVBases() || BaseMorallyVirtual)
151 && !NonVirtualPrimaryBase) {
152 llvm::Constant *init;
153 if (BaseMorallyVirtual || VtblClass == Class)
154 init = BuildVtablePtr(vtbl, VtblClass, Base, BaseOffset);
155 else {
Anders Carlsson5d7af6b2010-02-28 00:36:23 +0000156 init = getCtorVtable(BaseSubobject(Base, BaseOffset), i->isVirtual());
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000157
158 subvtbl = init;
159 subVtblClass = Base;
160
161 init = BuildVtablePtr(init, Class, Base, BaseOffset);
162 }
163
164 Inits.push_back(init);
165 }
166
167 if (i->isVirtual())
168 SeenVBasesInSecondary.insert(Base);
169
170 Secondary(Base, subvtbl, subVtblClass, BaseOffset, BaseMorallyVirtual);
171 }
172 }
173
Anders Carlssonc1246c82010-03-26 00:35:45 +0000174 /// LayoutSecondaryVTTs - Lay out the secondary VTTs of the given base
175 /// subobject.
176 void LayoutSecondaryVTTs(BaseSubobject Base);
177
Anders Carlsson9f17d412010-03-26 00:50:17 +0000178 /// LayoutVirtualVTTs - Lay out the VTTs for the virtual base classes of the
179 /// given record decl.
180 void LayoutVirtualVTTs(const CXXRecordDecl *RD,
181 VisitedVirtualBasesSetTy &VBases);
182
183 /// LayoutVTT - Will lay out the VTT for the given subobject, including any
184 /// secondary VTTs, secondary virtual pointers and virtual VTTs.
185 void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual);
186
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000187public:
188 VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c,
189 CodeGenModule &cgm, bool GenerateDefinition)
190 : Inits(inits), Class(c), CGM(cgm),
191 BLayout(cgm.getContext().getASTRecordLayout(c)),
Anders Carlsson66d567d2010-03-25 00:51:13 +0000192 AddressPoints(*cgm.getVTables().OldAddressPoints[c]),
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000193 VMContext(cgm.getModule().getContext()),
194 GenerateDefinition(GenerateDefinition) {
195
196 // First comes the primary virtual table pointer for the complete class...
Anders Carlsson5eea8762010-03-24 05:32:05 +0000197 ClassVtbl = GenerateDefinition ? CGM.getVTables().GetAddrOfVTable(Class) :0;
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000198
199 llvm::Constant *Init = BuildVtablePtr(ClassVtbl, Class, Class, 0);
200 Inits.push_back(Init);
201
202 // then the secondary VTTs...
Anders Carlssonc1246c82010-03-26 00:35:45 +0000203 LayoutSecondaryVTTs(BaseSubobject(Class, 0));
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000204
205 // Make sure to clear the set of seen virtual bases.
206 SeenVBasesInSecondary.clear();
207
208 // then the secondary vtable pointers...
Anders Carlsson18222542010-03-26 00:11:51 +0000209 Secondary(Class, ClassVtbl, Class, 0, false);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000210
211 // and last, the virtual VTTs.
Anders Carlsson9f17d412010-03-26 00:50:17 +0000212 VisitedVirtualBasesSetTy VBases;
213 LayoutVirtualVTTs(Class, VBases);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000214 }
215
216 llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getSubVTTIndicies() {
217 return SubVTTIndicies;
218 }
219};
Anders Carlssonc1246c82010-03-26 00:35:45 +0000220
221void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) {
222 const CXXRecordDecl *RD = Base.getBase();
223
224 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
225 E = RD->bases_end(); I != E; ++I) {
226
227 // Don't layout virtual bases.
228 if (I->isVirtual())
229 continue;
230
231 const CXXRecordDecl *BaseDecl =
232 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
233
234 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
235 uint64_t BaseOffset = Base.getBaseOffset() +
236 Layout.getBaseClassOffset(BaseDecl);
237
238 // Layout the VTT for this base.
239 LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false);
240 }
241}
242
Anders Carlsson9f17d412010-03-26 00:50:17 +0000243/// LayoutVirtualVTTs - Lay out the VTTs for the virtual base classes of the
244/// given record decl.
245void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD,
246 VisitedVirtualBasesSetTy &VBases) {
247 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
248 E = RD->bases_end(); I != E; ++I) {
249 const CXXRecordDecl *BaseDecl =
250 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
251
252 // Check if this is a virtual base.
253 if (I->isVirtual()) {
254 // Check if we've seen this base before.
255 if (!VBases.insert(BaseDecl))
256 continue;
257
258 const ASTRecordLayout &MostDerivedClassLayout =
259 CGM.getContext().getASTRecordLayout(Class);
260 uint64_t BaseOffset =
261 MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
262
263 LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true);
264 }
265
266 // We only need to layout virtual VTTs for this base if it actually has
267 // virtual bases.
268 if (BaseDecl->getNumVBases())
269 LayoutVirtualVTTs(BaseDecl, VBases);
270 }
271}
272
Anders Carlssonc1246c82010-03-26 00:35:45 +0000273void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) {
274 const CXXRecordDecl *RD = Base.getBase();
275
276 // Itanium C++ ABI 2.6.2:
277 // An array of virtual table addresses, called the VTT, is declared for
278 // each class type that has indirect or direct virtual base classes.
279 if (RD->getNumVBases() == 0)
280 return;
281
282 // Remember the sub-VTT index.
283 SubVTTIndicies[RD] = Inits.size();
284
285 llvm::Constant *Vtable;
286 const CXXRecordDecl *VtableClass;
287
288 // First comes the primary virtual table pointer...
289 Vtable = getCtorVtable(Base, /*IsVirtual=*/BaseIsVirtual);
290 VtableClass = RD;
291
292 llvm::Constant *Init = BuildVtablePtr(Vtable, VtableClass, RD,
293 Base.getBaseOffset());
294 Inits.push_back(Init);
295
296 // then the secondary VTTs....
297 LayoutSecondaryVTTs(Base);
298
299 // Make sure to clear the set of seen virtual bases.
300 SeenVBasesInSecondary.clear();
301
302 // and last the secondary vtable pointers.
303 Secondary(RD, Vtable, VtableClass, Base.getBaseOffset(), false);
304}
305
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000306}
307
308llvm::GlobalVariable *
Anders Carlssonaf440352010-03-23 04:11:45 +0000309CodeGenVTables::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
310 bool GenerateDefinition,
311 const CXXRecordDecl *RD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000312 // Only classes that have virtual bases need a VTT.
313 if (RD->getNumVBases() == 0)
314 return 0;
315
316 llvm::SmallString<256> OutName;
317 CGM.getMangleContext().mangleCXXVTT(RD, OutName);
318 llvm::StringRef Name = OutName.str();
319
320 D1(printf("vtt %s\n", RD->getNameAsCString()));
321
322 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
323 if (GV == 0 || GV->isDeclaration()) {
324 const llvm::Type *Int8PtrTy =
325 llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
326
327 std::vector<llvm::Constant *> inits;
328 VTTBuilder b(inits, RD, CGM, GenerateDefinition);
329
330 const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size());
331 llvm::Constant *Init = 0;
332 if (GenerateDefinition)
333 Init = llvm::ConstantArray::get(Type, inits);
334
335 llvm::GlobalVariable *OldGV = GV;
336 GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true,
337 Linkage, Init, Name);
338 CGM.setGlobalVisibility(GV, RD);
339
340 if (OldGV) {
341 GV->takeName(OldGV);
342 llvm::Constant *NewPtr =
343 llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
344 OldGV->replaceAllUsesWith(NewPtr);
345 OldGV->eraseFromParent();
346 }
347 }
348
349 return GV;
350}
351
Anders Carlssonaf440352010-03-23 04:11:45 +0000352llvm::GlobalVariable *CodeGenVTables::getVTT(const CXXRecordDecl *RD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000353 return GenerateVTT(llvm::GlobalValue::ExternalLinkage,
354 /*GenerateDefinition=*/false, RD);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000355}
356
Anders Carlssonaf440352010-03-23 04:11:45 +0000357bool CodeGenVTables::needsVTTParameter(GlobalDecl GD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000358 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
359
360 // We don't have any virtual bases, just return early.
361 if (!MD->getParent()->getNumVBases())
362 return false;
363
364 // Check if we have a base constructor.
365 if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
366 return true;
367
368 // Check if we have a base destructor.
369 if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
370 return true;
371
372 return false;
373}
374
Anders Carlssonaf440352010-03-23 04:11:45 +0000375uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD,
376 const CXXRecordDecl *Base) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000377 ClassPairTy ClassPair(RD, Base);
378
379 SubVTTIndiciesTy::iterator I =
380 SubVTTIndicies.find(ClassPair);
381 if (I != SubVTTIndicies.end())
382 return I->second;
383
384 std::vector<llvm::Constant *> inits;
385 VTTBuilder Builder(inits, RD, CGM, /*GenerateDefinition=*/false);
386
387 for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
388 Builder.getSubVTTIndicies().begin(),
389 E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
390 // Insert all indices.
391 ClassPairTy ClassPair(RD, I->first);
392
393 SubVTTIndicies.insert(std::make_pair(ClassPair, I->second));
394 }
395
396 I = SubVTTIndicies.find(ClassPair);
397 assert(I != SubVTTIndicies.end() && "Did not find index!");
398
399 return I->second;
400}