blob: 7cfee33fde250214564fd0e3acd6d855b952dd57 [file] [log] [blame]
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001//===--- CGVtable.cpp - Emit LLVM Code for C++ vtables --------------------===//
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 virtual tables.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CodeGenModule.h"
15#include "CodeGenFunction.h"
Anders Carlssonf942ee02009-11-27 20:47:55 +000016#include "clang/AST/CXXInheritance.h"
Anders Carlsson2bb27f52009-10-11 22:13:54 +000017#include "clang/AST/RecordLayout.h"
Anders Carlssond420a312009-11-26 19:32:45 +000018#include "llvm/ADT/DenseSet.h"
Zhongxing Xu1721ef72009-11-13 05:46:16 +000019#include <cstdio>
Anders Carlsson2bb27f52009-10-11 22:13:54 +000020
21using namespace clang;
22using namespace CodeGen;
23
Anders Carlssond59885022009-11-27 22:21:51 +000024namespace {
Benjamin Kramer337e3a52009-11-28 19:45:26 +000025class VtableBuilder {
Anders Carlsson2bb27f52009-10-11 22:13:54 +000026public:
27 /// Index_t - Vtable index type.
28 typedef uint64_t Index_t;
29private:
30 std::vector<llvm::Constant *> &methods;
31 std::vector<llvm::Constant *> submethods;
32 llvm::Type *Ptr8Ty;
33 /// Class - The most derived class that this vtable is being built for.
34 const CXXRecordDecl *Class;
Mike Stump83066c82009-11-13 01:54:23 +000035 /// LayoutClass - The most derived class used for virtual base layout
36 /// information.
37 const CXXRecordDecl *LayoutClass;
Mike Stump653d0b92009-11-13 02:13:54 +000038 /// LayoutOffset - The offset for Class in LayoutClass.
39 uint64_t LayoutOffset;
Anders Carlsson2bb27f52009-10-11 22:13:54 +000040 /// BLayout - Layout for the most derived class that this vtable is being
41 /// built for.
42 const ASTRecordLayout &BLayout;
43 llvm::SmallSet<const CXXRecordDecl *, 32> IndirectPrimary;
44 llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase;
45 llvm::Constant *rtti;
46 llvm::LLVMContext &VMContext;
47 CodeGenModule &CGM; // Per-module state.
48 /// Index - Maps a method decl into a vtable index. Useful for virtual
49 /// dispatch codegen.
Anders Carlssonfb4dda42009-11-13 17:08:56 +000050 llvm::DenseMap<GlobalDecl, Index_t> Index;
51 llvm::DenseMap<GlobalDecl, Index_t> VCall;
52 llvm::DenseMap<GlobalDecl, Index_t> VCallOffset;
Mike Stumpcd6f9ed2009-11-06 23:27:42 +000053 // This is the offset to the nearest virtual base
Anders Carlssonfb4dda42009-11-13 17:08:56 +000054 llvm::DenseMap<GlobalDecl, Index_t> NonVirtualOffset;
Anders Carlsson2bb27f52009-10-11 22:13:54 +000055 llvm::DenseMap<const CXXRecordDecl *, Index_t> VBIndex;
Mike Stumpbb9ff052009-10-27 23:46:47 +000056
Anders Carlsson323bb042009-11-26 19:54:33 +000057 /// PureVirtualFunction - Points to __cxa_pure_virtual.
58 llvm::Constant *PureVirtualFn;
59
Anders Carlssona84b6e82009-12-04 02:01:07 +000060 /// VtableMethods - A data structure for keeping track of methods in a vtable.
61 /// Can add methods, override methods and iterate in vtable order.
62 class VtableMethods {
63 // MethodToIndexMap - Maps from a global decl to the index it has in the
64 // Methods vector.
65 llvm::DenseMap<GlobalDecl, uint64_t> MethodToIndexMap;
66
67 /// Methods - The methods, in vtable order.
68 typedef llvm::SmallVector<GlobalDecl, 16> MethodsVectorTy;
69 MethodsVectorTy Methods;
70
71 public:
72 /// AddMethod - Add a method to the vtable methods.
73 void AddMethod(GlobalDecl GD) {
74 assert(!MethodToIndexMap.count(GD) &&
75 "Method has already been added!");
76
77 MethodToIndexMap[GD] = Methods.size();
78 Methods.push_back(GD);
79 }
80
81 /// OverrideMethod - Replace a method with another.
82 void OverrideMethod(GlobalDecl OverriddenGD, GlobalDecl GD) {
83 llvm::DenseMap<GlobalDecl, uint64_t>::iterator i
84 = MethodToIndexMap.find(OverriddenGD);
85 assert(i != MethodToIndexMap.end() && "Did not find entry!");
86
87 // Get the index of the old decl.
88 uint64_t Index = i->second;
89
90 // Replace the old decl with the new decl.
91 Methods[Index] = GD;
92
93 // Now remove the old decl from the method to index map.
94 MethodToIndexMap.erase(i);
95
96 // And add the new.
97 MethodToIndexMap[GD] = Index;
98 }
99
100 MethodsVectorTy::size_type size() const {
101 return Methods.size();
102 }
103
104 void clear() {
105 MethodToIndexMap.clear();
106 Methods.clear();
107 }
108
109 GlobalDecl operator[](unsigned Index) const {
110 return Methods[Index];
111 }
112 };
113
114 /// Methods - The vtable methods we're currently building.
115 VtableMethods Methods;
116
Anders Carlsson6d771bc2009-11-26 03:25:13 +0000117 /// Thunk - Represents a single thunk.
118 struct Thunk {
Anders Carlsson80bc5d52009-12-03 02:41:55 +0000119 Thunk() { }
Anders Carlsson6d771bc2009-11-26 03:25:13 +0000120
Anders Carlsson597c7762009-12-04 02:14:12 +0000121 Thunk(const ThunkAdjustment &Adjustment)
122 : Adjustment(Adjustment) { }
Anders Carlsson6d771bc2009-11-26 03:25:13 +0000123
Anders Carlssond420a312009-11-26 19:32:45 +0000124 /// Adjustment - The thunk adjustment.
Anders Carlsson6d771bc2009-11-26 03:25:13 +0000125 ThunkAdjustment Adjustment;
126 };
Anders Carlssond420a312009-11-26 19:32:45 +0000127
128 /// Thunks - The thunks in a vtable.
Anders Carlsson29a1f752009-12-03 02:39:59 +0000129 typedef llvm::DenseMap<uint64_t, Thunk> ThunksMapTy;
Anders Carlsson6d771bc2009-11-26 03:25:13 +0000130 ThunksMapTy Thunks;
Anders Carlssond420a312009-11-26 19:32:45 +0000131
Anders Carlssonc521f952009-12-04 02:22:02 +0000132 /// BaseReturnTypes - Contains the base return types of methods who have been
133 /// overridden with methods whose return types require adjustment. Used for
134 /// generating covariant thunk information.
135 typedef llvm::DenseMap<uint64_t, CanQualType> BaseReturnTypesMapTy;
136 BaseReturnTypesMapTy BaseReturnTypes;
Anders Carlssond420a312009-11-26 19:32:45 +0000137
138 /// PureVirtualMethods - Pure virtual methods.
139 typedef llvm::DenseSet<GlobalDecl> PureVirtualMethodsSetTy;
140 PureVirtualMethodsSetTy PureVirtualMethods;
141
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000142 std::vector<Index_t> VCalls;
Mike Stump2cefe382009-11-12 20:47:57 +0000143
144 typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
Mike Stumpcd2b8212009-11-19 20:52:19 +0000145 // subAddressPoints - Used to hold the AddressPoints (offsets) into the built
146 // vtable for use in computing the initializers for the VTT.
147 llvm::DenseMap<CtorVtable_t, int64_t> &subAddressPoints;
Mike Stump2cefe382009-11-12 20:47:57 +0000148
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000149 typedef CXXRecordDecl::method_iterator method_iter;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000150 const bool Extern;
151 const uint32_t LLVMPointerWidth;
152 Index_t extra;
Mike Stump37dbe962009-10-15 02:04:03 +0000153 typedef std::vector<std::pair<const CXXRecordDecl *, int64_t> > Path_t;
Mike Stumpcd2b8212009-11-19 20:52:19 +0000154 static llvm::DenseMap<CtorVtable_t, int64_t>&
155 AllocAddressPoint(CodeGenModule &cgm, const CXXRecordDecl *l,
156 const CXXRecordDecl *c) {
157 CodeGenModule::AddrMap_t *&oref = cgm.AddressPoints[l];
158 if (oref == 0)
159 oref = new CodeGenModule::AddrMap_t;
160
161 llvm::DenseMap<CtorVtable_t, int64_t> *&ref = (*oref)[c];
162 if (ref == 0)
163 ref = new llvm::DenseMap<CtorVtable_t, int64_t>;
164 return *ref;
165 }
Anders Carlsson323bb042009-11-26 19:54:33 +0000166
167 /// getPureVirtualFn - Return the __cxa_pure_virtual function.
168 llvm::Constant* getPureVirtualFn() {
169 if (!PureVirtualFn) {
170 const llvm::FunctionType *Ty =
171 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
172 /*isVarArg=*/false);
173 PureVirtualFn = wrap(CGM.CreateRuntimeFunction(Ty, "__cxa_pure_virtual"));
174 }
175
176 return PureVirtualFn;
177 }
178
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000179public:
Mike Stump653d0b92009-11-13 02:13:54 +0000180 VtableBuilder(std::vector<llvm::Constant *> &meth, const CXXRecordDecl *c,
181 const CXXRecordDecl *l, uint64_t lo, CodeGenModule &cgm)
182 : methods(meth), Class(c), LayoutClass(l), LayoutOffset(lo),
Mike Stump83066c82009-11-13 01:54:23 +0000183 BLayout(cgm.getContext().getASTRecordLayout(l)),
Mike Stumpc01c2b82009-12-02 18:57:08 +0000184 rtti(cgm.GenerateRTTIRef(c)), VMContext(cgm.getModule().getContext()),
Anders Carlsson323bb042009-11-26 19:54:33 +0000185 CGM(cgm), PureVirtualFn(0),subAddressPoints(AllocAddressPoint(cgm, l, c)),
Mike Stump1960b202009-11-19 00:49:05 +0000186 Extern(!l->isInAnonymousNamespace()),
Anders Carlsson323bb042009-11-26 19:54:33 +0000187 LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000188 Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
189 }
190
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000191 llvm::DenseMap<GlobalDecl, Index_t> &getIndex() { return Index; }
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000192 llvm::DenseMap<const CXXRecordDecl *, Index_t> &getVBIndex()
193 { return VBIndex; }
194
195 llvm::Constant *wrap(Index_t i) {
196 llvm::Constant *m;
197 m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), i);
198 return llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty);
199 }
200
201 llvm::Constant *wrap(llvm::Constant *m) {
202 return llvm::ConstantExpr::getBitCast(m, Ptr8Ty);
203 }
204
Mike Stump8a96d3a2009-12-02 19:50:41 +0000205#define D1(x)
206//#define D1(X) do { if (getenv("DEBUG")) { X; } } while (0)
Mike Stump75ce5732009-10-31 20:06:59 +0000207
208 void GenerateVBaseOffsets(const CXXRecordDecl *RD, uint64_t Offset,
Mike Stump28431212009-10-13 22:54:56 +0000209 bool updateVBIndex, Index_t current_vbindex) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000210 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
211 e = RD->bases_end(); i != e; ++i) {
212 const CXXRecordDecl *Base =
213 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
Mike Stump28431212009-10-13 22:54:56 +0000214 Index_t next_vbindex = current_vbindex;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000215 if (i->isVirtual() && !SeenVBase.count(Base)) {
216 SeenVBase.insert(Base);
Mike Stump28431212009-10-13 22:54:56 +0000217 if (updateVBIndex) {
Mike Stump75ce5732009-10-31 20:06:59 +0000218 next_vbindex = (ssize_t)(-(VCalls.size()*LLVMPointerWidth/8)
Mike Stump28431212009-10-13 22:54:56 +0000219 - 3*LLVMPointerWidth/8);
220 VBIndex[Base] = next_vbindex;
221 }
Mike Stump75ce5732009-10-31 20:06:59 +0000222 int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8;
223 VCalls.push_back((0?700:0) + BaseOffset);
224 D1(printf(" vbase for %s at %d delta %d most derived %s\n",
225 Base->getNameAsCString(),
226 (int)-VCalls.size()-3, (int)BaseOffset,
227 Class->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000228 }
Mike Stump28431212009-10-13 22:54:56 +0000229 // We also record offsets for non-virtual bases to closest enclosing
230 // virtual base. We do this so that we don't have to search
231 // for the nearst virtual base class when generating thunks.
232 if (updateVBIndex && VBIndex.count(Base) == 0)
233 VBIndex[Base] = next_vbindex;
Mike Stump75ce5732009-10-31 20:06:59 +0000234 GenerateVBaseOffsets(Base, Offset, updateVBIndex, next_vbindex);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000235 }
236 }
237
238 void StartNewTable() {
239 SeenVBase.clear();
240 }
241
Mike Stump8bccbfd2009-10-15 09:30:16 +0000242 Index_t getNVOffset_1(const CXXRecordDecl *D, const CXXRecordDecl *B,
243 Index_t Offset = 0) {
244
245 if (B == D)
246 return Offset;
247
248 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(D);
249 for (CXXRecordDecl::base_class_const_iterator i = D->bases_begin(),
250 e = D->bases_end(); i != e; ++i) {
251 const CXXRecordDecl *Base =
252 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
253 int64_t BaseOffset = 0;
254 if (!i->isVirtual())
255 BaseOffset = Offset + Layout.getBaseClassOffset(Base);
256 int64_t o = getNVOffset_1(Base, B, BaseOffset);
257 if (o >= 0)
258 return o;
259 }
260
261 return -1;
262 }
263
264 /// getNVOffset - Returns the non-virtual offset for the given (B) base of the
265 /// derived class D.
266 Index_t getNVOffset(QualType qB, QualType qD) {
Mike Stump46271322009-11-03 19:03:17 +0000267 qD = qD->getPointeeType();
268 qB = qB->getPointeeType();
Mike Stump8bccbfd2009-10-15 09:30:16 +0000269 CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
270 CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
271 int64_t o = getNVOffset_1(D, B);
272 if (o >= 0)
273 return o;
274
275 assert(false && "FIXME: non-virtual base not found");
276 return 0;
277 }
278
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000279 /// getVbaseOffset - Returns the index into the vtable for the virtual base
280 /// offset for the given (B) virtual base of the derived class D.
281 Index_t getVbaseOffset(QualType qB, QualType qD) {
Mike Stump46271322009-11-03 19:03:17 +0000282 qD = qD->getPointeeType();
283 qB = qB->getPointeeType();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000284 CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
285 CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
286 if (D != Class)
Eli Friedman03aa2f12009-11-30 01:19:33 +0000287 return CGM.getVtableInfo().getVirtualBaseOffsetIndex(D, B);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000288 llvm::DenseMap<const CXXRecordDecl *, Index_t>::iterator i;
289 i = VBIndex.find(B);
290 if (i != VBIndex.end())
291 return i->second;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000292
Mike Stump28431212009-10-13 22:54:56 +0000293 assert(false && "FIXME: Base not found");
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000294 return 0;
295 }
296
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000297 bool OverrideMethod(GlobalDecl GD, llvm::Constant *m,
Mike Stump8bccbfd2009-10-15 09:30:16 +0000298 bool MorallyVirtual, Index_t OverrideOffset,
Anders Carlssonca1bf682009-12-03 01:54:02 +0000299 Index_t Offset, int64_t CurrentVBaseOffset);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000300
301 void InstallThunks() {
Anders Carlssonc521f952009-12-04 02:22:02 +0000302 for (BaseReturnTypesMapTy::const_iterator i = BaseReturnTypes.begin(),
303 e = BaseReturnTypes.end(); i != e; ++i) {
Anders Carlsson8c889ab2009-12-04 02:11:21 +0000304 uint64_t Index = i->first;
305 GlobalDecl GD = Methods[Index];
306
Anders Carlsson2bd3c0f2009-12-03 01:58:20 +0000307 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
308 if (MD->isPure())
309 continue;
310
Anders Carlssonc521f952009-12-04 02:22:02 +0000311 QualType BaseReturnType = i->second;
312
Anders Carlsson06c14b62009-12-03 02:16:14 +0000313 assert(Index == VtableBuilder::Index[GD] && "Thunk index mismatch!");
Anders Carlsson2bd3c0f2009-12-03 01:58:20 +0000314
315 // Check if there is an adjustment for the 'this' pointer.
316 ThunkAdjustment ThisAdjustment;
Anders Carlssonc6089fd2009-12-03 07:30:40 +0000317 ThunksMapTy::iterator it = Thunks.find(Index);
318 if (it != Thunks.end()) {
319 ThisAdjustment = it->second.Adjustment;
Anders Carlsson2bd3c0f2009-12-03 01:58:20 +0000320
Anders Carlssonc6089fd2009-12-03 07:30:40 +0000321 Thunks.erase(it);
Anders Carlsson2bd3c0f2009-12-03 01:58:20 +0000322 }
Anders Carlsson657f1392009-12-03 02:32:59 +0000323
324 // Construct the return adjustment.
Anders Carlssondabfa3c2009-12-03 03:28:24 +0000325 QualType DerivedType =
326 MD->getType()->getAs<FunctionType>()->getResultType();
327
328 int64_t NonVirtualAdjustment =
Anders Carlssonc521f952009-12-04 02:22:02 +0000329 getNVOffset(BaseReturnType, DerivedType) / 8;
Anders Carlssondabfa3c2009-12-03 03:28:24 +0000330
331 int64_t VirtualAdjustment =
Anders Carlssonc521f952009-12-04 02:22:02 +0000332 getVbaseOffset(BaseReturnType, DerivedType);
Anders Carlssondabfa3c2009-12-03 03:28:24 +0000333
334 ThunkAdjustment ReturnAdjustment(NonVirtualAdjustment, VirtualAdjustment);
Anders Carlsson657f1392009-12-03 02:32:59 +0000335
336 CovariantThunkAdjustment Adjustment(ThisAdjustment, ReturnAdjustment);
Anders Carlsson06c14b62009-12-03 02:16:14 +0000337 submethods[Index] = CGM.BuildCovariantThunk(MD, Extern, Adjustment);
Anders Carlsson2bd3c0f2009-12-03 01:58:20 +0000338 }
Anders Carlssonc521f952009-12-04 02:22:02 +0000339 BaseReturnTypes.clear();
Anders Carlssonc38b40a2009-12-03 02:03:29 +0000340
Anders Carlsson6d771bc2009-11-26 03:25:13 +0000341 for (ThunksMapTy::const_iterator i = Thunks.begin(), e = Thunks.end();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000342 i != e; ++i) {
Anders Carlsson80bc5d52009-12-03 02:41:55 +0000343 uint64_t Index = i->first;
Anders Carlsson597c7762009-12-04 02:14:12 +0000344 GlobalDecl GD = Methods[Index];
Anders Carlsson80bc5d52009-12-03 02:41:55 +0000345 const Thunk& Thunk = i->second;
346
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000347 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
Anders Carlsson6d771bc2009-11-26 03:25:13 +0000348 assert(!MD->isPure() && "Can't thunk pure virtual methods!");
Anders Carlsson29a1f752009-12-03 02:39:59 +0000349
350 assert(Index == VtableBuilder::Index[GD] && "Thunk index mismatch!");
Anders Carlsson6d771bc2009-11-26 03:25:13 +0000351
Mike Stumpe2d4a2c2009-12-03 03:47:56 +0000352 submethods[Index] = CGM.BuildThunk(GD, Extern, Thunk.Adjustment);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000353 }
354 Thunks.clear();
Anders Carlsson6d771bc2009-11-26 03:25:13 +0000355
Anders Carlssond420a312009-11-26 19:32:45 +0000356 for (PureVirtualMethodsSetTy::iterator i = PureVirtualMethods.begin(),
357 e = PureVirtualMethods.end(); i != e; ++i) {
358 GlobalDecl GD = *i;
Anders Carlsson323bb042009-11-26 19:54:33 +0000359 submethods[Index[GD]] = getPureVirtualFn();
Mike Stumpbb9ff052009-10-27 23:46:47 +0000360 }
Anders Carlssond420a312009-11-26 19:32:45 +0000361 PureVirtualMethods.clear();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000362 }
363
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000364 llvm::Constant *WrapAddrOf(GlobalDecl GD) {
365 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
366
Anders Carlsson64457732009-11-24 05:08:52 +0000367 const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVtable(MD);
Mike Stump18e8b472009-10-27 23:36:26 +0000368
Mike Stumpcdeb8002009-12-03 16:55:20 +0000369 return wrap(CGM.GetAddrOfFunction(GD, Ty));
Mike Stump18e8b472009-10-27 23:36:26 +0000370 }
371
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000372 void OverrideMethods(Path_t *Path, bool MorallyVirtual, int64_t Offset,
373 int64_t CurrentVBaseOffset) {
Mike Stump37dbe962009-10-15 02:04:03 +0000374 for (Path_t::reverse_iterator i = Path->rbegin(),
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000375 e = Path->rend(); i != e; ++i) {
376 const CXXRecordDecl *RD = i->first;
Mike Stump8bccbfd2009-10-15 09:30:16 +0000377 int64_t OverrideOffset = i->second;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000378 for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
379 ++mi) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000380 const CXXMethodDecl *MD = *mi;
381
382 if (!MD->isVirtual())
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000383 continue;
384
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000385 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
386 // Override both the complete and the deleting destructor.
387 GlobalDecl CompDtor(DD, Dtor_Complete);
388 OverrideMethod(CompDtor, WrapAddrOf(CompDtor), MorallyVirtual,
389 OverrideOffset, Offset, CurrentVBaseOffset);
390
391 GlobalDecl DeletingDtor(DD, Dtor_Deleting);
392 OverrideMethod(DeletingDtor, WrapAddrOf(DeletingDtor), MorallyVirtual,
393 OverrideOffset, Offset, CurrentVBaseOffset);
394 } else {
395 OverrideMethod(MD, WrapAddrOf(MD), MorallyVirtual, OverrideOffset,
396 Offset, CurrentVBaseOffset);
397 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000398 }
399 }
400 }
401
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000402 void AddMethod(const GlobalDecl GD, bool MorallyVirtual, Index_t Offset,
Eli Friedman03aa2f12009-11-30 01:19:33 +0000403 int64_t CurrentVBaseOffset) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000404 llvm::Constant *m = WrapAddrOf(GD);
Mike Stump18e8b472009-10-27 23:36:26 +0000405
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000406 // If we can find a previously allocated slot for this, reuse it.
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000407 if (OverrideMethod(GD, m, MorallyVirtual, Offset, Offset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000408 CurrentVBaseOffset))
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000409 return;
410
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000411 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
412
Anders Carlssoncdf18982009-12-04 02:08:24 +0000413 // We didn't find an entry in the vtable that we could use, add a new
414 // entry.
415 Methods.AddMethod(GD);
416
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000417 Index[GD] = submethods.size();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000418 submethods.push_back(m);
Mike Stumpc5a332c2009-11-13 23:45:53 +0000419 D1(printf(" vfn for %s at %d\n", MD->getNameAsString().c_str(),
420 (int)Index[GD]));
Mike Stump375faa82009-10-28 00:35:46 +0000421 if (MD->isPure())
Anders Carlssond420a312009-11-26 19:32:45 +0000422 PureVirtualMethods.insert(GD);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000423 if (MorallyVirtual) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000424 VCallOffset[GD] = Offset/8;
425 Index_t &idx = VCall[GD];
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000426 // Allocate the first one, after that, we reuse the previous one.
427 if (idx == 0) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000428 NonVirtualOffset[GD] = CurrentVBaseOffset/8 - Offset/8;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000429 idx = VCalls.size()+1;
430 VCalls.push_back(0);
Mike Stump75ce5732009-10-31 20:06:59 +0000431 D1(printf(" vcall for %s at %d with delta %d\n",
Mike Stumpc5a332c2009-11-13 23:45:53 +0000432 MD->getNameAsString().c_str(), (int)-VCalls.size()-3, 0));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000433 }
434 }
435 }
436
437 void AddMethods(const CXXRecordDecl *RD, bool MorallyVirtual,
Eli Friedman03aa2f12009-11-30 01:19:33 +0000438 Index_t Offset, int64_t CurrentVBaseOffset) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000439 for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000440 ++mi) {
441 const CXXMethodDecl *MD = *mi;
442 if (!MD->isVirtual())
443 continue;
444
445 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
446 // For destructors, add both the complete and the deleting destructor
447 // to the vtable.
448 AddMethod(GlobalDecl(DD, Dtor_Complete), MorallyVirtual, Offset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000449 CurrentVBaseOffset);
Eli Friedman03aa2f12009-11-30 01:19:33 +0000450 AddMethod(GlobalDecl(DD, Dtor_Deleting), MorallyVirtual, Offset,
451 CurrentVBaseOffset);
452 } else
453 AddMethod(MD, MorallyVirtual, Offset, CurrentVBaseOffset);
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000454 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000455 }
456
457 void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
458 const CXXRecordDecl *PrimaryBase,
459 bool PrimaryBaseWasVirtual, bool MorallyVirtual,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000460 int64_t Offset, int64_t CurrentVBaseOffset,
461 Path_t *Path) {
Mike Stump37dbe962009-10-15 02:04:03 +0000462 Path->push_back(std::make_pair(RD, Offset));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000463 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
464 e = RD->bases_end(); i != e; ++i) {
465 if (i->isVirtual())
466 continue;
467 const CXXRecordDecl *Base =
468 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
469 if (Base != PrimaryBase || PrimaryBaseWasVirtual) {
470 uint64_t o = Offset + Layout.getBaseClassOffset(Base);
471 StartNewTable();
Mike Stump653d0b92009-11-13 02:13:54 +0000472 GenerateVtableForBase(Base, o, MorallyVirtual, false,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000473 CurrentVBaseOffset, Path);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000474 }
475 }
Mike Stump37dbe962009-10-15 02:04:03 +0000476 Path->pop_back();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000477 }
478
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000479// #define D(X) do { X; } while (0)
480#define D(X)
481
482 void insertVCalls(int InsertionPoint) {
483 llvm::Constant *e = 0;
Mike Stump75ce5732009-10-31 20:06:59 +0000484 D1(printf("============= combining vbase/vcall\n"));
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000485 D(VCalls.insert(VCalls.begin(), 673));
486 D(VCalls.push_back(672));
Mike Stump8bccbfd2009-10-15 09:30:16 +0000487 methods.insert(methods.begin() + InsertionPoint, VCalls.size(), e);
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000488 // The vcalls come first...
489 for (std::vector<Index_t>::reverse_iterator i = VCalls.rbegin(),
490 e = VCalls.rend();
491 i != e; ++i)
492 methods[InsertionPoint++] = wrap((0?600:0) + *i);
493 VCalls.clear();
Mike Stump9f23a142009-11-10 02:30:51 +0000494 VCall.clear();
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000495 }
496
Mike Stump559387f2009-11-13 23:13:20 +0000497 void AddAddressPoints(const CXXRecordDecl *RD, uint64_t Offset,
498 Index_t AddressPoint) {
499 D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n",
500 RD->getNameAsCString(), Class->getNameAsCString(),
501 LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
Mike Stumpcd2b8212009-11-19 20:52:19 +0000502 subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
Mike Stump559387f2009-11-13 23:13:20 +0000503
504 // Now also add the address point for all our primary bases.
505 while (1) {
506 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
507 RD = Layout.getPrimaryBase();
508 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
509 // FIXME: Double check this.
510 if (RD == 0)
511 break;
512 if (PrimaryBaseWasVirtual &&
513 BLayout.getVBaseClassOffset(RD) != Offset)
514 break;
515 D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n",
516 RD->getNameAsCString(), Class->getNameAsCString(),
517 LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
Mike Stumpcd2b8212009-11-19 20:52:19 +0000518 subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
Mike Stump559387f2009-11-13 23:13:20 +0000519 }
520 }
521
522
Mike Stump75ce5732009-10-31 20:06:59 +0000523 Index_t end(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
524 const CXXRecordDecl *PrimaryBase, bool PrimaryBaseWasVirtual,
525 bool MorallyVirtual, int64_t Offset, bool ForVirtualBase,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000526 int64_t CurrentVBaseOffset,
Mike Stump75ce5732009-10-31 20:06:59 +0000527 Path_t *Path) {
Mike Stump37dbe962009-10-15 02:04:03 +0000528 bool alloc = false;
529 if (Path == 0) {
530 alloc = true;
531 Path = new Path_t;
532 }
533
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000534 StartNewTable();
535 extra = 0;
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000536 bool DeferVCalls = MorallyVirtual || ForVirtualBase;
537 int VCallInsertionPoint = methods.size();
538 if (!DeferVCalls) {
539 insertVCalls(VCallInsertionPoint);
Mike Stump8bccbfd2009-10-15 09:30:16 +0000540 } else
541 // FIXME: just for extra, or for all uses of VCalls.size post this?
542 extra = -VCalls.size();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000543
Mike Stump653d0b92009-11-13 02:13:54 +0000544 methods.push_back(wrap(-((Offset-LayoutOffset)/8)));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000545 methods.push_back(rtti);
546 Index_t AddressPoint = methods.size();
547
Anders Carlssoncdf18982009-12-04 02:08:24 +0000548 assert(submethods.size() == Methods.size() && "Method size mismatch!");
549
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000550 InstallThunks();
Mike Stump75ce5732009-10-31 20:06:59 +0000551 D1(printf("============= combining methods\n"));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000552 methods.insert(methods.end(), submethods.begin(), submethods.end());
Anders Carlssoncdf18982009-12-04 02:08:24 +0000553
554 Methods.clear();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000555 submethods.clear();
556
557 // and then the non-virtual bases.
558 NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000559 MorallyVirtual, Offset, CurrentVBaseOffset, Path);
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000560
561 if (ForVirtualBase) {
Mike Stump2cefe382009-11-12 20:47:57 +0000562 // FIXME: We're adding to VCalls in callers, we need to do the overrides
563 // in the inner part, so that we know the complete set of vcalls during
564 // the build and don't have to insert into methods. Saving out the
565 // AddressPoint here, would need to be fixed, if we didn't do that. Also
566 // retroactively adding vcalls for overrides later wind up in the wrong
567 // place, the vcall slot has to be alloted during the walk of the base
568 // when the function is first introduces.
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000569 AddressPoint += VCalls.size();
Mike Stump2cefe382009-11-12 20:47:57 +0000570 insertVCalls(VCallInsertionPoint);
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000571 }
572
Mike Stump559387f2009-11-13 23:13:20 +0000573 AddAddressPoints(RD, Offset, AddressPoint);
Mike Stump2cefe382009-11-12 20:47:57 +0000574
Mike Stump37dbe962009-10-15 02:04:03 +0000575 if (alloc) {
576 delete Path;
577 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000578 return AddressPoint;
579 }
580
Mike Stump75ce5732009-10-31 20:06:59 +0000581 void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
582 bool updateVBIndex, Index_t current_vbindex,
Eli Friedman03aa2f12009-11-30 01:19:33 +0000583 int64_t CurrentVBaseOffset) {
Mike Stump75ce5732009-10-31 20:06:59 +0000584 if (!RD->isDynamicClass())
585 return;
586
587 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
588 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
589 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
590
591 // vtables are composed from the chain of primaries.
592 if (PrimaryBase) {
593 D1(printf(" doing primaries for %s most derived %s\n",
594 RD->getNameAsCString(), Class->getNameAsCString()));
595
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000596 int BaseCurrentVBaseOffset = CurrentVBaseOffset;
597 if (PrimaryBaseWasVirtual)
598 BaseCurrentVBaseOffset = BLayout.getVBaseClassOffset(PrimaryBase);
599
Mike Stump75ce5732009-10-31 20:06:59 +0000600 if (!PrimaryBaseWasVirtual)
601 Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
Eli Friedman03aa2f12009-11-30 01:19:33 +0000602 updateVBIndex, current_vbindex, BaseCurrentVBaseOffset);
Mike Stump75ce5732009-10-31 20:06:59 +0000603 }
604
605 D1(printf(" doing vcall entries for %s most derived %s\n",
606 RD->getNameAsCString(), Class->getNameAsCString()));
607
608 // And add the virtuals for the class to the primary vtable.
Eli Friedman03aa2f12009-11-30 01:19:33 +0000609 AddMethods(RD, MorallyVirtual, Offset, CurrentVBaseOffset);
Mike Stump75ce5732009-10-31 20:06:59 +0000610 }
611
612 void VBPrimaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
613 bool updateVBIndex, Index_t current_vbindex,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000614 bool RDisVirtualBase, int64_t CurrentVBaseOffset,
Eli Friedman03aa2f12009-11-30 01:19:33 +0000615 bool bottom) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000616 if (!RD->isDynamicClass())
617 return;
618
619 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
620 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
621 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
622
623 // vtables are composed from the chain of primaries.
624 if (PrimaryBase) {
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000625 int BaseCurrentVBaseOffset = CurrentVBaseOffset;
626 if (PrimaryBaseWasVirtual) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000627 IndirectPrimary.insert(PrimaryBase);
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000628 BaseCurrentVBaseOffset = BLayout.getVBaseClassOffset(PrimaryBase);
629 }
Mike Stump75ce5732009-10-31 20:06:59 +0000630
631 D1(printf(" doing primaries for %s most derived %s\n",
632 RD->getNameAsCString(), Class->getNameAsCString()));
633
634 VBPrimaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000635 updateVBIndex, current_vbindex, PrimaryBaseWasVirtual,
Eli Friedman03aa2f12009-11-30 01:19:33 +0000636 BaseCurrentVBaseOffset, false);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000637 }
638
Mike Stump75ce5732009-10-31 20:06:59 +0000639 D1(printf(" doing vbase entries for %s most derived %s\n",
640 RD->getNameAsCString(), Class->getNameAsCString()));
641 GenerateVBaseOffsets(RD, Offset, updateVBIndex, current_vbindex);
642
643 if (RDisVirtualBase || bottom) {
644 Primaries(RD, MorallyVirtual, Offset, updateVBIndex, current_vbindex,
Eli Friedman03aa2f12009-11-30 01:19:33 +0000645 CurrentVBaseOffset);
Mike Stump75ce5732009-10-31 20:06:59 +0000646 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000647 }
648
Mike Stump653d0b92009-11-13 02:13:54 +0000649 int64_t GenerateVtableForBase(const CXXRecordDecl *RD, int64_t Offset = 0,
650 bool MorallyVirtual = false,
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000651 bool ForVirtualBase = false,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000652 int CurrentVBaseOffset = 0,
Mike Stump37dbe962009-10-15 02:04:03 +0000653 Path_t *Path = 0) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000654 if (!RD->isDynamicClass())
655 return 0;
656
Mike Stumpfa818082009-11-13 02:35:38 +0000657 // Construction vtable don't need parts that have no virtual bases and
658 // aren't morally virtual.
659 if ((LayoutClass != Class) && RD->getNumVBases() == 0 && !MorallyVirtual)
660 return 0;
661
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000662 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
663 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
664 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
665
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000666 extra = 0;
Mike Stump75ce5732009-10-31 20:06:59 +0000667 D1(printf("building entries for base %s most derived %s\n",
668 RD->getNameAsCString(), Class->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000669
Mike Stump75ce5732009-10-31 20:06:59 +0000670 if (ForVirtualBase)
671 extra = VCalls.size();
672
673 VBPrimaries(RD, MorallyVirtual, Offset, !ForVirtualBase, 0, ForVirtualBase,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000674 CurrentVBaseOffset, true);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000675
676 if (Path)
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000677 OverrideMethods(Path, MorallyVirtual, Offset, CurrentVBaseOffset);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000678
Mike Stump75ce5732009-10-31 20:06:59 +0000679 return end(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual, MorallyVirtual,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000680 Offset, ForVirtualBase, CurrentVBaseOffset, Path);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000681 }
682
683 void GenerateVtableForVBases(const CXXRecordDecl *RD,
684 int64_t Offset = 0,
Mike Stump37dbe962009-10-15 02:04:03 +0000685 Path_t *Path = 0) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000686 bool alloc = false;
687 if (Path == 0) {
688 alloc = true;
Mike Stump37dbe962009-10-15 02:04:03 +0000689 Path = new Path_t;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000690 }
691 // FIXME: We also need to override using all paths to a virtual base,
692 // right now, we just process the first path
693 Path->push_back(std::make_pair(RD, Offset));
694 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
695 e = RD->bases_end(); i != e; ++i) {
696 const CXXRecordDecl *Base =
697 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
698 if (i->isVirtual() && !IndirectPrimary.count(Base)) {
699 // Mark it so we don't output it twice.
700 IndirectPrimary.insert(Base);
701 StartNewTable();
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000702 VCall.clear();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000703 int64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000704 int64_t CurrentVBaseOffset = BaseOffset;
Mike Stump75ce5732009-10-31 20:06:59 +0000705 D1(printf("vtable %s virtual base %s\n",
706 Class->getNameAsCString(), Base->getNameAsCString()));
Mike Stump653d0b92009-11-13 02:13:54 +0000707 GenerateVtableForBase(Base, BaseOffset, true, true, CurrentVBaseOffset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000708 Path);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000709 }
Mike Stump2cefe382009-11-12 20:47:57 +0000710 int64_t BaseOffset;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000711 if (i->isVirtual())
712 BaseOffset = BLayout.getVBaseClassOffset(Base);
Mike Stump2cefe382009-11-12 20:47:57 +0000713 else {
714 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
715 BaseOffset = Offset + Layout.getBaseClassOffset(Base);
716 }
717
Mike Stump37dbe962009-10-15 02:04:03 +0000718 if (Base->getNumVBases()) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000719 GenerateVtableForVBases(Base, BaseOffset, Path);
Mike Stump37dbe962009-10-15 02:04:03 +0000720 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000721 }
722 Path->pop_back();
723 if (alloc)
724 delete Path;
725 }
726};
Anders Carlssonca1bf682009-12-03 01:54:02 +0000727} // end anonymous namespace
728
Anders Carlsson657f1392009-12-03 02:32:59 +0000729/// TypeConversionRequiresAdjustment - Returns whether conversion from a
730/// derived type to a base type requires adjustment.
731static bool
732TypeConversionRequiresAdjustment(ASTContext &Ctx,
733 const CXXRecordDecl *DerivedDecl,
734 const CXXRecordDecl *BaseDecl) {
735 CXXBasePaths Paths(/*FindAmbiguities=*/false,
736 /*RecordPaths=*/true, /*DetectVirtual=*/true);
737 if (!const_cast<CXXRecordDecl *>(DerivedDecl)->
738 isDerivedFrom(const_cast<CXXRecordDecl *>(BaseDecl), Paths)) {
739 assert(false && "Class must be derived from the passed in base class!");
740 return false;
741 }
742
743 // If we found a virtual base we always want to require adjustment.
744 if (Paths.getDetectedVirtual())
745 return true;
746
747 const CXXBasePath &Path = Paths.front();
748
749 for (size_t Start = 0, End = Path.size(); Start != End; ++Start) {
750 const CXXBasePathElement &Element = Path[Start];
751
752 // Check the base class offset.
753 const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Element.Class);
754
755 const RecordType *BaseType = Element.Base->getType()->getAs<RecordType>();
756 const CXXRecordDecl *Base = cast<CXXRecordDecl>(BaseType->getDecl());
757
758 if (Layout.getBaseClassOffset(Base) != 0) {
759 // This requires an adjustment.
760 return true;
761 }
762 }
763
764 return false;
765}
766
767static bool
768TypeConversionRequiresAdjustment(ASTContext &Ctx,
769 QualType DerivedType, QualType BaseType) {
770 // Canonicalize the types.
771 QualType CanDerivedType = Ctx.getCanonicalType(DerivedType);
772 QualType CanBaseType = Ctx.getCanonicalType(BaseType);
773
774 assert(CanDerivedType->getTypeClass() == CanBaseType->getTypeClass() &&
775 "Types must have same type class!");
776
777 if (CanDerivedType == CanBaseType) {
778 // No adjustment needed.
779 return false;
780 }
781
782 if (const ReferenceType *RT = dyn_cast<ReferenceType>(CanDerivedType)) {
783 CanDerivedType = RT->getPointeeType();
784 CanBaseType = cast<ReferenceType>(CanBaseType)->getPointeeType();
785 } else if (const PointerType *PT = dyn_cast<PointerType>(CanDerivedType)) {
786 CanDerivedType = PT->getPointeeType();
787 CanBaseType = cast<PointerType>(CanBaseType)->getPointeeType();
788 } else {
789 assert(false && "Unexpected return type!");
790 }
791
792 if (CanDerivedType == CanBaseType) {
793 // No adjustment needed.
794 return false;
795 }
796
797 const CXXRecordDecl *DerivedDecl =
Anders Carlssondabfa3c2009-12-03 03:28:24 +0000798 cast<CXXRecordDecl>(cast<RecordType>(CanDerivedType)->getDecl());
Anders Carlsson657f1392009-12-03 02:32:59 +0000799
800 const CXXRecordDecl *BaseDecl =
801 cast<CXXRecordDecl>(cast<RecordType>(CanBaseType)->getDecl());
802
803 return TypeConversionRequiresAdjustment(Ctx, DerivedDecl, BaseDecl);
804}
805
Anders Carlssonca1bf682009-12-03 01:54:02 +0000806bool VtableBuilder::OverrideMethod(GlobalDecl GD, llvm::Constant *m,
807 bool MorallyVirtual, Index_t OverrideOffset,
808 Index_t Offset, int64_t CurrentVBaseOffset) {
809 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
810
811 const bool isPure = MD->isPure();
812 typedef CXXMethodDecl::method_iterator meth_iter;
813 // FIXME: Should OverrideOffset's be Offset?
814
815 // FIXME: Don't like the nested loops. For very large inheritance
816 // heirarchies we could have a table on the side with the final overridder
817 // and just replace each instance of an overridden method once. Would be
818 // nice to measure the cost/benefit on real code.
819
820 for (meth_iter mi = MD->begin_overridden_methods(),
821 e = MD->end_overridden_methods();
822 mi != e; ++mi) {
823 GlobalDecl OGD;
824
825 const CXXMethodDecl *OMD = *mi;
826 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(OMD))
827 OGD = GlobalDecl(DD, GD.getDtorType());
828 else
829 OGD = OMD;
830
831 llvm::Constant *om;
832 om = WrapAddrOf(OGD);
833 om = llvm::ConstantExpr::getBitCast(om, Ptr8Ty);
834
835 for (Index_t i = 0, e = submethods.size();
836 i != e; ++i) {
837 // FIXME: begin_overridden_methods might be too lax, covariance */
838 if (submethods[i] != om)
839 continue;
Anders Carlsson657f1392009-12-03 02:32:59 +0000840
841 QualType ReturnType =
842 MD->getType()->getAs<FunctionType>()->getResultType();
843 QualType OverriddenReturnType =
844 OMD->getType()->getAs<FunctionType>()->getResultType();
845
846 // Check if we need a return type adjustment.
847 if (TypeConversionRequiresAdjustment(CGM.getContext(), ReturnType,
848 OverriddenReturnType)) {
Anders Carlssonc521f952009-12-04 02:22:02 +0000849 CanQualType &BaseReturnType = BaseReturnTypes[i];
Anders Carlsson2ca285f2009-12-03 02:22:59 +0000850
Anders Carlsson657f1392009-12-03 02:32:59 +0000851 // Get the canonical return type.
852 CanQualType CanReturnType =
853 CGM.getContext().getCanonicalType(ReturnType);
854
855 // Insert the base return type.
Anders Carlssonc521f952009-12-04 02:22:02 +0000856 if (BaseReturnType.isNull())
857 BaseReturnType =
Anders Carlsson657f1392009-12-03 02:32:59 +0000858 CGM.getContext().getCanonicalType(OverriddenReturnType);
Anders Carlssonca1bf682009-12-03 01:54:02 +0000859 }
Anders Carlsson657f1392009-12-03 02:32:59 +0000860
Anders Carlssoncdf18982009-12-04 02:08:24 +0000861 Methods.OverrideMethod(OGD, GD);
862
Anders Carlssonca1bf682009-12-03 01:54:02 +0000863 Index[GD] = i;
864 submethods[i] = m;
865 if (isPure)
866 PureVirtualMethods.insert(GD);
867 PureVirtualMethods.erase(OGD);
Anders Carlsson29a1f752009-12-03 02:39:59 +0000868 Thunks.erase(i);
Anders Carlssonca1bf682009-12-03 01:54:02 +0000869 if (MorallyVirtual || VCall.count(OGD)) {
870 Index_t &idx = VCall[OGD];
871 if (idx == 0) {
872 NonVirtualOffset[GD] = -OverrideOffset/8 + CurrentVBaseOffset/8;
873 VCallOffset[GD] = OverrideOffset/8;
874 idx = VCalls.size()+1;
875 VCalls.push_back(0);
876 D1(printf(" vcall for %s at %d with delta %d most derived %s\n",
877 MD->getNameAsString().c_str(), (int)-idx-3,
878 (int)VCalls[idx-1], Class->getNameAsCString()));
879 } else {
880 NonVirtualOffset[GD] = NonVirtualOffset[OGD];
881 VCallOffset[GD] = VCallOffset[OGD];
882 VCalls[idx-1] = -VCallOffset[OGD] + OverrideOffset/8;
883 D1(printf(" vcall patch for %s at %d with delta %d most derived %s\n",
884 MD->getNameAsString().c_str(), (int)-idx-3,
885 (int)VCalls[idx-1], Class->getNameAsCString()));
886 }
887 VCall[GD] = idx;
888 int64_t NonVirtualAdjustment = NonVirtualOffset[GD];
889 int64_t VirtualAdjustment =
890 -((idx + extra + 2) * LLVMPointerWidth / 8);
891
892 // Optimize out virtual adjustments of 0.
893 if (VCalls[idx-1] == 0)
894 VirtualAdjustment = 0;
895
896 ThunkAdjustment ThisAdjustment(NonVirtualAdjustment,
897 VirtualAdjustment);
898
Anders Carlsson2bd3c0f2009-12-03 01:58:20 +0000899 if (!isPure && !ThisAdjustment.isEmpty())
Anders Carlsson597c7762009-12-04 02:14:12 +0000900 Thunks[i] = Thunk(ThisAdjustment);
Anders Carlssonca1bf682009-12-03 01:54:02 +0000901 return true;
902 }
903
904 // FIXME: finish off
905 int64_t NonVirtualAdjustment = VCallOffset[OGD] - OverrideOffset/8;
906
Anders Carlsson2ca285f2009-12-03 02:22:59 +0000907 if (NonVirtualAdjustment) {
Anders Carlssonca1bf682009-12-03 01:54:02 +0000908 ThunkAdjustment ThisAdjustment(NonVirtualAdjustment, 0);
909
Anders Carlsson2bd3c0f2009-12-03 01:58:20 +0000910 if (!isPure)
Anders Carlsson597c7762009-12-04 02:14:12 +0000911 Thunks[i] = Thunk(ThisAdjustment);
Anders Carlssonca1bf682009-12-03 01:54:02 +0000912 }
913 return true;
914 }
915 }
916
917 return false;
Anders Carlssond59885022009-11-27 22:21:51 +0000918}
919
Anders Carlssonf942ee02009-11-27 20:47:55 +0000920void CGVtableInfo::ComputeMethodVtableIndices(const CXXRecordDecl *RD) {
921
922 // Itanium C++ ABI 2.5.2:
923 // The order of the virtual function pointers in a virtual table is the
924 // order of declaration of the corresponding member functions in the class.
925 //
926 // There is an entry for any virtual function declared in a class,
927 // whether it is a new function or overrides a base class function,
928 // unless it overrides a function from the primary base, and conversion
929 // between their return types does not require an adjustment.
930
931 int64_t CurrentIndex = 0;
932
933 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
934 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
935
936 if (PrimaryBase) {
Anders Carlssonc920fa22009-11-30 19:43:26 +0000937 assert(PrimaryBase->isDefinition() &&
938 "Should have the definition decl of the primary base!");
Anders Carlssonf942ee02009-11-27 20:47:55 +0000939
940 // Since the record decl shares its vtable pointer with the primary base
941 // we need to start counting at the end of the primary base's vtable.
942 CurrentIndex = getNumVirtualFunctionPointers(PrimaryBase);
943 }
944
945 const CXXDestructorDecl *ImplicitVirtualDtor = 0;
946
947 for (CXXRecordDecl::method_iterator i = RD->method_begin(),
948 e = RD->method_end(); i != e; ++i) {
949 const CXXMethodDecl *MD = *i;
950
951 // We only want virtual methods.
952 if (!MD->isVirtual())
953 continue;
954
955 bool ShouldAddEntryForMethod = true;
956
957 // Check if this method overrides a method in the primary base.
958 for (CXXMethodDecl::method_iterator i = MD->begin_overridden_methods(),
959 e = MD->end_overridden_methods(); i != e; ++i) {
960 const CXXMethodDecl *OverriddenMD = *i;
961 const CXXRecordDecl *OverriddenRD = OverriddenMD->getParent();
962 assert(OverriddenMD->isCanonicalDecl() &&
963 "Should have the canonical decl of the overridden RD!");
964
965 if (OverriddenRD == PrimaryBase) {
966 // Check if converting from the return type of the method to the
967 // return type of the overridden method requires conversion.
968 QualType ReturnType =
969 MD->getType()->getAs<FunctionType>()->getResultType();
970 QualType OverriddenReturnType =
971 OverriddenMD->getType()->getAs<FunctionType>()->getResultType();
972
973 if (!TypeConversionRequiresAdjustment(CGM.getContext(),
974 ReturnType, OverriddenReturnType)) {
975 // This index is shared between the index in the vtable of the primary
976 // base class.
977 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
978 const CXXDestructorDecl *OverriddenDD =
979 cast<CXXDestructorDecl>(OverriddenMD);
980
981 // Add both the complete and deleting entries.
982 MethodVtableIndices[GlobalDecl(DD, Dtor_Complete)] =
983 getMethodVtableIndex(GlobalDecl(OverriddenDD, Dtor_Complete));
984 MethodVtableIndices[GlobalDecl(DD, Dtor_Deleting)] =
985 getMethodVtableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting));
986 } else {
987 MethodVtableIndices[MD] = getMethodVtableIndex(OverriddenMD);
988 }
989
990 // We don't need to add an entry for this method.
991 ShouldAddEntryForMethod = false;
992 break;
993 }
994 }
995 }
996
997 if (!ShouldAddEntryForMethod)
998 continue;
999
1000 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1001 if (MD->isImplicit()) {
1002 assert(!ImplicitVirtualDtor &&
1003 "Did already see an implicit virtual dtor!");
1004 ImplicitVirtualDtor = DD;
1005 continue;
1006 }
1007
1008 // Add the complete dtor.
1009 MethodVtableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++;
1010
1011 // Add the deleting dtor.
1012 MethodVtableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++;
1013 } else {
1014 // Add the entry.
1015 MethodVtableIndices[MD] = CurrentIndex++;
1016 }
1017 }
1018
1019 if (ImplicitVirtualDtor) {
1020 // Itanium C++ ABI 2.5.2:
1021 // If a class has an implicitly-defined virtual destructor,
1022 // its entries come after the declared virtual function pointers.
1023
1024 // Add the complete dtor.
1025 MethodVtableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Complete)] =
1026 CurrentIndex++;
1027
1028 // Add the deleting dtor.
1029 MethodVtableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Deleting)] =
1030 CurrentIndex++;
1031 }
1032
1033 NumVirtualFunctionPointers[RD] = CurrentIndex;
1034}
1035
1036uint64_t CGVtableInfo::getNumVirtualFunctionPointers(const CXXRecordDecl *RD) {
1037 llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
1038 NumVirtualFunctionPointers.find(RD);
1039 if (I != NumVirtualFunctionPointers.end())
1040 return I->second;
1041
1042 ComputeMethodVtableIndices(RD);
1043
1044 I = NumVirtualFunctionPointers.find(RD);
1045 assert(I != NumVirtualFunctionPointers.end() && "Did not find entry!");
1046 return I->second;
1047}
1048
1049uint64_t CGVtableInfo::getMethodVtableIndex(GlobalDecl GD) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001050 MethodVtableIndicesTy::iterator I = MethodVtableIndices.find(GD);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001051 if (I != MethodVtableIndices.end())
1052 return I->second;
1053
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001054 const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
Anders Carlssonf942ee02009-11-27 20:47:55 +00001055
1056 ComputeMethodVtableIndices(RD);
1057
Anders Carlssonfb4dda42009-11-13 17:08:56 +00001058 I = MethodVtableIndices.find(GD);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001059 assert(I != MethodVtableIndices.end() && "Did not find index!");
1060 return I->second;
1061}
1062
1063int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
1064 const CXXRecordDecl *VBase) {
1065 ClassPairTy ClassPair(RD, VBase);
1066
1067 VirtualBaseClassIndiciesTy::iterator I =
1068 VirtualBaseClassIndicies.find(ClassPair);
1069 if (I != VirtualBaseClassIndicies.end())
1070 return I->second;
1071
1072 std::vector<llvm::Constant *> methods;
1073 // FIXME: This seems expensive. Can we do a partial job to get
1074 // just this data.
Mike Stump653d0b92009-11-13 02:13:54 +00001075 VtableBuilder b(methods, RD, RD, 0, CGM);
Mike Stump75ce5732009-10-31 20:06:59 +00001076 D1(printf("vtable %s\n", RD->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001077 b.GenerateVtableForBase(RD);
1078 b.GenerateVtableForVBases(RD);
1079
1080 for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
1081 b.getVBIndex().begin(), E = b.getVBIndex().end(); I != E; ++I) {
1082 // Insert all types.
1083 ClassPairTy ClassPair(RD, I->first);
1084
1085 VirtualBaseClassIndicies.insert(std::make_pair(ClassPair, I->second));
1086 }
1087
1088 I = VirtualBaseClassIndicies.find(ClassPair);
1089 assert(I != VirtualBaseClassIndicies.end() && "Did not find index!");
1090
1091 return I->second;
1092}
1093
Mike Stump2cefe382009-11-12 20:47:57 +00001094llvm::Constant *CodeGenModule::GenerateVtable(const CXXRecordDecl *LayoutClass,
1095 const CXXRecordDecl *RD,
Mike Stumpeac45592009-11-11 20:26:26 +00001096 uint64_t Offset) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001097 llvm::SmallString<256> OutName;
Mike Stump2cefe382009-11-12 20:47:57 +00001098 if (LayoutClass != RD)
Daniel Dunbare128dd12009-11-21 09:06:22 +00001099 getMangleContext().mangleCXXCtorVtable(LayoutClass, Offset/8, RD, OutName);
Mike Stumpeac45592009-11-11 20:26:26 +00001100 else
Daniel Dunbare128dd12009-11-21 09:06:22 +00001101 getMangleContext().mangleCXXVtable(RD, OutName);
1102 llvm::StringRef Name = OutName.str();
Benjamin Kramerbb0a07b2009-10-11 22:57:54 +00001103
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001104 std::vector<llvm::Constant *> methods;
1105 llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0);
1106 int64_t AddressPoint;
1107
Mike Stumpaa51ad62009-11-19 04:04:36 +00001108 llvm::GlobalVariable *GV = getModule().getGlobalVariable(Name);
Mike Stumpcd2b8212009-11-19 20:52:19 +00001109 if (GV && AddressPoints[LayoutClass] && !GV->isDeclaration()) {
Mike Stumpaa51ad62009-11-19 04:04:36 +00001110 AddressPoint=(*(*(AddressPoints[LayoutClass]))[RD])[std::make_pair(RD,
1111 Offset)];
Mike Stumpcd2b8212009-11-19 20:52:19 +00001112 // FIXME: We can never have 0 address point. Do this for now so gepping
1113 // retains the same structure. Later, we'll just assert.
1114 if (AddressPoint == 0)
1115 AddressPoint = 1;
1116 } else {
Mike Stumpaa51ad62009-11-19 04:04:36 +00001117 VtableBuilder b(methods, RD, LayoutClass, Offset, *this);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001118
Mike Stumpaa51ad62009-11-19 04:04:36 +00001119 D1(printf("vtable %s\n", RD->getNameAsCString()));
1120 // First comes the vtables for all the non-virtual bases...
1121 AddressPoint = b.GenerateVtableForBase(RD, Offset);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001122
Mike Stumpaa51ad62009-11-19 04:04:36 +00001123 // then the vtables for all the virtual bases.
1124 b.GenerateVtableForVBases(RD, Offset);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001125
Mike Stumpaa51ad62009-11-19 04:04:36 +00001126 bool CreateDefinition = true;
1127 if (LayoutClass != RD)
1128 CreateDefinition = true;
1129 else {
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00001130 const ASTRecordLayout &Layout =
1131 getContext().getASTRecordLayout(LayoutClass);
1132
1133 if (const CXXMethodDecl *KeyFunction = Layout.getKeyFunction()) {
Mike Stumpaa51ad62009-11-19 04:04:36 +00001134 if (!KeyFunction->getBody()) {
1135 // If there is a KeyFunction, and it isn't defined, just build a
1136 // reference to the vtable.
1137 CreateDefinition = false;
1138 }
1139 }
1140 }
1141
1142 llvm::Constant *C = 0;
1143 llvm::Type *type = Ptr8Ty;
1144 llvm::GlobalVariable::LinkageTypes linktype
1145 = llvm::GlobalValue::ExternalLinkage;
1146 if (CreateDefinition) {
1147 llvm::ArrayType *ntype = llvm::ArrayType::get(Ptr8Ty, methods.size());
1148 C = llvm::ConstantArray::get(ntype, methods);
1149 linktype = llvm::GlobalValue::LinkOnceODRLinkage;
1150 if (LayoutClass->isInAnonymousNamespace())
1151 linktype = llvm::GlobalValue::InternalLinkage;
1152 type = ntype;
1153 }
1154 llvm::GlobalVariable *OGV = GV;
1155 GV = new llvm::GlobalVariable(getModule(), type, true, linktype, C, Name);
1156 if (OGV) {
1157 GV->takeName(OGV);
1158 llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV,
1159 OGV->getType());
1160 OGV->replaceAllUsesWith(NewPtr);
1161 OGV->eraseFromParent();
1162 }
1163 bool Hidden = getDeclVisibilityMode(RD) == LangOptions::Hidden;
1164 if (Hidden)
1165 GV->setVisibility(llvm::GlobalVariable::HiddenVisibility);
1166 }
Mike Stumpc0f632d2009-11-18 04:00:48 +00001167 llvm::Constant *vtable = llvm::ConstantExpr::getBitCast(GV, Ptr8Ty);
Mike Stumpd846d082009-11-10 07:44:33 +00001168 llvm::Constant *AddressPointC;
1169 uint32_t LLVMPointerWidth = getContext().Target.getPointerWidth(0);
1170 AddressPointC = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
1171 AddressPoint*LLVMPointerWidth/8);
Mike Stump2cefe382009-11-12 20:47:57 +00001172 vtable = llvm::ConstantExpr::getInBoundsGetElementPtr(vtable, &AddressPointC,
1173 1);
Mike Stumpd846d082009-11-10 07:44:33 +00001174
Mike Stumpcd2b8212009-11-19 20:52:19 +00001175 assert(vtable->getType() == Ptr8Ty);
Anders Carlsson2bb27f52009-10-11 22:13:54 +00001176 return vtable;
1177}
Mike Stump9f23a142009-11-10 02:30:51 +00001178
Mike Stumpae1b85d2009-12-02 19:07:44 +00001179namespace {
Mike Stump9f23a142009-11-10 02:30:51 +00001180class VTTBuilder {
1181 /// Inits - The list of values built for the VTT.
1182 std::vector<llvm::Constant *> &Inits;
1183 /// Class - The most derived class that this vtable is being built for.
1184 const CXXRecordDecl *Class;
1185 CodeGenModule &CGM; // Per-module state.
Mike Stump8b2d2d02009-11-11 00:35:07 +00001186 llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase;
Mike Stumpc7b9f5e2009-11-11 03:08:24 +00001187 /// BLayout - Layout for the most derived class that this vtable is being
1188 /// built for.
1189 const ASTRecordLayout &BLayout;
Mike Stump83066c82009-11-13 01:54:23 +00001190 CodeGenModule::AddrMap_t &AddressPoints;
Mike Stump2cefe382009-11-12 20:47:57 +00001191 // vtbl - A pointer to the vtable for Class.
1192 llvm::Constant *ClassVtbl;
1193 llvm::LLVMContext &VMContext;
Mike Stump9f23a142009-11-10 02:30:51 +00001194
Mike Stump8677bc22009-11-12 22:56:32 +00001195 /// BuildVtablePtr - Build up a referene to the given secondary vtable
Mike Stump83066c82009-11-13 01:54:23 +00001196 llvm::Constant *BuildVtablePtr(llvm::Constant *vtbl,
1197 const CXXRecordDecl *VtblClass,
1198 const CXXRecordDecl *RD,
Mike Stump8677bc22009-11-12 22:56:32 +00001199 uint64_t Offset) {
1200 int64_t AddressPoint;
Mike Stump83066c82009-11-13 01:54:23 +00001201 AddressPoint = (*AddressPoints[VtblClass])[std::make_pair(RD, Offset)];
Mike Stump2b34bc52009-11-12 23:36:21 +00001202 // FIXME: We can never have 0 address point. Do this for now so gepping
Mike Stumpcd2b8212009-11-19 20:52:19 +00001203 // retains the same structure. Later we'll just assert.
Mike Stump2b34bc52009-11-12 23:36:21 +00001204 if (AddressPoint == 0)
1205 AddressPoint = 1;
Mike Stump83066c82009-11-13 01:54:23 +00001206 D1(printf("XXX address point for %s in %s layout %s at offset %d was %d\n",
1207 RD->getNameAsCString(), VtblClass->getNameAsCString(),
1208 Class->getNameAsCString(), (int)Offset, (int)AddressPoint));
Mike Stump8677bc22009-11-12 22:56:32 +00001209 uint32_t LLVMPointerWidth = CGM.getContext().Target.getPointerWidth(0);
1210 llvm::Constant *init;
1211 init = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
1212 AddressPoint*LLVMPointerWidth/8);
1213 init = llvm::ConstantExpr::getInBoundsGetElementPtr(vtbl, &init, 1);
1214 return init;
1215 }
1216
Mike Stump2cefe382009-11-12 20:47:57 +00001217 /// Secondary - Add the secondary vtable pointers to Inits. Offset is the
1218 /// current offset in bits to the object we're working on.
Mike Stump8677bc22009-11-12 22:56:32 +00001219 void Secondary(const CXXRecordDecl *RD, llvm::Constant *vtbl,
Mike Stump83066c82009-11-13 01:54:23 +00001220 const CXXRecordDecl *VtblClass, uint64_t Offset=0,
1221 bool MorallyVirtual=false) {
Mike Stump8b2d2d02009-11-11 00:35:07 +00001222 if (RD->getNumVBases() == 0 && ! MorallyVirtual)
1223 return;
1224
1225 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
1226 e = RD->bases_end(); i != e; ++i) {
1227 const CXXRecordDecl *Base =
1228 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
1229 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1230 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1231 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
1232 bool NonVirtualPrimaryBase;
1233 NonVirtualPrimaryBase = !PrimaryBaseWasVirtual && Base == PrimaryBase;
1234 bool BaseMorallyVirtual = MorallyVirtual | i->isVirtual();
Mike Stumpc7b9f5e2009-11-11 03:08:24 +00001235 uint64_t BaseOffset;
1236 if (!i->isVirtual()) {
1237 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1238 BaseOffset = Offset + Layout.getBaseClassOffset(Base);
1239 } else
1240 BaseOffset = BLayout.getVBaseClassOffset(Base);
Mike Stump2b34bc52009-11-12 23:36:21 +00001241 llvm::Constant *subvtbl = vtbl;
Mike Stump83066c82009-11-13 01:54:23 +00001242 const CXXRecordDecl *subVtblClass = VtblClass;
Mike Stump8b2d2d02009-11-11 00:35:07 +00001243 if ((Base->getNumVBases() || BaseMorallyVirtual)
1244 && !NonVirtualPrimaryBase) {
1245 // FIXME: Slightly too many of these for __ZTT8test8_B2
Mike Stump8677bc22009-11-12 22:56:32 +00001246 llvm::Constant *init;
Mike Stump2b34bc52009-11-12 23:36:21 +00001247 if (BaseMorallyVirtual)
Mike Stump83066c82009-11-13 01:54:23 +00001248 init = BuildVtablePtr(vtbl, VtblClass, RD, Offset);
Mike Stump2b34bc52009-11-12 23:36:21 +00001249 else {
Mike Stump8677bc22009-11-12 22:56:32 +00001250 init = CGM.getVtableInfo().getCtorVtable(Class, Base, BaseOffset);
Mike Stump2b34bc52009-11-12 23:36:21 +00001251 subvtbl = dyn_cast<llvm::Constant>(init->getOperand(0));
Mike Stump83066c82009-11-13 01:54:23 +00001252 subVtblClass = Base;
Mike Stump2b34bc52009-11-12 23:36:21 +00001253 }
Mike Stump8677bc22009-11-12 22:56:32 +00001254 Inits.push_back(init);
Mike Stump8b2d2d02009-11-11 00:35:07 +00001255 }
Mike Stump83066c82009-11-13 01:54:23 +00001256 Secondary(Base, subvtbl, subVtblClass, BaseOffset, BaseMorallyVirtual);
Mike Stump8b2d2d02009-11-11 00:35:07 +00001257 }
1258 }
1259
Mike Stump2cefe382009-11-12 20:47:57 +00001260 /// BuiltVTT - Add the VTT to Inits. Offset is the offset in bits to the
1261 /// currnet object we're working on.
1262 void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool MorallyVirtual) {
Mike Stump8b2d2d02009-11-11 00:35:07 +00001263 if (RD->getNumVBases() == 0 && !MorallyVirtual)
1264 return;
1265
Mike Stump2cefe382009-11-12 20:47:57 +00001266 llvm::Constant *init;
Mike Stump83066c82009-11-13 01:54:23 +00001267 const CXXRecordDecl *VtblClass;
1268
Mike Stump8b2d2d02009-11-11 00:35:07 +00001269 // First comes the primary virtual table pointer...
Mike Stump83066c82009-11-13 01:54:23 +00001270 if (MorallyVirtual) {
1271 init = BuildVtablePtr(ClassVtbl, Class, RD, Offset);
1272 VtblClass = Class;
1273 } else {
Mike Stump2cefe382009-11-12 20:47:57 +00001274 init = CGM.getVtableInfo().getCtorVtable(Class, RD, Offset);
Mike Stump83066c82009-11-13 01:54:23 +00001275 VtblClass = RD;
1276 }
Mike Stump8677bc22009-11-12 22:56:32 +00001277 llvm::Constant *vtbl = dyn_cast<llvm::Constant>(init->getOperand(0));
Mike Stump2cefe382009-11-12 20:47:57 +00001278 Inits.push_back(init);
Mike Stump8b2d2d02009-11-11 00:35:07 +00001279
1280 // then the secondary VTTs....
Mike Stump2cefe382009-11-12 20:47:57 +00001281 SecondaryVTTs(RD, Offset, MorallyVirtual);
Mike Stump8b2d2d02009-11-11 00:35:07 +00001282
1283 // and last the secondary vtable pointers.
Mike Stump83066c82009-11-13 01:54:23 +00001284 Secondary(RD, vtbl, VtblClass, Offset, MorallyVirtual);
Mike Stump8b2d2d02009-11-11 00:35:07 +00001285 }
1286
1287 /// SecondaryVTTs - Add the secondary VTTs to Inits. The secondary VTTs are
1288 /// built from each direct non-virtual proper base that requires a VTT in
1289 /// declaration order.
Mike Stump2cefe382009-11-12 20:47:57 +00001290 void SecondaryVTTs(const CXXRecordDecl *RD, uint64_t Offset=0,
1291 bool MorallyVirtual=false) {
Mike Stump8b2d2d02009-11-11 00:35:07 +00001292 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
1293 e = RD->bases_end(); i != e; ++i) {
1294 const CXXRecordDecl *Base =
1295 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
1296 if (i->isVirtual())
1297 continue;
Mike Stump2cefe382009-11-12 20:47:57 +00001298 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1299 uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base);
1300 BuildVTT(Base, BaseOffset, MorallyVirtual);
Mike Stump8b2d2d02009-11-11 00:35:07 +00001301 }
1302 }
1303
1304 /// VirtualVTTs - Add the VTT for each proper virtual base in inheritance
1305 /// graph preorder.
1306 void VirtualVTTs(const CXXRecordDecl *RD) {
1307 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
1308 e = RD->bases_end(); i != e; ++i) {
1309 const CXXRecordDecl *Base =
1310 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
1311 if (i->isVirtual() && !SeenVBase.count(Base)) {
1312 SeenVBase.insert(Base);
Mike Stump2cefe382009-11-12 20:47:57 +00001313 uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
1314 BuildVTT(Base, BaseOffset, true);
Mike Stump8b2d2d02009-11-11 00:35:07 +00001315 }
1316 VirtualVTTs(Base);
1317 }
1318 }
Mike Stump9f23a142009-11-10 02:30:51 +00001319public:
1320 VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c,
Mike Stumpc7b9f5e2009-11-11 03:08:24 +00001321 CodeGenModule &cgm)
1322 : Inits(inits), Class(c), CGM(cgm),
Mike Stump2cefe382009-11-12 20:47:57 +00001323 BLayout(cgm.getContext().getASTRecordLayout(c)),
Mike Stump83066c82009-11-13 01:54:23 +00001324 AddressPoints(*cgm.AddressPoints[c]),
Mike Stump2cefe382009-11-12 20:47:57 +00001325 VMContext(cgm.getModule().getContext()) {
Mike Stumpd846d082009-11-10 07:44:33 +00001326
Mike Stump8b2d2d02009-11-11 00:35:07 +00001327 // First comes the primary virtual table pointer for the complete class...
Mike Stump2cefe382009-11-12 20:47:57 +00001328 ClassVtbl = CGM.getVtableInfo().getVtable(Class);
1329 Inits.push_back(ClassVtbl);
1330 ClassVtbl = dyn_cast<llvm::Constant>(ClassVtbl->getOperand(0));
1331
Mike Stump8b2d2d02009-11-11 00:35:07 +00001332 // then the secondary VTTs...
1333 SecondaryVTTs(Class);
1334
1335 // then the secondary vtable pointers...
Mike Stump83066c82009-11-13 01:54:23 +00001336 Secondary(Class, ClassVtbl, Class);
Mike Stump8b2d2d02009-11-11 00:35:07 +00001337
1338 // and last, the virtual VTTs.
1339 VirtualVTTs(Class);
Mike Stump9f23a142009-11-10 02:30:51 +00001340 }
1341};
Mike Stumpae1b85d2009-12-02 19:07:44 +00001342}
Mike Stump9f23a142009-11-10 02:30:51 +00001343
Mike Stumpd846d082009-11-10 07:44:33 +00001344llvm::Constant *CodeGenModule::GenerateVTT(const CXXRecordDecl *RD) {
Mike Stumpb4722212009-11-10 19:13:04 +00001345 // Only classes that have virtual bases need a VTT.
1346 if (RD->getNumVBases() == 0)
1347 return 0;
1348
Mike Stump9f23a142009-11-10 02:30:51 +00001349 llvm::SmallString<256> OutName;
Daniel Dunbare128dd12009-11-21 09:06:22 +00001350 getMangleContext().mangleCXXVTT(RD, OutName);
1351 llvm::StringRef Name = OutName.str();
Mike Stump9f23a142009-11-10 02:30:51 +00001352
1353 llvm::GlobalVariable::LinkageTypes linktype;
1354 linktype = llvm::GlobalValue::LinkOnceODRLinkage;
Mike Stumpaa51ad62009-11-19 04:04:36 +00001355 if (RD->isInAnonymousNamespace())
1356 linktype = llvm::GlobalValue::InternalLinkage;
Mike Stump9f23a142009-11-10 02:30:51 +00001357 std::vector<llvm::Constant *> inits;
1358 llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0);
1359
Mike Stump9f23a142009-11-10 02:30:51 +00001360 D1(printf("vtt %s\n", RD->getNameAsCString()));
1361
Mike Stump8b2d2d02009-11-11 00:35:07 +00001362 VTTBuilder b(inits, RD, *this);
1363
Mike Stump9f23a142009-11-10 02:30:51 +00001364 llvm::Constant *C;
1365 llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, inits.size());
1366 C = llvm::ConstantArray::get(type, inits);
Mike Stumpc0f632d2009-11-18 04:00:48 +00001367 llvm::GlobalVariable *vtt = new llvm::GlobalVariable(getModule(), type, true,
Mike Stumpaa51ad62009-11-19 04:04:36 +00001368 linktype, C, Name);
Mike Stumpc0f632d2009-11-18 04:00:48 +00001369 bool Hidden = getDeclVisibilityMode(RD) == LangOptions::Hidden;
1370 if (Hidden)
1371 vtt->setVisibility(llvm::GlobalVariable::HiddenVisibility);
1372 return llvm::ConstantExpr::getBitCast(vtt, Ptr8Ty);
Mike Stump9f23a142009-11-10 02:30:51 +00001373}
Mike Stumpd846d082009-11-10 07:44:33 +00001374
Mike Stump1a139f82009-11-19 01:08:19 +00001375void CGVtableInfo::GenerateClassData(const CXXRecordDecl *RD) {
1376 Vtables[RD] = CGM.GenerateVtable(RD, RD);
Mike Stumpc01c2b82009-12-02 18:57:08 +00001377 CGM.GenerateRTTI(RD);
Mike Stump1a139f82009-11-19 01:08:19 +00001378 CGM.GenerateVTT(RD);
1379}
1380
Mike Stumpeac45592009-11-11 20:26:26 +00001381llvm::Constant *CGVtableInfo::getVtable(const CXXRecordDecl *RD) {
Mike Stumpd846d082009-11-10 07:44:33 +00001382 llvm::Constant *&vtbl = Vtables[RD];
1383 if (vtbl)
1384 return vtbl;
Mike Stump2cefe382009-11-12 20:47:57 +00001385 vtbl = CGM.GenerateVtable(RD, RD);
Mike Stumpaa51ad62009-11-19 04:04:36 +00001386
1387 bool CreateDefinition = true;
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00001388
1389 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1390 if (const CXXMethodDecl *KeyFunction = Layout.getKeyFunction()) {
Mike Stumpaa51ad62009-11-19 04:04:36 +00001391 if (!KeyFunction->getBody()) {
1392 // If there is a KeyFunction, and it isn't defined, just build a
1393 // reference to the vtable.
1394 CreateDefinition = false;
1395 }
1396 }
1397
1398 if (CreateDefinition) {
Mike Stumpc01c2b82009-12-02 18:57:08 +00001399 CGM.GenerateRTTI(RD);
Mike Stumpaa51ad62009-11-19 04:04:36 +00001400 CGM.GenerateVTT(RD);
1401 }
Mike Stumpd846d082009-11-10 07:44:33 +00001402 return vtbl;
1403}
Mike Stumpeac45592009-11-11 20:26:26 +00001404
Mike Stump2cefe382009-11-12 20:47:57 +00001405llvm::Constant *CGVtableInfo::getCtorVtable(const CXXRecordDecl *LayoutClass,
1406 const CXXRecordDecl *RD,
Mike Stumpeac45592009-11-11 20:26:26 +00001407 uint64_t Offset) {
Mike Stump2cefe382009-11-12 20:47:57 +00001408 return CGM.GenerateVtable(LayoutClass, RD, Offset);
Mike Stumpeac45592009-11-11 20:26:26 +00001409}
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +00001410
1411void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
1412 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
1413 const CXXRecordDecl *RD = MD->getParent();
1414
1415 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
1416
1417 // Get the key function.
1418 const CXXMethodDecl *KeyFunction = Layout.getKeyFunction();
1419
1420 if (!KeyFunction) {
1421 // If there's no key function, we don't want to emit the vtable here.
1422 return;
1423 }
1424
1425 // Check if we have the key function.
1426 if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl())
1427 return;
1428
1429 // If the key function is a destructor, we only want to emit the vtable once,
1430 // so do it for the complete destructor.
1431 if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() != Dtor_Complete)
1432 return;
1433
1434 // Emit the data.
1435 GenerateClassData(RD);
1436}
1437