blob: 14b58fe3060d7e9ee2bfabec60f3048e66619763 [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,
110 const CXXRecordDecl *VtblClass, uint64_t Offset=0,
111 bool MorallyVirtual=false) {
112 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 Carlsson5d7af6b2010-02-28 00:36:23 +0000174 void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool BaseIsVirtual,
175 bool MorallyVirtual) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000176 // Itanium C++ ABI 2.6.2:
177 // An array of virtual table addresses, called the VTT, is declared for
178 // each class type that has indirect or direct virtual base classes.
179 if (RD->getNumVBases() == 0)
180 return;
181
182 // Remember the sub-VTT index.
183 SubVTTIndicies[RD] = Inits.size();
184
185 llvm::Constant *Vtable;
186 const CXXRecordDecl *VtableClass;
187
188 // First comes the primary virtual table pointer...
189 if (MorallyVirtual) {
190 Vtable = ClassVtbl;
191 VtableClass = Class;
192 } else {
Anders Carlsson5d7af6b2010-02-28 00:36:23 +0000193 Vtable = getCtorVtable(BaseSubobject(RD, Offset),
194 /*IsVirtual=*/BaseIsVirtual);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000195 VtableClass = RD;
196 }
197
198 llvm::Constant *Init = BuildVtablePtr(Vtable, VtableClass, RD, Offset);
199 Inits.push_back(Init);
200
201 // then the secondary VTTs....
202 SecondaryVTTs(RD, Offset, MorallyVirtual);
203
204 // Make sure to clear the set of seen virtual bases.
205 SeenVBasesInSecondary.clear();
206
207 // and last the secondary vtable pointers.
208 Secondary(RD, Vtable, VtableClass, Offset, MorallyVirtual);
209 }
210
211 /// SecondaryVTTs - Add the secondary VTTs to Inits. The secondary VTTs are
212 /// built from each direct non-virtual proper base that requires a VTT in
213 /// declaration order.
214 void SecondaryVTTs(const CXXRecordDecl *RD, uint64_t Offset=0,
215 bool MorallyVirtual=false) {
216 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
217 e = RD->bases_end(); i != e; ++i) {
218 const CXXRecordDecl *Base =
219 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
220 if (i->isVirtual())
221 continue;
222 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
223 uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base);
224
Anders Carlsson5d7af6b2010-02-28 00:36:23 +0000225 BuildVTT(Base, BaseOffset, /*BaseIsVirtual=*/false, MorallyVirtual);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000226 }
227 }
228
229 /// VirtualVTTs - Add the VTT for each proper virtual base in inheritance
230 /// graph preorder.
231 void VirtualVTTs(const CXXRecordDecl *RD) {
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() && !SeenVBase.count(Base)) {
237 SeenVBase.insert(Base);
238 uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
Anders Carlsson5d7af6b2010-02-28 00:36:23 +0000239 BuildVTT(Base, BaseOffset, /*BaseIsVirtual=*/true, false);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000240 }
241 VirtualVTTs(Base);
242 }
243 }
244
245public:
246 VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c,
247 CodeGenModule &cgm, bool GenerateDefinition)
248 : Inits(inits), Class(c), CGM(cgm),
249 BLayout(cgm.getContext().getASTRecordLayout(c)),
Anders Carlsson66d567d2010-03-25 00:51:13 +0000250 AddressPoints(*cgm.getVTables().OldAddressPoints[c]),
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000251 VMContext(cgm.getModule().getContext()),
252 GenerateDefinition(GenerateDefinition) {
253
254 // First comes the primary virtual table pointer for the complete class...
Anders Carlsson5eea8762010-03-24 05:32:05 +0000255 ClassVtbl = GenerateDefinition ? CGM.getVTables().GetAddrOfVTable(Class) :0;
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000256
257 llvm::Constant *Init = BuildVtablePtr(ClassVtbl, Class, Class, 0);
258 Inits.push_back(Init);
259
260 // then the secondary VTTs...
261 SecondaryVTTs(Class);
262
263 // Make sure to clear the set of seen virtual bases.
264 SeenVBasesInSecondary.clear();
265
266 // then the secondary vtable pointers...
267 Secondary(Class, ClassVtbl, Class);
268
269 // and last, the virtual VTTs.
270 VirtualVTTs(Class);
271 }
272
273 llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getSubVTTIndicies() {
274 return SubVTTIndicies;
275 }
276};
277}
278
279llvm::GlobalVariable *
Anders Carlssonaf440352010-03-23 04:11:45 +0000280CodeGenVTables::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
281 bool GenerateDefinition,
282 const CXXRecordDecl *RD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000283 // Only classes that have virtual bases need a VTT.
284 if (RD->getNumVBases() == 0)
285 return 0;
286
287 llvm::SmallString<256> OutName;
288 CGM.getMangleContext().mangleCXXVTT(RD, OutName);
289 llvm::StringRef Name = OutName.str();
290
291 D1(printf("vtt %s\n", RD->getNameAsCString()));
292
293 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
294 if (GV == 0 || GV->isDeclaration()) {
295 const llvm::Type *Int8PtrTy =
296 llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
297
298 std::vector<llvm::Constant *> inits;
299 VTTBuilder b(inits, RD, CGM, GenerateDefinition);
300
301 const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size());
302 llvm::Constant *Init = 0;
303 if (GenerateDefinition)
304 Init = llvm::ConstantArray::get(Type, inits);
305
306 llvm::GlobalVariable *OldGV = GV;
307 GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true,
308 Linkage, Init, Name);
309 CGM.setGlobalVisibility(GV, RD);
310
311 if (OldGV) {
312 GV->takeName(OldGV);
313 llvm::Constant *NewPtr =
314 llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
315 OldGV->replaceAllUsesWith(NewPtr);
316 OldGV->eraseFromParent();
317 }
318 }
319
320 return GV;
321}
322
Anders Carlssonaf440352010-03-23 04:11:45 +0000323llvm::GlobalVariable *CodeGenVTables::getVTT(const CXXRecordDecl *RD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000324 return GenerateVTT(llvm::GlobalValue::ExternalLinkage,
325 /*GenerateDefinition=*/false, RD);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000326}
327
Anders Carlssonaf440352010-03-23 04:11:45 +0000328bool CodeGenVTables::needsVTTParameter(GlobalDecl GD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000329 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
330
331 // We don't have any virtual bases, just return early.
332 if (!MD->getParent()->getNumVBases())
333 return false;
334
335 // Check if we have a base constructor.
336 if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
337 return true;
338
339 // Check if we have a base destructor.
340 if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
341 return true;
342
343 return false;
344}
345
Anders Carlssonaf440352010-03-23 04:11:45 +0000346uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD,
347 const CXXRecordDecl *Base) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000348 ClassPairTy ClassPair(RD, Base);
349
350 SubVTTIndiciesTy::iterator I =
351 SubVTTIndicies.find(ClassPair);
352 if (I != SubVTTIndicies.end())
353 return I->second;
354
355 std::vector<llvm::Constant *> inits;
356 VTTBuilder Builder(inits, RD, CGM, /*GenerateDefinition=*/false);
357
358 for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
359 Builder.getSubVTTIndicies().begin(),
360 E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
361 // Insert all indices.
362 ClassPairTy ClassPair(RD, I->first);
363
364 SubVTTIndicies.insert(std::make_pair(ClassPair, I->second));
365 }
366
367 I = SubVTTIndicies.find(ClassPair);
368 assert(I != SubVTTIndicies.end() && "Did not find index!");
369
370 return I->second;
371}