blob: e179ecbce4154f60fbf18ea4901023fc89b958c9 [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 Carlsson19f191f2010-03-26 04:10:39 +000025
26 CodeGenModule &CGM;
27
Anders Carlsson50a2b422010-03-26 00:58:21 +000028 /// MostDerivedClass - The most derived class for which we're building this
29 /// vtable.
30 const CXXRecordDecl *MostDerivedClass;
31
Anders Carlsson19f191f2010-03-26 04:10:39 +000032 typedef llvm::SmallVector<llvm::Constant *, 64> VTTComponentsVectorTy;
33
34 /// VTTComponents - The VTT components.
35 VTTComponentsVectorTy VTTComponents;
Anders Carlsson50a2b422010-03-26 00:58:21 +000036
37 /// MostDerivedClassLayout - the AST record layout of the most derived class.
38 const ASTRecordLayout &MostDerivedClassLayout;
39
Anders Carlssonaf440352010-03-23 04:11:45 +000040 CodeGenVTables::AddrMap_t &AddressPoints;
Anders Carlsson58b7eee2010-01-21 16:50:45 +000041
Anders Carlsson9f17d412010-03-26 00:50:17 +000042 typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
43
Anders Carlsson2c822f12010-03-26 03:56:54 +000044 typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
45
Anders Carlsson19f191f2010-03-26 04:10:39 +000046 /// SubVTTIndicies - The sub-VTT indices for the bases of the most derived
47 /// class whose VTT is being built.
Anders Carlsson58b7eee2010-01-21 16:50:45 +000048 llvm::DenseMap<const CXXRecordDecl *, uint64_t> SubVTTIndicies;
49
Anders Carlsson19f191f2010-03-26 04:10:39 +000050 /// GenerateDefinition - Whether the VTT builder should generate LLVM IR for
51 /// the VTT.
Anders Carlsson58b7eee2010-01-21 16:50:45 +000052 bool GenerateDefinition;
Anders Carlsson58b7eee2010-01-21 16:50:45 +000053
Anders Carlsson2c822f12010-03-26 03:56:54 +000054 /// GetAddrOfVTable - Returns the address of the vtable for the base class in
55 /// the given vtable class.
56 ///
57 /// \param AddressPoints - If the returned vtable is a construction vtable,
58 /// this will hold the address points for it.
59 llvm::Constant *GetAddrOfVTable(BaseSubobject Base, bool BaseIsVirtual,
60 AddressPointsMapTy& AddressPoints);
61
62 /// AddVTablePointer - Add a vtable pointer to the VTT currently being built.
63 ///
64 /// \param AddressPoints - If the vtable is a construction vtable, this has
65 /// the address points for it.
66 void AddVTablePointer(BaseSubobject Base, llvm::Constant *VTable,
67 const CXXRecordDecl *VTableClass,
68 const AddressPointsMapTy& AddressPoints);
69
Anders Carlssonc1246c82010-03-26 00:35:45 +000070 /// LayoutSecondaryVTTs - Lay out the secondary VTTs of the given base
71 /// subobject.
72 void LayoutSecondaryVTTs(BaseSubobject Base);
73
Anders Carlsson2c822f12010-03-26 03:56:54 +000074 /// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers
75 /// for the given base subobject.
76 ///
77 /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
78 /// or a direct or indirect base of a virtual base.
79 ///
80 /// \param AddressPoints - If the vtable is a construction vtable, this has
81 /// the address points for it.
82 void LayoutSecondaryVirtualPointers(BaseSubobject Base,
83 bool BaseIsMorallyVirtual,
84 llvm::Constant *VTable,
85 const CXXRecordDecl *VTableClass,
86 const AddressPointsMapTy& AddressPoints,
87 VisitedVirtualBasesSetTy &VBases);
88
89 /// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers
90 /// for the given base subobject.
91 ///
92 /// \param AddressPoints - If the vtable is a construction vtable, this has
93 /// the address points for it.
94 void LayoutSecondaryVirtualPointers(BaseSubobject Base,
95 llvm::Constant *VTable,
96 const AddressPointsMapTy& AddressPoints);
97
Anders Carlsson9f17d412010-03-26 00:50:17 +000098 /// LayoutVirtualVTTs - Lay out the VTTs for the virtual base classes of the
99 /// given record decl.
100 void LayoutVirtualVTTs(const CXXRecordDecl *RD,
101 VisitedVirtualBasesSetTy &VBases);
102
103 /// LayoutVTT - Will lay out the VTT for the given subobject, including any
104 /// secondary VTTs, secondary virtual pointers and virtual VTTs.
105 void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual);
106
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000107public:
Anders Carlsson19f191f2010-03-26 04:10:39 +0000108 VTTBuilder(CodeGenModule &CGM, const CXXRecordDecl *MostDerivedClass,
109 bool GenerateDefinition);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000110
111 llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getSubVTTIndicies() {
112 return SubVTTIndicies;
113 }
Anders Carlsson19f191f2010-03-26 04:10:39 +0000114
115 // getVTTComponents - Returns a reference to the VTT components.
116 const VTTComponentsVectorTy &getVTTComponents() const {
117 return VTTComponents;
118 }
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000119};
Anders Carlsson2c822f12010-03-26 03:56:54 +0000120
Anders Carlsson19f191f2010-03-26 04:10:39 +0000121VTTBuilder::VTTBuilder(CodeGenModule &CGM,
122 const CXXRecordDecl *MostDerivedClass,
123 bool GenerateDefinition)
124 : CGM(CGM), MostDerivedClass(MostDerivedClass),
125 MostDerivedClassLayout(CGM.getContext().getASTRecordLayout(MostDerivedClass)),
126 AddressPoints(*CGM.getVTables().OldAddressPoints[MostDerivedClass]),
127 GenerateDefinition(GenerateDefinition) {
128
129 // Lay out this VTT.
130 LayoutVTT(BaseSubobject(MostDerivedClass, 0), /*BaseIsVirtual=*/false);
131}
132
Anders Carlsson2c822f12010-03-26 03:56:54 +0000133llvm::Constant *
134VTTBuilder::GetAddrOfVTable(BaseSubobject Base, bool BaseIsVirtual,
135 AddressPointsMapTy& AddressPoints) {
136 if (!GenerateDefinition)
137 return 0;
Anders Carlssonc1246c82010-03-26 00:35:45 +0000138
Anders Carlsson2c822f12010-03-26 03:56:54 +0000139 if (Base.getBase() == MostDerivedClass) {
140 assert(Base.getBaseOffset() == 0 &&
141 "Most derived class vtable must have a zero offset!");
142 // This is a regular vtable.
143 return CGM.getVTables().GetAddrOfVTable(MostDerivedClass);
144 }
145
146 return CGM.getVTables().GenerateConstructionVTable(MostDerivedClass,
147 Base, BaseIsVirtual,
148 AddressPoints);
149}
150
151void VTTBuilder::AddVTablePointer(BaseSubobject Base, llvm::Constant *VTable,
152 const CXXRecordDecl *VTableClass,
153 const AddressPointsMapTy& AddressPoints) {
154 if (!GenerateDefinition) {
Anders Carlsson19f191f2010-03-26 04:10:39 +0000155 VTTComponents.push_back(0);
Anders Carlsson2c822f12010-03-26 03:56:54 +0000156 return;
157 }
158
159 uint64_t AddressPoint;
160 if (VTableClass != MostDerivedClass) {
161 // The vtable is a construction vtable, look in the construction vtable
162 // address points.
163 AddressPoint = AddressPoints.lookup(Base);
164 } else {
165 AddressPoint =
166 (*this->AddressPoints[VTableClass])[std::make_pair(Base.getBase(),
167 Base.getBaseOffset())];
168 }
169
170 if (!AddressPoint) AddressPoint = 0;
171 assert(AddressPoint != 0 && "Did not find an address point!");
172
173 llvm::Value *Idxs[] = {
174 llvm::ConstantInt::get(llvm::Type::getInt64Ty(CGM.getLLVMContext()), 0),
175 llvm::ConstantInt::get(llvm::Type::getInt64Ty(CGM.getLLVMContext()),
176 AddressPoint)
177 };
178
179 llvm::Constant *Init =
180 llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Idxs, 2);
181
182 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
183 Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
184
Anders Carlsson19f191f2010-03-26 04:10:39 +0000185 VTTComponents.push_back(Init);
Anders Carlsson2c822f12010-03-26 03:56:54 +0000186}
187
Anders Carlssonc1246c82010-03-26 00:35:45 +0000188void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) {
189 const CXXRecordDecl *RD = Base.getBase();
190
191 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
192 E = RD->bases_end(); I != E; ++I) {
193
194 // Don't layout virtual bases.
195 if (I->isVirtual())
196 continue;
197
198 const CXXRecordDecl *BaseDecl =
199 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
200
201 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
202 uint64_t BaseOffset = Base.getBaseOffset() +
203 Layout.getBaseClassOffset(BaseDecl);
204
205 // Layout the VTT for this base.
206 LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false);
207 }
208}
209
Anders Carlsson2c822f12010-03-26 03:56:54 +0000210void
211VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
212 bool BaseIsMorallyVirtual,
213 llvm::Constant *VTable,
214 const CXXRecordDecl *VTableClass,
215 const AddressPointsMapTy& AddressPoints,
216 VisitedVirtualBasesSetTy &VBases) {
217 const CXXRecordDecl *RD = Base.getBase();
218
219 // We're not interested in bases that don't have virtual bases, and not
220 // morally virtual bases.
221 if (!RD->getNumVBases() && !BaseIsMorallyVirtual)
222 return;
223
224 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
225 E = RD->bases_end(); I != E; ++I) {
226 const CXXRecordDecl *BaseDecl =
227 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
228
229 // Itanium C++ ABI 2.6.2:
230 // Secondary virtual pointers are present for all bases with either
231 // virtual bases or virtual function declarations overridden along a
232 // virtual path.
233 //
234 // If the base class is not dynamic, we don't want to add it, nor any
235 // of its base classes.
236 if (!BaseDecl->isDynamicClass())
237 continue;
238
239 bool BaseDeclIsMorallyVirtual = BaseIsMorallyVirtual;
240 bool BaseDeclIsNonVirtualPrimaryBase = false;
241 uint64_t BaseOffset;
242 if (I->isVirtual()) {
243 // Ignore virtual bases that we've already visited.
244 if (!VBases.insert(BaseDecl))
245 continue;
246
247 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
248 BaseDeclIsMorallyVirtual = true;
249 } else {
250 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
251
252 BaseOffset = Base.getBaseOffset() + Layout.getBaseClassOffset(BaseDecl);
253
254 if (!Layout.getPrimaryBaseWasVirtual() &&
255 Layout.getPrimaryBase() == BaseDecl)
256 BaseDeclIsNonVirtualPrimaryBase = true;
257 }
258
259 // Itanium C++ ABI 2.6.2:
260 // Secondary virtual pointers: for each base class X which (a) has virtual
261 // bases or is reachable along a virtual path from D, and (b) is not a
262 // non-virtual primary base, the address of the virtual table for X-in-D
263 // or an appropriate construction virtual table.
264 if (!BaseDeclIsNonVirtualPrimaryBase &&
265 (BaseDecl->getNumVBases() || BaseDeclIsMorallyVirtual)) {
266 // Add the vtable pointer.
267 AddVTablePointer(BaseSubobject(BaseDecl, BaseOffset), VTable, VTableClass,
268 AddressPoints);
269 }
270
271 // And lay out the secondary virtual pointers for the base class.
272 LayoutSecondaryVirtualPointers(BaseSubobject(BaseDecl, BaseOffset),
273 BaseDeclIsMorallyVirtual, VTable,
274 VTableClass, AddressPoints, VBases);
275 }
276}
277
278void
279VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
280 llvm::Constant *VTable,
281 const AddressPointsMapTy& AddressPoints) {
282 VisitedVirtualBasesSetTy VBases;
283 LayoutSecondaryVirtualPointers(Base, /*BaseIsMorallyVirtual=*/false,
284 VTable, Base.getBase(), AddressPoints, VBases);
285}
286
Anders Carlsson9f17d412010-03-26 00:50:17 +0000287void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD,
288 VisitedVirtualBasesSetTy &VBases) {
289 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
290 E = RD->bases_end(); I != E; ++I) {
291 const CXXRecordDecl *BaseDecl =
292 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
293
294 // Check if this is a virtual base.
295 if (I->isVirtual()) {
296 // Check if we've seen this base before.
297 if (!VBases.insert(BaseDecl))
298 continue;
299
Anders Carlsson9f17d412010-03-26 00:50:17 +0000300 uint64_t BaseOffset =
301 MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
302
303 LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true);
304 }
305
306 // We only need to layout virtual VTTs for this base if it actually has
307 // virtual bases.
308 if (BaseDecl->getNumVBases())
309 LayoutVirtualVTTs(BaseDecl, VBases);
310 }
311}
312
Anders Carlssonc1246c82010-03-26 00:35:45 +0000313void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) {
314 const CXXRecordDecl *RD = Base.getBase();
315
316 // Itanium C++ ABI 2.6.2:
317 // An array of virtual table addresses, called the VTT, is declared for
318 // each class type that has indirect or direct virtual base classes.
319 if (RD->getNumVBases() == 0)
320 return;
Anders Carlsson19f191f2010-03-26 04:10:39 +0000321
322 bool IsPrimaryVTT = Base.getBase() == MostDerivedClass;
323
324 if (!IsPrimaryVTT) {
325 // Remember the sub-VTT index.
326 SubVTTIndicies[RD] = VTTComponents.size();
327 }
Anders Carlssonc1246c82010-03-26 00:35:45 +0000328
Anders Carlsson2c822f12010-03-26 03:56:54 +0000329 AddressPointsMapTy AddressPoints;
330 llvm::Constant *VTable = GetAddrOfVTable(Base, BaseIsVirtual, AddressPoints);
Anders Carlssonc1246c82010-03-26 00:35:45 +0000331
Anders Carlsson2c822f12010-03-26 03:56:54 +0000332 // Add the primary vtable pointer.
333 AddVTablePointer(Base, VTable, RD, AddressPoints);
Anders Carlssonc1246c82010-03-26 00:35:45 +0000334
Anders Carlsson2c822f12010-03-26 03:56:54 +0000335 // Add the secondary VTTs.
Anders Carlssonc1246c82010-03-26 00:35:45 +0000336 LayoutSecondaryVTTs(Base);
Anders Carlsson2c822f12010-03-26 03:56:54 +0000337
338 // Add the secondary virtual pointers.
339 LayoutSecondaryVirtualPointers(Base, VTable, AddressPoints);
340
341 // If this is the primary VTT, we want to lay out virtual VTTs as well.
Anders Carlsson19f191f2010-03-26 04:10:39 +0000342 if (IsPrimaryVTT) {
Anders Carlsson2c822f12010-03-26 03:56:54 +0000343 VisitedVirtualBasesSetTy VBases;
344 LayoutVirtualVTTs(Base.getBase(), VBases);
345 }
Anders Carlssonc1246c82010-03-26 00:35:45 +0000346}
347
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000348}
349
350llvm::GlobalVariable *
Anders Carlssonaf440352010-03-23 04:11:45 +0000351CodeGenVTables::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
352 bool GenerateDefinition,
353 const CXXRecordDecl *RD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000354 // Only classes that have virtual bases need a VTT.
355 if (RD->getNumVBases() == 0)
356 return 0;
357
358 llvm::SmallString<256> OutName;
359 CGM.getMangleContext().mangleCXXVTT(RD, OutName);
360 llvm::StringRef Name = OutName.str();
361
362 D1(printf("vtt %s\n", RD->getNameAsCString()));
363
364 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
365 if (GV == 0 || GV->isDeclaration()) {
366 const llvm::Type *Int8PtrTy =
367 llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
368
Anders Carlsson19f191f2010-03-26 04:10:39 +0000369 VTTBuilder Builder(CGM, RD, GenerateDefinition);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000370
Anders Carlsson19f191f2010-03-26 04:10:39 +0000371 const llvm::ArrayType *Type =
372 llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size());
373
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000374 llvm::Constant *Init = 0;
375 if (GenerateDefinition)
Anders Carlsson19f191f2010-03-26 04:10:39 +0000376 Init = llvm::ConstantArray::get(Type, Builder.getVTTComponents().data(),
377 Builder.getVTTComponents().size());
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000378
379 llvm::GlobalVariable *OldGV = GV;
380 GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true,
381 Linkage, Init, Name);
382 CGM.setGlobalVisibility(GV, RD);
383
384 if (OldGV) {
385 GV->takeName(OldGV);
386 llvm::Constant *NewPtr =
387 llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
388 OldGV->replaceAllUsesWith(NewPtr);
389 OldGV->eraseFromParent();
390 }
391 }
392
393 return GV;
394}
395
Anders Carlssonaf440352010-03-23 04:11:45 +0000396llvm::GlobalVariable *CodeGenVTables::getVTT(const CXXRecordDecl *RD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000397 return GenerateVTT(llvm::GlobalValue::ExternalLinkage,
398 /*GenerateDefinition=*/false, RD);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000399}
400
Anders Carlssonaf440352010-03-23 04:11:45 +0000401bool CodeGenVTables::needsVTTParameter(GlobalDecl GD) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000402 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
403
404 // We don't have any virtual bases, just return early.
405 if (!MD->getParent()->getNumVBases())
406 return false;
407
408 // Check if we have a base constructor.
409 if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
410 return true;
411
412 // Check if we have a base destructor.
413 if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
414 return true;
415
416 return false;
417}
418
Anders Carlssonaf440352010-03-23 04:11:45 +0000419uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD,
420 const CXXRecordDecl *Base) {
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000421 ClassPairTy ClassPair(RD, Base);
422
423 SubVTTIndiciesTy::iterator I =
424 SubVTTIndicies.find(ClassPair);
425 if (I != SubVTTIndicies.end())
426 return I->second;
427
Anders Carlsson19f191f2010-03-26 04:10:39 +0000428 VTTBuilder Builder(CGM, RD, /*GenerateDefinition=*/false);
Anders Carlsson58b7eee2010-01-21 16:50:45 +0000429
430 for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
431 Builder.getSubVTTIndicies().begin(),
432 E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
433 // Insert all indices.
434 ClassPairTy ClassPair(RD, I->first);
435
436 SubVTTIndicies.insert(std::make_pair(ClassPair, I->second));
437 }
438
439 I = SubVTTIndicies.find(ClassPair);
440 assert(I != SubVTTIndicies.end() && "Did not find index!");
441
442 return I->second;
443}