blob: cc28388b6305fae0df48f48c02d13301868e47e7 [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 {
Anders Carlsson50a2b422010-03-26 00:58:21 +000022
23/// VTT builder - Class for building VTT layout information.
Anders Carlsson58b7eee2010-01-21 16:50:45 +000024class VTTBuilder {
Anders Carlsson50a2b422010-03-26 00:58:21 +000025 /// MostDerivedClass - The most derived class for which we're building this
26 /// vtable.
27 const CXXRecordDecl *MostDerivedClass;
28
Anders Carlsson58b7eee2010-01-21 16:50:45 +000029 /// Inits - The list of values built for the VTT.
30 std::vector<llvm::Constant *> &Inits;
Anders Carlsson50a2b422010-03-26 00:58:21 +000031
32 /// MostDerivedClassLayout - the AST record layout of the most derived class.
33 const ASTRecordLayout &MostDerivedClassLayout;
34
Anders Carlsson58b7eee2010-01-21 16:50:45 +000035 CodeGenModule &CGM; // Per-module state.
Anders Carlsson50a2b422010-03-26 00:58:21 +000036
Anders Carlssonaf440352010-03-23 04:11:45 +000037 CodeGenVTables::AddrMap_t &AddressPoints;
Anders Carlsson58b7eee2010-01-21 16:50:45 +000038 // vtbl - A pointer to the vtable for Class.
39 llvm::Constant *ClassVtbl;
40 llvm::LLVMContext &VMContext;
41
Anders Carlsson9f17d412010-03-26 00:50:17 +000042 typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
43
Anders Carlsson58b7eee2010-01-21 16:50:45 +000044 /// SeenVBasesInSecondary - The seen virtual bases when building the
45 /// secondary virtual pointers.
46 llvm::SmallPtrSet<const CXXRecordDecl *, 32> SeenVBasesInSecondary;
47
48 llvm::DenseMap<const CXXRecordDecl *, uint64_t> SubVTTIndicies;
49
50 bool GenerateDefinition;
51
52 llvm::DenseMap<BaseSubobject, llvm::Constant *> CtorVtables;
53 llvm::DenseMap<std::pair<const CXXRecordDecl *, BaseSubobject>, uint64_t>
54 CtorVtableAddressPoints;
55
Anders Carlsson5d7af6b2010-02-28 00:36:23 +000056 llvm::Constant *getCtorVtable(const BaseSubobject &Base,
57 bool BaseIsVirtual) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +000058 if (!GenerateDefinition)
59 return 0;
60
61 llvm::Constant *&CtorVtable = CtorVtables[Base];
62 if (!CtorVtable) {
Anders Carlssonff143f82010-03-25 00:35:49 +000063 // Get the vtable.
64 CtorVtable =
Anders Carlsson50a2b422010-03-26 00:58:21 +000065 CGM.getVTables().GenerateConstructionVTable(MostDerivedClass,
66 Base, BaseIsVirtual,
Anders Carlssonff143f82010-03-25 00:35:49 +000067 CtorVtableAddressPoints);
Anders Carlsson58b7eee2010-01-21 16:50:45 +000068 }
69
70 return CtorVtable;
71 }
72
73
74 /// BuildVtablePtr - Build up a referene to the given secondary vtable
75 llvm::Constant *BuildVtablePtr(llvm::Constant *Vtable,
76 const CXXRecordDecl *VtableClass,
77 const CXXRecordDecl *RD,
78 uint64_t Offset) {
79 if (!GenerateDefinition)
80 return 0;
81
82 uint64_t AddressPoint;
83
Anders Carlsson50a2b422010-03-26 00:58:21 +000084 if (VtableClass != MostDerivedClass) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +000085 // We have a ctor vtable, look for the address point in the ctor vtable
86 // address points.
87 AddressPoint =
88 CtorVtableAddressPoints[std::make_pair(VtableClass,
89 BaseSubobject(RD, Offset))];
90 } else {
91 AddressPoint =
92 (*AddressPoints[VtableClass])[std::make_pair(RD, Offset)];
93 }
94
95 // FIXME: We can never have 0 address point. Do this for now so gepping
96 // retains the same structure. Later we'll just assert.
97 if (AddressPoint == 0)
98 AddressPoint = 1;
99 D1(printf("XXX address point for %s in %s layout %s at offset %d was %d\n",
100 RD->getNameAsCString(), VtblClass->getNameAsCString(),
101 Class->getNameAsCString(), (int)Offset, (int)AddressPoint));
102
103 llvm::Value *Idxs[] = {
104 llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 0),
105 llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), AddressPoint)
106 };
107
108 llvm::Constant *Init =
109 llvm::ConstantExpr::getInBoundsGetElementPtr(Vtable, Idxs, 2);
110
111 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
112 return llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
113 }
114
115 /// Secondary - Add the secondary vtable pointers to Inits. Offset is the
116 /// current offset in bits to the object we're working on.
117 void Secondary(const CXXRecordDecl *RD, llvm::Constant *vtbl,
Anders Carlsson18222542010-03-26 00:11:51 +0000118 const CXXRecordDecl *VtblClass, uint64_t Offset,
119 bool MorallyVirtual) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000120 if (RD->getNumVBases() == 0 && ! MorallyVirtual)
121 return;
122
123 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
124 e = RD->bases_end(); i != e; ++i) {
125 const CXXRecordDecl *Base =
126 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
127
128 // We only want to visit each virtual base once.
129 if (i->isVirtual() && SeenVBasesInSecondary.count(Base))
130 continue;
131
132 // Itanium C++ ABI 2.6.2:
133 // Secondary virtual pointers are present for all bases with either
134 // virtual bases or virtual function declarations overridden along a
135 // virtual path.
136 //
137 // If the base class is not dynamic, we don't want to add it, nor any
138 // of its base classes.
139 if (!Base->isDynamicClass())
140 continue;
141
142 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
143 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
144 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
145 bool NonVirtualPrimaryBase;
146 NonVirtualPrimaryBase = !PrimaryBaseWasVirtual && Base == PrimaryBase;
147 bool BaseMorallyVirtual = MorallyVirtual | i->isVirtual();
148 uint64_t BaseOffset;
149 if (!i->isVirtual()) {
150 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
151 BaseOffset = Offset + Layout.getBaseClassOffset(Base);
152 } else
Anders Carlsson50a2b422010-03-26 00:58:21 +0000153 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(Base);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000154 llvm::Constant *subvtbl = vtbl;
155 const CXXRecordDecl *subVtblClass = VtblClass;
156 if ((Base->getNumVBases() || BaseMorallyVirtual)
157 && !NonVirtualPrimaryBase) {
158 llvm::Constant *init;
Anders Carlsson50a2b422010-03-26 00:58:21 +0000159 if (BaseMorallyVirtual || VtblClass == MostDerivedClass)
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000160 init = BuildVtablePtr(vtbl, VtblClass, Base, BaseOffset);
161 else {
Anders Carlsson5d7af6b2010-02-28 00:36:23 +0000162 init = getCtorVtable(BaseSubobject(Base, BaseOffset), i->isVirtual());
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000163
164 subvtbl = init;
165 subVtblClass = Base;
166
Anders Carlsson50a2b422010-03-26 00:58:21 +0000167 init = BuildVtablePtr(init, MostDerivedClass, Base, BaseOffset);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000168 }
169
170 Inits.push_back(init);
171 }
172
173 if (i->isVirtual())
174 SeenVBasesInSecondary.insert(Base);
175
176 Secondary(Base, subvtbl, subVtblClass, BaseOffset, BaseMorallyVirtual);
177 }
178 }
179
Anders Carlssonc1246c82010-03-26 00:35:45 +0000180 /// LayoutSecondaryVTTs - Lay out the secondary VTTs of the given base
181 /// subobject.
182 void LayoutSecondaryVTTs(BaseSubobject Base);
183
Anders Carlsson9f17d412010-03-26 00:50:17 +0000184 /// LayoutVirtualVTTs - Lay out the VTTs for the virtual base classes of the
185 /// given record decl.
186 void LayoutVirtualVTTs(const CXXRecordDecl *RD,
187 VisitedVirtualBasesSetTy &VBases);
188
189 /// LayoutVTT - Will lay out the VTT for the given subobject, including any
190 /// secondary VTTs, secondary virtual pointers and virtual VTTs.
191 void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual);
192
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000193public:
Anders Carlsson50a2b422010-03-26 00:58:21 +0000194 VTTBuilder(std::vector<llvm::Constant *> &inits,
195 const CXXRecordDecl *MostDerivedClass,
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000196 CodeGenModule &cgm, bool GenerateDefinition)
Anders Carlsson50a2b422010-03-26 00:58:21 +0000197 : MostDerivedClass(MostDerivedClass),
198 Inits(inits),
199 MostDerivedClassLayout(cgm.getContext().getASTRecordLayout(MostDerivedClass)),
200 CGM(cgm),
201 AddressPoints(*cgm.getVTables().OldAddressPoints[MostDerivedClass]),
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000202 VMContext(cgm.getModule().getContext()),
203 GenerateDefinition(GenerateDefinition) {
204
205 // First comes the primary virtual table pointer for the complete class...
Anders Carlsson50a2b422010-03-26 00:58:21 +0000206 ClassVtbl = GenerateDefinition ?
207 CGM.getVTables().GetAddrOfVTable(MostDerivedClass) :0;
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000208
Anders Carlsson50a2b422010-03-26 00:58:21 +0000209 llvm::Constant *Init = BuildVtablePtr(ClassVtbl, MostDerivedClass,
210 MostDerivedClass, 0);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000211 Inits.push_back(Init);
212
213 // then the secondary VTTs...
Anders Carlsson50a2b422010-03-26 00:58:21 +0000214 LayoutSecondaryVTTs(BaseSubobject(MostDerivedClass, 0));
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000215
216 // Make sure to clear the set of seen virtual bases.
217 SeenVBasesInSecondary.clear();
218
219 // then the secondary vtable pointers...
Anders Carlsson50a2b422010-03-26 00:58:21 +0000220 Secondary(MostDerivedClass, ClassVtbl, MostDerivedClass, 0, false);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000221
222 // and last, the virtual VTTs.
Anders Carlsson9f17d412010-03-26 00:50:17 +0000223 VisitedVirtualBasesSetTy VBases;
Anders Carlsson50a2b422010-03-26 00:58:21 +0000224 LayoutVirtualVTTs(MostDerivedClass, VBases);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000225 }
226
227 llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getSubVTTIndicies() {
228 return SubVTTIndicies;
229 }
230};
Anders Carlssonc1246c82010-03-26 00:35:45 +0000231
232void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) {
233 const CXXRecordDecl *RD = Base.getBase();
234
235 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
236 E = RD->bases_end(); I != E; ++I) {
237
238 // Don't layout virtual bases.
239 if (I->isVirtual())
240 continue;
241
242 const CXXRecordDecl *BaseDecl =
243 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
244
245 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
246 uint64_t BaseOffset = Base.getBaseOffset() +
247 Layout.getBaseClassOffset(BaseDecl);
248
249 // Layout the VTT for this base.
250 LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false);
251 }
252}
253
Anders Carlsson9f17d412010-03-26 00:50:17 +0000254/// LayoutVirtualVTTs - Lay out the VTTs for the virtual base classes of the
255/// given record decl.
256void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD,
257 VisitedVirtualBasesSetTy &VBases) {
258 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
259 E = RD->bases_end(); I != E; ++I) {
260 const CXXRecordDecl *BaseDecl =
261 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
262
263 // Check if this is a virtual base.
264 if (I->isVirtual()) {
265 // Check if we've seen this base before.
266 if (!VBases.insert(BaseDecl))
267 continue;
268
Anders Carlsson9f17d412010-03-26 00:50:17 +0000269 uint64_t BaseOffset =
270 MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
271
272 LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true);
273 }
274
275 // We only need to layout virtual VTTs for this base if it actually has
276 // virtual bases.
277 if (BaseDecl->getNumVBases())
278 LayoutVirtualVTTs(BaseDecl, VBases);
279 }
280}
281
Anders Carlssonc1246c82010-03-26 00:35:45 +0000282void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) {
283 const CXXRecordDecl *RD = Base.getBase();
284
285 // Itanium C++ ABI 2.6.2:
286 // An array of virtual table addresses, called the VTT, is declared for
287 // each class type that has indirect or direct virtual base classes.
288 if (RD->getNumVBases() == 0)
289 return;
290
291 // Remember the sub-VTT index.
292 SubVTTIndicies[RD] = Inits.size();
293
294 llvm::Constant *Vtable;
295 const CXXRecordDecl *VtableClass;
296
297 // First comes the primary virtual table pointer...
298 Vtable = getCtorVtable(Base, /*IsVirtual=*/BaseIsVirtual);
299 VtableClass = RD;
300
301 llvm::Constant *Init = BuildVtablePtr(Vtable, VtableClass, RD,
302 Base.getBaseOffset());
303 Inits.push_back(Init);
304
305 // then the secondary VTTs....
306 LayoutSecondaryVTTs(Base);
307
308 // Make sure to clear the set of seen virtual bases.
309 SeenVBasesInSecondary.clear();
310
311 // and last the secondary vtable pointers.
312 Secondary(RD, Vtable, VtableClass, Base.getBaseOffset(), false);
313}
314
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000315}
316
317llvm::GlobalVariable *
Anders Carlssonaf440352010-03-23 04:11:45 +0000318CodeGenVTables::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
319 bool GenerateDefinition,
320 const CXXRecordDecl *RD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000321 // Only classes that have virtual bases need a VTT.
322 if (RD->getNumVBases() == 0)
323 return 0;
324
325 llvm::SmallString<256> OutName;
326 CGM.getMangleContext().mangleCXXVTT(RD, OutName);
327 llvm::StringRef Name = OutName.str();
328
329 D1(printf("vtt %s\n", RD->getNameAsCString()));
330
331 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
332 if (GV == 0 || GV->isDeclaration()) {
333 const llvm::Type *Int8PtrTy =
334 llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
335
336 std::vector<llvm::Constant *> inits;
337 VTTBuilder b(inits, RD, CGM, GenerateDefinition);
338
339 const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size());
340 llvm::Constant *Init = 0;
341 if (GenerateDefinition)
342 Init = llvm::ConstantArray::get(Type, inits);
343
344 llvm::GlobalVariable *OldGV = GV;
345 GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true,
346 Linkage, Init, Name);
347 CGM.setGlobalVisibility(GV, RD);
348
349 if (OldGV) {
350 GV->takeName(OldGV);
351 llvm::Constant *NewPtr =
352 llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
353 OldGV->replaceAllUsesWith(NewPtr);
354 OldGV->eraseFromParent();
355 }
356 }
357
358 return GV;
359}
360
Anders Carlssonaf440352010-03-23 04:11:45 +0000361llvm::GlobalVariable *CodeGenVTables::getVTT(const CXXRecordDecl *RD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000362 return GenerateVTT(llvm::GlobalValue::ExternalLinkage,
363 /*GenerateDefinition=*/false, RD);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000364}
365
Anders Carlssonaf440352010-03-23 04:11:45 +0000366bool CodeGenVTables::needsVTTParameter(GlobalDecl GD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000367 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
368
369 // We don't have any virtual bases, just return early.
370 if (!MD->getParent()->getNumVBases())
371 return false;
372
373 // Check if we have a base constructor.
374 if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
375 return true;
376
377 // Check if we have a base destructor.
378 if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
379 return true;
380
381 return false;
382}
383
Anders Carlssonaf440352010-03-23 04:11:45 +0000384uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD,
385 const CXXRecordDecl *Base) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000386 ClassPairTy ClassPair(RD, Base);
387
388 SubVTTIndiciesTy::iterator I =
389 SubVTTIndicies.find(ClassPair);
390 if (I != SubVTTIndicies.end())
391 return I->second;
392
393 std::vector<llvm::Constant *> inits;
394 VTTBuilder Builder(inits, RD, CGM, /*GenerateDefinition=*/false);
395
396 for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
397 Builder.getSubVTTIndicies().begin(),
398 E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
399 // Insert all indices.
400 ClassPairTy ClassPair(RD, I->first);
401
402 SubVTTIndicies.insert(std::make_pair(ClassPair, I->second));
403 }
404
405 I = SubVTTIndicies.find(ClassPair);
406 assert(I != SubVTTIndicies.end() && "Did not find index!");
407
408 return I->second;
409}