blob: 9be1a3b22b3371335fe58dcd25c5e6269d717377 [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"
16
17#include "clang/AST/RecordLayout.h"
Zhongxing Xu1721ef72009-11-13 05:46:16 +000018#include <cstdio>
Anders Carlsson2bb27f52009-10-11 22:13:54 +000019
20using namespace clang;
21using namespace CodeGen;
22
23class VtableBuilder {
24public:
25 /// Index_t - Vtable index type.
26 typedef uint64_t Index_t;
27private:
28 std::vector<llvm::Constant *> &methods;
29 std::vector<llvm::Constant *> submethods;
30 llvm::Type *Ptr8Ty;
31 /// Class - The most derived class that this vtable is being built for.
32 const CXXRecordDecl *Class;
Mike Stump83066c82009-11-13 01:54:23 +000033 /// LayoutClass - The most derived class used for virtual base layout
34 /// information.
35 const CXXRecordDecl *LayoutClass;
Mike Stump653d0b92009-11-13 02:13:54 +000036 /// LayoutOffset - The offset for Class in LayoutClass.
37 uint64_t LayoutOffset;
Anders Carlsson2bb27f52009-10-11 22:13:54 +000038 /// BLayout - Layout for the most derived class that this vtable is being
39 /// built for.
40 const ASTRecordLayout &BLayout;
41 llvm::SmallSet<const CXXRecordDecl *, 32> IndirectPrimary;
42 llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase;
43 llvm::Constant *rtti;
44 llvm::LLVMContext &VMContext;
45 CodeGenModule &CGM; // Per-module state.
46 /// Index - Maps a method decl into a vtable index. Useful for virtual
47 /// dispatch codegen.
Anders Carlssonfb4dda42009-11-13 17:08:56 +000048 llvm::DenseMap<GlobalDecl, Index_t> Index;
49 llvm::DenseMap<GlobalDecl, Index_t> VCall;
50 llvm::DenseMap<GlobalDecl, Index_t> VCallOffset;
Mike Stumpcd6f9ed2009-11-06 23:27:42 +000051 // This is the offset to the nearest virtual base
Anders Carlssonfb4dda42009-11-13 17:08:56 +000052 llvm::DenseMap<GlobalDecl, Index_t> NonVirtualOffset;
Anders Carlsson2bb27f52009-10-11 22:13:54 +000053 llvm::DenseMap<const CXXRecordDecl *, Index_t> VBIndex;
Mike Stumpbb9ff052009-10-27 23:46:47 +000054
Anders Carlssonfb4dda42009-11-13 17:08:56 +000055 typedef llvm::DenseMap<GlobalDecl, int> Pures_t;
Mike Stumpbb9ff052009-10-27 23:46:47 +000056 Pures_t Pures;
Anders Carlsson2bb27f52009-10-11 22:13:54 +000057 typedef std::pair<Index_t, Index_t> CallOffset;
Anders Carlssonfb4dda42009-11-13 17:08:56 +000058 typedef llvm::DenseMap<GlobalDecl, CallOffset> Thunks_t;
Anders Carlsson2bb27f52009-10-11 22:13:54 +000059 Thunks_t Thunks;
Anders Carlssonfb4dda42009-11-13 17:08:56 +000060 typedef llvm::DenseMap<GlobalDecl,
Mike Stump87876a02009-10-13 10:55:21 +000061 std::pair<std::pair<CallOffset, CallOffset>,
62 CanQualType> > CovariantThunks_t;
Anders Carlsson2bb27f52009-10-11 22:13:54 +000063 CovariantThunks_t CovariantThunks;
64 std::vector<Index_t> VCalls;
Mike Stump2cefe382009-11-12 20:47:57 +000065
66 typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
67 // CtorVtable - Used to hold the AddressPoints (offsets) into the built vtable
68 // for use in computing the initializers for the VTT.
69 llvm::DenseMap<CtorVtable_t, int64_t> &AddressPoints;
70
Anders Carlsson2bb27f52009-10-11 22:13:54 +000071 typedef CXXRecordDecl::method_iterator method_iter;
Anders Carlsson2bb27f52009-10-11 22:13:54 +000072 const bool Extern;
73 const uint32_t LLVMPointerWidth;
74 Index_t extra;
Mike Stump37dbe962009-10-15 02:04:03 +000075 typedef std::vector<std::pair<const CXXRecordDecl *, int64_t> > Path_t;
Mike Stumpbb9ff052009-10-27 23:46:47 +000076 llvm::Constant *cxa_pure;
Anders Carlsson2bb27f52009-10-11 22:13:54 +000077public:
Mike Stump653d0b92009-11-13 02:13:54 +000078 VtableBuilder(std::vector<llvm::Constant *> &meth, const CXXRecordDecl *c,
79 const CXXRecordDecl *l, uint64_t lo, CodeGenModule &cgm)
80 : methods(meth), Class(c), LayoutClass(l), LayoutOffset(lo),
Mike Stump83066c82009-11-13 01:54:23 +000081 BLayout(cgm.getContext().getASTRecordLayout(l)),
Mike Stumpf5b28692009-11-14 23:32:21 +000082 rtti(cgm.GenerateRttiRef(c)), VMContext(cgm.getModule().getContext()),
Mike Stump2cefe382009-11-12 20:47:57 +000083 CGM(cgm), AddressPoints(*new llvm::DenseMap<CtorVtable_t, int64_t>),
Mike Stump1960b202009-11-19 00:49:05 +000084 Extern(!l->isInAnonymousNamespace()),
Mike Stumpcd6f9ed2009-11-06 23:27:42 +000085 LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +000086 Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
Mike Stump375faa82009-10-28 00:35:46 +000087
88 // Calculate pointer for ___cxa_pure_virtual.
89 const llvm::FunctionType *FTy;
90 std::vector<const llvm::Type*> ArgTys;
91 const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
92 FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
93 cxa_pure = wrap(CGM.CreateRuntimeFunction(FTy, "__cxa_pure_virtual"));
Anders Carlsson2bb27f52009-10-11 22:13:54 +000094 }
95
Anders Carlssonfb4dda42009-11-13 17:08:56 +000096 llvm::DenseMap<GlobalDecl, Index_t> &getIndex() { return Index; }
Anders Carlsson2bb27f52009-10-11 22:13:54 +000097 llvm::DenseMap<const CXXRecordDecl *, Index_t> &getVBIndex()
98 { return VBIndex; }
99
Mike Stump2cefe382009-11-12 20:47:57 +0000100 llvm::DenseMap<CtorVtable_t, int64_t> *getAddressPoints()
101 { return &AddressPoints; }
102
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000103 llvm::Constant *wrap(Index_t i) {
104 llvm::Constant *m;
105 m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), i);
106 return llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty);
107 }
108
109 llvm::Constant *wrap(llvm::Constant *m) {
110 return llvm::ConstantExpr::getBitCast(m, Ptr8Ty);
111 }
112
Mike Stump2b34bc52009-11-12 23:36:21 +0000113//#define D1(x)
114#define D1(X) do { if (getenv("DEBUG")) { X; } } while (0)
Mike Stump75ce5732009-10-31 20:06:59 +0000115
116 void GenerateVBaseOffsets(const CXXRecordDecl *RD, uint64_t Offset,
Mike Stump28431212009-10-13 22:54:56 +0000117 bool updateVBIndex, Index_t current_vbindex) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000118 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
119 e = RD->bases_end(); i != e; ++i) {
120 const CXXRecordDecl *Base =
121 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
Mike Stump28431212009-10-13 22:54:56 +0000122 Index_t next_vbindex = current_vbindex;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000123 if (i->isVirtual() && !SeenVBase.count(Base)) {
124 SeenVBase.insert(Base);
Mike Stump28431212009-10-13 22:54:56 +0000125 if (updateVBIndex) {
Mike Stump75ce5732009-10-31 20:06:59 +0000126 next_vbindex = (ssize_t)(-(VCalls.size()*LLVMPointerWidth/8)
Mike Stump28431212009-10-13 22:54:56 +0000127 - 3*LLVMPointerWidth/8);
128 VBIndex[Base] = next_vbindex;
129 }
Mike Stump75ce5732009-10-31 20:06:59 +0000130 int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8;
131 VCalls.push_back((0?700:0) + BaseOffset);
132 D1(printf(" vbase for %s at %d delta %d most derived %s\n",
133 Base->getNameAsCString(),
134 (int)-VCalls.size()-3, (int)BaseOffset,
135 Class->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000136 }
Mike Stump28431212009-10-13 22:54:56 +0000137 // We also record offsets for non-virtual bases to closest enclosing
138 // virtual base. We do this so that we don't have to search
139 // for the nearst virtual base class when generating thunks.
140 if (updateVBIndex && VBIndex.count(Base) == 0)
141 VBIndex[Base] = next_vbindex;
Mike Stump75ce5732009-10-31 20:06:59 +0000142 GenerateVBaseOffsets(Base, Offset, updateVBIndex, next_vbindex);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000143 }
144 }
145
146 void StartNewTable() {
147 SeenVBase.clear();
148 }
149
150 Index_t VBlookup(CXXRecordDecl *D, CXXRecordDecl *B);
151
Mike Stump8bccbfd2009-10-15 09:30:16 +0000152 Index_t getNVOffset_1(const CXXRecordDecl *D, const CXXRecordDecl *B,
153 Index_t Offset = 0) {
154
155 if (B == D)
156 return Offset;
157
158 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(D);
159 for (CXXRecordDecl::base_class_const_iterator i = D->bases_begin(),
160 e = D->bases_end(); i != e; ++i) {
161 const CXXRecordDecl *Base =
162 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
163 int64_t BaseOffset = 0;
164 if (!i->isVirtual())
165 BaseOffset = Offset + Layout.getBaseClassOffset(Base);
166 int64_t o = getNVOffset_1(Base, B, BaseOffset);
167 if (o >= 0)
168 return o;
169 }
170
171 return -1;
172 }
173
174 /// getNVOffset - Returns the non-virtual offset for the given (B) base of the
175 /// derived class D.
176 Index_t getNVOffset(QualType qB, QualType qD) {
Mike Stump46271322009-11-03 19:03:17 +0000177 qD = qD->getPointeeType();
178 qB = qB->getPointeeType();
Mike Stump8bccbfd2009-10-15 09:30:16 +0000179 CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
180 CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
181 int64_t o = getNVOffset_1(D, B);
182 if (o >= 0)
183 return o;
184
185 assert(false && "FIXME: non-virtual base not found");
186 return 0;
187 }
188
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000189 /// getVbaseOffset - Returns the index into the vtable for the virtual base
190 /// offset for the given (B) virtual base of the derived class D.
191 Index_t getVbaseOffset(QualType qB, QualType qD) {
Mike Stump46271322009-11-03 19:03:17 +0000192 qD = qD->getPointeeType();
193 qB = qB->getPointeeType();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000194 CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
195 CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
196 if (D != Class)
197 return VBlookup(D, B);
198 llvm::DenseMap<const CXXRecordDecl *, Index_t>::iterator i;
199 i = VBIndex.find(B);
200 if (i != VBIndex.end())
201 return i->second;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000202
Mike Stump28431212009-10-13 22:54:56 +0000203 assert(false && "FIXME: Base not found");
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000204 return 0;
205 }
206
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000207 bool OverrideMethod(GlobalDecl GD, llvm::Constant *m,
Mike Stump8bccbfd2009-10-15 09:30:16 +0000208 bool MorallyVirtual, Index_t OverrideOffset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000209 Index_t Offset, int64_t CurrentVBaseOffset) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000210 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
211
Mike Stump375faa82009-10-28 00:35:46 +0000212 const bool isPure = MD->isPure();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000213 typedef CXXMethodDecl::method_iterator meth_iter;
Mike Stump8bccbfd2009-10-15 09:30:16 +0000214 // FIXME: Should OverrideOffset's be Offset?
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000215
216 // FIXME: Don't like the nested loops. For very large inheritance
217 // heirarchies we could have a table on the side with the final overridder
218 // and just replace each instance of an overridden method once. Would be
219 // nice to measure the cost/benefit on real code.
220
221 for (meth_iter mi = MD->begin_overridden_methods(),
222 e = MD->end_overridden_methods();
223 mi != e; ++mi) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000224 GlobalDecl OGD;
225
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000226 const CXXMethodDecl *OMD = *mi;
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000227 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(OMD))
228 OGD = GlobalDecl(DD, GD.getDtorType());
229 else
230 OGD = OMD;
231
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000232 llvm::Constant *om;
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000233 om = WrapAddrOf(OGD);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000234 om = llvm::ConstantExpr::getBitCast(om, Ptr8Ty);
235
236 for (Index_t i = 0, e = submethods.size();
237 i != e; ++i) {
238 // FIXME: begin_overridden_methods might be too lax, covariance */
239 if (submethods[i] != om)
240 continue;
241 QualType nc_oret = OMD->getType()->getAs<FunctionType>()->getResultType();
242 CanQualType oret = CGM.getContext().getCanonicalType(nc_oret);
243 QualType nc_ret = MD->getType()->getAs<FunctionType>()->getResultType();
244 CanQualType ret = CGM.getContext().getCanonicalType(nc_ret);
245 CallOffset ReturnOffset = std::make_pair(0, 0);
246 if (oret != ret) {
247 // FIXME: calculate offsets for covariance
Mike Stump87876a02009-10-13 10:55:21 +0000248 if (CovariantThunks.count(OMD)) {
249 oret = CovariantThunks[OMD].second;
250 CovariantThunks.erase(OMD);
251 }
Mike Stump8bccbfd2009-10-15 09:30:16 +0000252 // FIXME: Double check oret
253 Index_t nv = getNVOffset(oret, ret)/8;
Mike Stump87876a02009-10-13 10:55:21 +0000254 ReturnOffset = std::make_pair(nv, getVbaseOffset(oret, ret));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000255 }
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000256 Index[GD] = i;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000257 submethods[i] = m;
Mike Stump375faa82009-10-28 00:35:46 +0000258 if (isPure)
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000259 Pures[GD] = 1;
260 Pures.erase(OGD);
261 Thunks.erase(OGD);
262 if (MorallyVirtual || VCall.count(OGD)) {
263 Index_t &idx = VCall[OGD];
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000264 if (idx == 0) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000265 NonVirtualOffset[GD] = -OverrideOffset/8 + CurrentVBaseOffset/8;
266 VCallOffset[GD] = OverrideOffset/8;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000267 idx = VCalls.size()+1;
268 VCalls.push_back(0);
Mike Stump75ce5732009-10-31 20:06:59 +0000269 D1(printf(" vcall for %s at %d with delta %d most derived %s\n",
Mike Stumpc5a332c2009-11-13 23:45:53 +0000270 MD->getNameAsString().c_str(), (int)-idx-3,
271 (int)VCalls[idx-1], Class->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000272 } else {
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000273 NonVirtualOffset[GD] = NonVirtualOffset[OGD];
274 VCallOffset[GD] = VCallOffset[OGD];
275 VCalls[idx-1] = -VCallOffset[OGD] + OverrideOffset/8;
Mike Stump75ce5732009-10-31 20:06:59 +0000276 D1(printf(" vcall patch for %s at %d with delta %d most derived %s\n",
Mike Stumpc5a332c2009-11-13 23:45:53 +0000277 MD->getNameAsString().c_str(), (int)-idx-3,
278 (int)VCalls[idx-1], Class->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000279 }
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000280 VCall[GD] = idx;
281 int64_t O = NonVirtualOffset[GD];
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000282 int v = -((idx+extra+2)*LLVMPointerWidth/8);
283 // Optimize out virtual adjustments of 0.
284 if (VCalls[idx-1] == 0)
285 v = 0;
286 CallOffset ThisOffset = std::make_pair(O, v);
Mike Stump37dbe962009-10-15 02:04:03 +0000287 // FIXME: Do we always have to build a covariant thunk to save oret,
288 // which is the containing virtual base class?
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000289 if (ReturnOffset.first || ReturnOffset.second)
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000290 CovariantThunks[GD] = std::make_pair(std::make_pair(ThisOffset,
Mike Stump87876a02009-10-13 10:55:21 +0000291 ReturnOffset),
292 oret);
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000293 else if (!isPure && (ThisOffset.first || ThisOffset.second))
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000294 Thunks[GD] = ThisOffset;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000295 return true;
296 }
Mike Stump28431212009-10-13 22:54:56 +0000297
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000298 // FIXME: finish off
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000299 int64_t O = VCallOffset[OGD] - OverrideOffset/8;
Mike Stump72431bd2009-11-06 02:38:24 +0000300
Mike Stump28431212009-10-13 22:54:56 +0000301 if (O || ReturnOffset.first || ReturnOffset.second) {
302 CallOffset ThisOffset = std::make_pair(O, 0);
303
304 if (ReturnOffset.first || ReturnOffset.second)
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000305 CovariantThunks[GD] = std::make_pair(std::make_pair(ThisOffset,
Mike Stump28431212009-10-13 22:54:56 +0000306 ReturnOffset),
307 oret);
Mike Stump375faa82009-10-28 00:35:46 +0000308 else if (!isPure)
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000309 Thunks[GD] = ThisOffset;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000310 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000311 return true;
312 }
313 }
314
315 return false;
316 }
317
318 void InstallThunks() {
319 for (Thunks_t::iterator i = Thunks.begin(), e = Thunks.end();
320 i != e; ++i) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000321 GlobalDecl GD = i->first;
322 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
Mike Stump375faa82009-10-28 00:35:46 +0000323 assert(!MD->isPure() && "Trying to thunk a pure");
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000324 Index_t idx = Index[GD];
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000325 Index_t nv_O = i->second.first;
326 Index_t v_O = i->second.second;
327 submethods[idx] = CGM.BuildThunk(MD, Extern, nv_O, v_O);
328 }
329 Thunks.clear();
330 for (CovariantThunks_t::iterator i = CovariantThunks.begin(),
331 e = CovariantThunks.end();
332 i != e; ++i) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000333 GlobalDecl GD = i->first;
334 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
Mike Stump375faa82009-10-28 00:35:46 +0000335 if (MD->isPure())
336 continue;
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000337 Index_t idx = Index[GD];
Mike Stump87876a02009-10-13 10:55:21 +0000338 Index_t nv_t = i->second.first.first.first;
339 Index_t v_t = i->second.first.first.second;
340 Index_t nv_r = i->second.first.second.first;
341 Index_t v_r = i->second.first.second.second;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000342 submethods[idx] = CGM.BuildCovariantThunk(MD, Extern, nv_t, v_t, nv_r,
343 v_r);
344 }
345 CovariantThunks.clear();
Mike Stumpbb9ff052009-10-27 23:46:47 +0000346 for (Pures_t::iterator i = Pures.begin(), e = Pures.end();
347 i != e; ++i) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000348 GlobalDecl GD = i->first;
349 Index_t idx = Index[GD];
Mike Stumpbb9ff052009-10-27 23:46:47 +0000350 submethods[idx] = cxa_pure;
351 }
352 Pures.clear();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000353 }
354
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000355 llvm::Constant *WrapAddrOf(GlobalDecl GD) {
356 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
357
Mike Stump18e8b472009-10-27 23:36:26 +0000358 if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD))
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000359 return wrap(CGM.GetAddrOfCXXDestructor(Dtor, GD.getDtorType()));
Mike Stump18e8b472009-10-27 23:36:26 +0000360
361 const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
362 const llvm::Type *Ty =
363 CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
364 FPT->isVariadic());
365
366 return wrap(CGM.GetAddrOfFunction(MD, Ty));
367 }
368
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000369 void OverrideMethods(Path_t *Path, bool MorallyVirtual, int64_t Offset,
370 int64_t CurrentVBaseOffset) {
Mike Stump37dbe962009-10-15 02:04:03 +0000371 for (Path_t::reverse_iterator i = Path->rbegin(),
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000372 e = Path->rend(); i != e; ++i) {
373 const CXXRecordDecl *RD = i->first;
Mike Stump8bccbfd2009-10-15 09:30:16 +0000374 int64_t OverrideOffset = i->second;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000375 for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
376 ++mi) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000377 const CXXMethodDecl *MD = *mi;
378
379 if (!MD->isVirtual())
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000380 continue;
381
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000382 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
383 // Override both the complete and the deleting destructor.
384 GlobalDecl CompDtor(DD, Dtor_Complete);
385 OverrideMethod(CompDtor, WrapAddrOf(CompDtor), MorallyVirtual,
386 OverrideOffset, Offset, CurrentVBaseOffset);
387
388 GlobalDecl DeletingDtor(DD, Dtor_Deleting);
389 OverrideMethod(DeletingDtor, WrapAddrOf(DeletingDtor), MorallyVirtual,
390 OverrideOffset, Offset, CurrentVBaseOffset);
391 } else {
392 OverrideMethod(MD, WrapAddrOf(MD), MorallyVirtual, OverrideOffset,
393 Offset, CurrentVBaseOffset);
394 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000395 }
396 }
397 }
398
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000399 void AddMethod(const GlobalDecl GD, bool MorallyVirtual, Index_t Offset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000400 bool ForVirtualBase, int64_t CurrentVBaseOffset) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000401 llvm::Constant *m = WrapAddrOf(GD);
Mike Stump18e8b472009-10-27 23:36:26 +0000402
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000403 // If we can find a previously allocated slot for this, reuse it.
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000404 if (OverrideMethod(GD, m, MorallyVirtual, Offset, Offset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000405 CurrentVBaseOffset))
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000406 return;
407
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000408 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
409
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000410 // else allocate a new slot.
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000411 Index[GD] = submethods.size();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000412 submethods.push_back(m);
Mike Stumpc5a332c2009-11-13 23:45:53 +0000413 D1(printf(" vfn for %s at %d\n", MD->getNameAsString().c_str(),
414 (int)Index[GD]));
Mike Stump375faa82009-10-28 00:35:46 +0000415 if (MD->isPure())
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000416 Pures[GD] = 1;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000417 if (MorallyVirtual) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000418 VCallOffset[GD] = Offset/8;
419 Index_t &idx = VCall[GD];
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000420 // Allocate the first one, after that, we reuse the previous one.
421 if (idx == 0) {
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000422 NonVirtualOffset[GD] = CurrentVBaseOffset/8 - Offset/8;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000423 idx = VCalls.size()+1;
424 VCalls.push_back(0);
Mike Stump75ce5732009-10-31 20:06:59 +0000425 D1(printf(" vcall for %s at %d with delta %d\n",
Mike Stumpc5a332c2009-11-13 23:45:53 +0000426 MD->getNameAsString().c_str(), (int)-VCalls.size()-3, 0));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000427 }
428 }
429 }
430
431 void AddMethods(const CXXRecordDecl *RD, bool MorallyVirtual,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000432 Index_t Offset, bool RDisVirtualBase,
433 int64_t CurrentVBaseOffset) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000434 for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000435 ++mi) {
436 const CXXMethodDecl *MD = *mi;
437 if (!MD->isVirtual())
438 continue;
439
440 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
441 // For destructors, add both the complete and the deleting destructor
442 // to the vtable.
443 AddMethod(GlobalDecl(DD, Dtor_Complete), MorallyVirtual, Offset,
444 RDisVirtualBase, CurrentVBaseOffset);
445 AddMethod(GlobalDecl(DD, Dtor_Deleting), MorallyVirtual, Offset,
446 RDisVirtualBase, CurrentVBaseOffset);
447 } else
448 AddMethod(MD, MorallyVirtual, Offset, RDisVirtualBase,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000449 CurrentVBaseOffset);
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000450 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000451 }
452
453 void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
454 const CXXRecordDecl *PrimaryBase,
455 bool PrimaryBaseWasVirtual, bool MorallyVirtual,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000456 int64_t Offset, int64_t CurrentVBaseOffset,
457 Path_t *Path) {
Mike Stump37dbe962009-10-15 02:04:03 +0000458 Path->push_back(std::make_pair(RD, Offset));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000459 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
460 e = RD->bases_end(); i != e; ++i) {
461 if (i->isVirtual())
462 continue;
463 const CXXRecordDecl *Base =
464 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
465 if (Base != PrimaryBase || PrimaryBaseWasVirtual) {
466 uint64_t o = Offset + Layout.getBaseClassOffset(Base);
467 StartNewTable();
Mike Stump653d0b92009-11-13 02:13:54 +0000468 GenerateVtableForBase(Base, o, MorallyVirtual, false,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000469 CurrentVBaseOffset, Path);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000470 }
471 }
Mike Stump37dbe962009-10-15 02:04:03 +0000472 Path->pop_back();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000473 }
474
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000475// #define D(X) do { X; } while (0)
476#define D(X)
477
478 void insertVCalls(int InsertionPoint) {
479 llvm::Constant *e = 0;
Mike Stump75ce5732009-10-31 20:06:59 +0000480 D1(printf("============= combining vbase/vcall\n"));
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000481 D(VCalls.insert(VCalls.begin(), 673));
482 D(VCalls.push_back(672));
Mike Stump8bccbfd2009-10-15 09:30:16 +0000483 methods.insert(methods.begin() + InsertionPoint, VCalls.size(), e);
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000484 // The vcalls come first...
485 for (std::vector<Index_t>::reverse_iterator i = VCalls.rbegin(),
486 e = VCalls.rend();
487 i != e; ++i)
488 methods[InsertionPoint++] = wrap((0?600:0) + *i);
489 VCalls.clear();
Mike Stump9f23a142009-11-10 02:30:51 +0000490 VCall.clear();
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000491 }
492
Mike Stump559387f2009-11-13 23:13:20 +0000493 void AddAddressPoints(const CXXRecordDecl *RD, uint64_t Offset,
494 Index_t AddressPoint) {
495 D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n",
496 RD->getNameAsCString(), Class->getNameAsCString(),
497 LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
498 AddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
499
500 // Now also add the address point for all our primary bases.
501 while (1) {
502 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
503 RD = Layout.getPrimaryBase();
504 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
505 // FIXME: Double check this.
506 if (RD == 0)
507 break;
508 if (PrimaryBaseWasVirtual &&
509 BLayout.getVBaseClassOffset(RD) != Offset)
510 break;
511 D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n",
512 RD->getNameAsCString(), Class->getNameAsCString(),
513 LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
514 AddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
515 }
516 }
517
518
Mike Stump75ce5732009-10-31 20:06:59 +0000519 Index_t end(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
520 const CXXRecordDecl *PrimaryBase, bool PrimaryBaseWasVirtual,
521 bool MorallyVirtual, int64_t Offset, bool ForVirtualBase,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000522 int64_t CurrentVBaseOffset,
Mike Stump75ce5732009-10-31 20:06:59 +0000523 Path_t *Path) {
Mike Stump37dbe962009-10-15 02:04:03 +0000524 bool alloc = false;
525 if (Path == 0) {
526 alloc = true;
527 Path = new Path_t;
528 }
529
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000530 StartNewTable();
531 extra = 0;
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000532 bool DeferVCalls = MorallyVirtual || ForVirtualBase;
533 int VCallInsertionPoint = methods.size();
534 if (!DeferVCalls) {
535 insertVCalls(VCallInsertionPoint);
Mike Stump8bccbfd2009-10-15 09:30:16 +0000536 } else
537 // FIXME: just for extra, or for all uses of VCalls.size post this?
538 extra = -VCalls.size();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000539
Mike Stump653d0b92009-11-13 02:13:54 +0000540 methods.push_back(wrap(-((Offset-LayoutOffset)/8)));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000541 methods.push_back(rtti);
542 Index_t AddressPoint = methods.size();
543
544 InstallThunks();
Mike Stump75ce5732009-10-31 20:06:59 +0000545 D1(printf("============= combining methods\n"));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000546 methods.insert(methods.end(), submethods.begin(), submethods.end());
547 submethods.clear();
548
549 // and then the non-virtual bases.
550 NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000551 MorallyVirtual, Offset, CurrentVBaseOffset, Path);
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000552
553 if (ForVirtualBase) {
Mike Stump2cefe382009-11-12 20:47:57 +0000554 // FIXME: We're adding to VCalls in callers, we need to do the overrides
555 // in the inner part, so that we know the complete set of vcalls during
556 // the build and don't have to insert into methods. Saving out the
557 // AddressPoint here, would need to be fixed, if we didn't do that. Also
558 // retroactively adding vcalls for overrides later wind up in the wrong
559 // place, the vcall slot has to be alloted during the walk of the base
560 // when the function is first introduces.
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000561 AddressPoint += VCalls.size();
Mike Stump2cefe382009-11-12 20:47:57 +0000562 insertVCalls(VCallInsertionPoint);
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000563 }
564
Mike Stump559387f2009-11-13 23:13:20 +0000565 AddAddressPoints(RD, Offset, AddressPoint);
Mike Stump2cefe382009-11-12 20:47:57 +0000566
Mike Stump37dbe962009-10-15 02:04:03 +0000567 if (alloc) {
568 delete Path;
569 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000570 return AddressPoint;
571 }
572
Mike Stump75ce5732009-10-31 20:06:59 +0000573 void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
574 bool updateVBIndex, Index_t current_vbindex,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000575 bool RDisVirtualBase, int64_t CurrentVBaseOffset) {
Mike Stump75ce5732009-10-31 20:06:59 +0000576 if (!RD->isDynamicClass())
577 return;
578
579 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
580 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
581 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
582
583 // vtables are composed from the chain of primaries.
584 if (PrimaryBase) {
585 D1(printf(" doing primaries for %s most derived %s\n",
586 RD->getNameAsCString(), Class->getNameAsCString()));
587
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000588 int BaseCurrentVBaseOffset = CurrentVBaseOffset;
589 if (PrimaryBaseWasVirtual)
590 BaseCurrentVBaseOffset = BLayout.getVBaseClassOffset(PrimaryBase);
591
Mike Stump75ce5732009-10-31 20:06:59 +0000592 if (!PrimaryBaseWasVirtual)
593 Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000594 updateVBIndex, current_vbindex, PrimaryBaseWasVirtual,
595 BaseCurrentVBaseOffset);
Mike Stump75ce5732009-10-31 20:06:59 +0000596 }
597
598 D1(printf(" doing vcall entries for %s most derived %s\n",
599 RD->getNameAsCString(), Class->getNameAsCString()));
600
601 // And add the virtuals for the class to the primary vtable.
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000602 AddMethods(RD, MorallyVirtual, Offset, RDisVirtualBase, CurrentVBaseOffset);
Mike Stump75ce5732009-10-31 20:06:59 +0000603 }
604
605 void VBPrimaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
606 bool updateVBIndex, Index_t current_vbindex,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000607 bool RDisVirtualBase, int64_t CurrentVBaseOffset,
608 bool bottom=false) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000609 if (!RD->isDynamicClass())
610 return;
611
612 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
613 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
614 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
615
616 // vtables are composed from the chain of primaries.
617 if (PrimaryBase) {
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000618 int BaseCurrentVBaseOffset = CurrentVBaseOffset;
619 if (PrimaryBaseWasVirtual) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000620 IndirectPrimary.insert(PrimaryBase);
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000621 BaseCurrentVBaseOffset = BLayout.getVBaseClassOffset(PrimaryBase);
622 }
Mike Stump75ce5732009-10-31 20:06:59 +0000623
624 D1(printf(" doing primaries for %s most derived %s\n",
625 RD->getNameAsCString(), Class->getNameAsCString()));
626
627 VBPrimaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000628 updateVBIndex, current_vbindex, PrimaryBaseWasVirtual,
629 BaseCurrentVBaseOffset);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000630 }
631
Mike Stump75ce5732009-10-31 20:06:59 +0000632 D1(printf(" doing vbase entries for %s most derived %s\n",
633 RD->getNameAsCString(), Class->getNameAsCString()));
634 GenerateVBaseOffsets(RD, Offset, updateVBIndex, current_vbindex);
635
636 if (RDisVirtualBase || bottom) {
637 Primaries(RD, MorallyVirtual, Offset, updateVBIndex, current_vbindex,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000638 RDisVirtualBase, CurrentVBaseOffset);
Mike Stump75ce5732009-10-31 20:06:59 +0000639 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000640 }
641
Mike Stump653d0b92009-11-13 02:13:54 +0000642 int64_t GenerateVtableForBase(const CXXRecordDecl *RD, int64_t Offset = 0,
643 bool MorallyVirtual = false,
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000644 bool ForVirtualBase = false,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000645 int CurrentVBaseOffset = 0,
Mike Stump37dbe962009-10-15 02:04:03 +0000646 Path_t *Path = 0) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000647 if (!RD->isDynamicClass())
648 return 0;
649
Mike Stumpfa818082009-11-13 02:35:38 +0000650 // Construction vtable don't need parts that have no virtual bases and
651 // aren't morally virtual.
652 if ((LayoutClass != Class) && RD->getNumVBases() == 0 && !MorallyVirtual)
653 return 0;
654
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000655 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
656 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
657 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
658
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000659 extra = 0;
Mike Stump75ce5732009-10-31 20:06:59 +0000660 D1(printf("building entries for base %s most derived %s\n",
661 RD->getNameAsCString(), Class->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000662
Mike Stump75ce5732009-10-31 20:06:59 +0000663 if (ForVirtualBase)
664 extra = VCalls.size();
665
666 VBPrimaries(RD, MorallyVirtual, Offset, !ForVirtualBase, 0, ForVirtualBase,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000667 CurrentVBaseOffset, true);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000668
669 if (Path)
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000670 OverrideMethods(Path, MorallyVirtual, Offset, CurrentVBaseOffset);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000671
Mike Stump75ce5732009-10-31 20:06:59 +0000672 return end(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual, MorallyVirtual,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000673 Offset, ForVirtualBase, CurrentVBaseOffset, Path);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000674 }
675
676 void GenerateVtableForVBases(const CXXRecordDecl *RD,
677 int64_t Offset = 0,
Mike Stump37dbe962009-10-15 02:04:03 +0000678 Path_t *Path = 0) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000679 bool alloc = false;
680 if (Path == 0) {
681 alloc = true;
Mike Stump37dbe962009-10-15 02:04:03 +0000682 Path = new Path_t;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000683 }
684 // FIXME: We also need to override using all paths to a virtual base,
685 // right now, we just process the first path
686 Path->push_back(std::make_pair(RD, Offset));
687 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
688 e = RD->bases_end(); i != e; ++i) {
689 const CXXRecordDecl *Base =
690 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
691 if (i->isVirtual() && !IndirectPrimary.count(Base)) {
692 // Mark it so we don't output it twice.
693 IndirectPrimary.insert(Base);
694 StartNewTable();
Mike Stumpb21c4ee2009-10-14 18:14:51 +0000695 VCall.clear();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000696 int64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000697 int64_t CurrentVBaseOffset = BaseOffset;
Mike Stump75ce5732009-10-31 20:06:59 +0000698 D1(printf("vtable %s virtual base %s\n",
699 Class->getNameAsCString(), Base->getNameAsCString()));
Mike Stump653d0b92009-11-13 02:13:54 +0000700 GenerateVtableForBase(Base, BaseOffset, true, true, CurrentVBaseOffset,
Mike Stumpcd6f9ed2009-11-06 23:27:42 +0000701 Path);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000702 }
Mike Stump2cefe382009-11-12 20:47:57 +0000703 int64_t BaseOffset;
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000704 if (i->isVirtual())
705 BaseOffset = BLayout.getVBaseClassOffset(Base);
Mike Stump2cefe382009-11-12 20:47:57 +0000706 else {
707 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
708 BaseOffset = Offset + Layout.getBaseClassOffset(Base);
709 }
710
Mike Stump37dbe962009-10-15 02:04:03 +0000711 if (Base->getNumVBases()) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000712 GenerateVtableForVBases(Base, BaseOffset, Path);
Mike Stump37dbe962009-10-15 02:04:03 +0000713 }
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000714 }
715 Path->pop_back();
716 if (alloc)
717 delete Path;
718 }
719};
720
721
722VtableBuilder::Index_t VtableBuilder::VBlookup(CXXRecordDecl *D,
723 CXXRecordDecl *B) {
724 return CGM.getVtableInfo().getVirtualBaseOffsetIndex(D, B);
725}
726
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000727int64_t CGVtableInfo::getMethodVtableIndex(GlobalDecl GD) {
728 MethodVtableIndicesTy::iterator I = MethodVtableIndices.find(GD);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000729 if (I != MethodVtableIndices.end())
730 return I->second;
731
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000732 const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000733
734 std::vector<llvm::Constant *> methods;
735 // FIXME: This seems expensive. Can we do a partial job to get
736 // just this data.
Mike Stump653d0b92009-11-13 02:13:54 +0000737 VtableBuilder b(methods, RD, RD, 0, CGM);
Mike Stump75ce5732009-10-31 20:06:59 +0000738 D1(printf("vtable %s\n", RD->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000739 b.GenerateVtableForBase(RD);
740 b.GenerateVtableForVBases(RD);
741
742 MethodVtableIndices.insert(b.getIndex().begin(),
743 b.getIndex().end());
744
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000745 I = MethodVtableIndices.find(GD);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000746 assert(I != MethodVtableIndices.end() && "Did not find index!");
747 return I->second;
748}
749
750int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
751 const CXXRecordDecl *VBase) {
752 ClassPairTy ClassPair(RD, VBase);
753
754 VirtualBaseClassIndiciesTy::iterator I =
755 VirtualBaseClassIndicies.find(ClassPair);
756 if (I != VirtualBaseClassIndicies.end())
757 return I->second;
758
759 std::vector<llvm::Constant *> methods;
760 // FIXME: This seems expensive. Can we do a partial job to get
761 // just this data.
Mike Stump653d0b92009-11-13 02:13:54 +0000762 VtableBuilder b(methods, RD, RD, 0, CGM);
Mike Stump75ce5732009-10-31 20:06:59 +0000763 D1(printf("vtable %s\n", RD->getNameAsCString()));
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000764 b.GenerateVtableForBase(RD);
765 b.GenerateVtableForVBases(RD);
766
767 for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
768 b.getVBIndex().begin(), E = b.getVBIndex().end(); I != E; ++I) {
769 // Insert all types.
770 ClassPairTy ClassPair(RD, I->first);
771
772 VirtualBaseClassIndicies.insert(std::make_pair(ClassPair, I->second));
773 }
774
775 I = VirtualBaseClassIndicies.find(ClassPair);
776 assert(I != VirtualBaseClassIndicies.end() && "Did not find index!");
777
778 return I->second;
779}
780
Mike Stump2cefe382009-11-12 20:47:57 +0000781llvm::Constant *CodeGenModule::GenerateVtable(const CXXRecordDecl *LayoutClass,
782 const CXXRecordDecl *RD,
Mike Stumpeac45592009-11-11 20:26:26 +0000783 uint64_t Offset) {
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000784 llvm::SmallString<256> OutName;
785 llvm::raw_svector_ostream Out(OutName);
Mike Stump2cefe382009-11-12 20:47:57 +0000786 if (LayoutClass != RD)
787 mangleCXXCtorVtable(getMangleContext(), LayoutClass, Offset/8, RD, Out);
Mike Stumpeac45592009-11-11 20:26:26 +0000788 else
789 mangleCXXVtable(getMangleContext(), RD, Out);
Mike Stumpaa51ad62009-11-19 04:04:36 +0000790 llvm::StringRef Name = Out.str();
Benjamin Kramerbb0a07b2009-10-11 22:57:54 +0000791
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000792 std::vector<llvm::Constant *> methods;
793 llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0);
794 int64_t AddressPoint;
795
Mike Stumpaa51ad62009-11-19 04:04:36 +0000796 llvm::GlobalVariable *GV = getModule().getGlobalVariable(Name);
797 if (GV && AddressPoints[LayoutClass] && !GV->isDeclaration())
798 AddressPoint=(*(*(AddressPoints[LayoutClass]))[RD])[std::make_pair(RD,
799 Offset)];
800 else {
801 VtableBuilder b(methods, RD, LayoutClass, Offset, *this);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000802
Mike Stumpaa51ad62009-11-19 04:04:36 +0000803 D1(printf("vtable %s\n", RD->getNameAsCString()));
804 // First comes the vtables for all the non-virtual bases...
805 AddressPoint = b.GenerateVtableForBase(RD, Offset);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000806
Mike Stumpaa51ad62009-11-19 04:04:36 +0000807 // then the vtables for all the virtual bases.
808 b.GenerateVtableForVBases(RD, Offset);
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000809
Mike Stumpaa51ad62009-11-19 04:04:36 +0000810 CodeGenModule::AddrMap_t *&ref = AddressPoints[LayoutClass];
811 if (ref == 0)
812 ref = new CodeGenModule::AddrMap_t;
Mike Stump83066c82009-11-13 01:54:23 +0000813
Mike Stumpaa51ad62009-11-19 04:04:36 +0000814 (*ref)[RD] = b.getAddressPoints();
Mike Stump2cefe382009-11-12 20:47:57 +0000815
Mike Stumpaa51ad62009-11-19 04:04:36 +0000816 bool CreateDefinition = true;
817 if (LayoutClass != RD)
818 CreateDefinition = true;
819 else {
820 // We have to convert it to have a record layout.
821 Types.ConvertTagDeclType(LayoutClass);
822 const CGRecordLayout &CGLayout = Types.getCGRecordLayout(LayoutClass);
823 if (const CXXMethodDecl *KeyFunction = CGLayout.getKeyFunction()) {
824 if (!KeyFunction->getBody()) {
825 // If there is a KeyFunction, and it isn't defined, just build a
826 // reference to the vtable.
827 CreateDefinition = false;
828 }
829 }
830 }
831
832 llvm::Constant *C = 0;
833 llvm::Type *type = Ptr8Ty;
834 llvm::GlobalVariable::LinkageTypes linktype
835 = llvm::GlobalValue::ExternalLinkage;
836 if (CreateDefinition) {
837 llvm::ArrayType *ntype = llvm::ArrayType::get(Ptr8Ty, methods.size());
838 C = llvm::ConstantArray::get(ntype, methods);
839 linktype = llvm::GlobalValue::LinkOnceODRLinkage;
840 if (LayoutClass->isInAnonymousNamespace())
841 linktype = llvm::GlobalValue::InternalLinkage;
842 type = ntype;
843 }
844 llvm::GlobalVariable *OGV = GV;
845 GV = new llvm::GlobalVariable(getModule(), type, true, linktype, C, Name);
846 if (OGV) {
847 GV->takeName(OGV);
848 llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV,
849 OGV->getType());
850 OGV->replaceAllUsesWith(NewPtr);
851 OGV->eraseFromParent();
852 }
853 bool Hidden = getDeclVisibilityMode(RD) == LangOptions::Hidden;
854 if (Hidden)
855 GV->setVisibility(llvm::GlobalVariable::HiddenVisibility);
856 }
Mike Stumpc0f632d2009-11-18 04:00:48 +0000857 llvm::Constant *vtable = llvm::ConstantExpr::getBitCast(GV, Ptr8Ty);
Mike Stumpd846d082009-11-10 07:44:33 +0000858 llvm::Constant *AddressPointC;
859 uint32_t LLVMPointerWidth = getContext().Target.getPointerWidth(0);
860 AddressPointC = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
861 AddressPoint*LLVMPointerWidth/8);
Mike Stump2cefe382009-11-12 20:47:57 +0000862 vtable = llvm::ConstantExpr::getInBoundsGetElementPtr(vtable, &AddressPointC,
863 1);
Mike Stumpd846d082009-11-10 07:44:33 +0000864
Anders Carlsson2bb27f52009-10-11 22:13:54 +0000865 return vtable;
866}
Mike Stump9f23a142009-11-10 02:30:51 +0000867
868class VTTBuilder {
869 /// Inits - The list of values built for the VTT.
870 std::vector<llvm::Constant *> &Inits;
871 /// Class - The most derived class that this vtable is being built for.
872 const CXXRecordDecl *Class;
873 CodeGenModule &CGM; // Per-module state.
Mike Stump8b2d2d02009-11-11 00:35:07 +0000874 llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase;
Mike Stumpc7b9f5e2009-11-11 03:08:24 +0000875 /// BLayout - Layout for the most derived class that this vtable is being
876 /// built for.
877 const ASTRecordLayout &BLayout;
Mike Stump83066c82009-11-13 01:54:23 +0000878 CodeGenModule::AddrMap_t &AddressPoints;
Mike Stump2cefe382009-11-12 20:47:57 +0000879 // vtbl - A pointer to the vtable for Class.
880 llvm::Constant *ClassVtbl;
881 llvm::LLVMContext &VMContext;
Mike Stump9f23a142009-11-10 02:30:51 +0000882
Mike Stump8677bc22009-11-12 22:56:32 +0000883 /// BuildVtablePtr - Build up a referene to the given secondary vtable
Mike Stump83066c82009-11-13 01:54:23 +0000884 llvm::Constant *BuildVtablePtr(llvm::Constant *vtbl,
885 const CXXRecordDecl *VtblClass,
886 const CXXRecordDecl *RD,
Mike Stump8677bc22009-11-12 22:56:32 +0000887 uint64_t Offset) {
888 int64_t AddressPoint;
Mike Stump83066c82009-11-13 01:54:23 +0000889 AddressPoint = (*AddressPoints[VtblClass])[std::make_pair(RD, Offset)];
Mike Stump2b34bc52009-11-12 23:36:21 +0000890 // FIXME: We can never have 0 address point. Do this for now so gepping
891 // retains the same structure.
892 if (AddressPoint == 0)
893 AddressPoint = 1;
Mike Stump83066c82009-11-13 01:54:23 +0000894 D1(printf("XXX address point for %s in %s layout %s at offset %d was %d\n",
895 RD->getNameAsCString(), VtblClass->getNameAsCString(),
896 Class->getNameAsCString(), (int)Offset, (int)AddressPoint));
Mike Stump8677bc22009-11-12 22:56:32 +0000897 uint32_t LLVMPointerWidth = CGM.getContext().Target.getPointerWidth(0);
898 llvm::Constant *init;
899 init = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
900 AddressPoint*LLVMPointerWidth/8);
901 init = llvm::ConstantExpr::getInBoundsGetElementPtr(vtbl, &init, 1);
902 return init;
903 }
904
Mike Stump2cefe382009-11-12 20:47:57 +0000905 /// Secondary - Add the secondary vtable pointers to Inits. Offset is the
906 /// current offset in bits to the object we're working on.
Mike Stump8677bc22009-11-12 22:56:32 +0000907 void Secondary(const CXXRecordDecl *RD, llvm::Constant *vtbl,
Mike Stump83066c82009-11-13 01:54:23 +0000908 const CXXRecordDecl *VtblClass, uint64_t Offset=0,
909 bool MorallyVirtual=false) {
Mike Stump8b2d2d02009-11-11 00:35:07 +0000910 if (RD->getNumVBases() == 0 && ! MorallyVirtual)
911 return;
912
913 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
914 e = RD->bases_end(); i != e; ++i) {
915 const CXXRecordDecl *Base =
916 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
917 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
918 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
919 const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
920 bool NonVirtualPrimaryBase;
921 NonVirtualPrimaryBase = !PrimaryBaseWasVirtual && Base == PrimaryBase;
922 bool BaseMorallyVirtual = MorallyVirtual | i->isVirtual();
Mike Stumpc7b9f5e2009-11-11 03:08:24 +0000923 uint64_t BaseOffset;
924 if (!i->isVirtual()) {
925 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
926 BaseOffset = Offset + Layout.getBaseClassOffset(Base);
927 } else
928 BaseOffset = BLayout.getVBaseClassOffset(Base);
Mike Stump2b34bc52009-11-12 23:36:21 +0000929 llvm::Constant *subvtbl = vtbl;
Mike Stump83066c82009-11-13 01:54:23 +0000930 const CXXRecordDecl *subVtblClass = VtblClass;
Mike Stump8b2d2d02009-11-11 00:35:07 +0000931 if ((Base->getNumVBases() || BaseMorallyVirtual)
932 && !NonVirtualPrimaryBase) {
933 // FIXME: Slightly too many of these for __ZTT8test8_B2
Mike Stump8677bc22009-11-12 22:56:32 +0000934 llvm::Constant *init;
Mike Stump2b34bc52009-11-12 23:36:21 +0000935 if (BaseMorallyVirtual)
Mike Stump83066c82009-11-13 01:54:23 +0000936 init = BuildVtablePtr(vtbl, VtblClass, RD, Offset);
Mike Stump2b34bc52009-11-12 23:36:21 +0000937 else {
Mike Stump8677bc22009-11-12 22:56:32 +0000938 init = CGM.getVtableInfo().getCtorVtable(Class, Base, BaseOffset);
Mike Stump2b34bc52009-11-12 23:36:21 +0000939 subvtbl = dyn_cast<llvm::Constant>(init->getOperand(0));
Mike Stump83066c82009-11-13 01:54:23 +0000940 subVtblClass = Base;
Mike Stump2b34bc52009-11-12 23:36:21 +0000941 }
Mike Stump8677bc22009-11-12 22:56:32 +0000942 Inits.push_back(init);
Mike Stump8b2d2d02009-11-11 00:35:07 +0000943 }
Mike Stump83066c82009-11-13 01:54:23 +0000944 Secondary(Base, subvtbl, subVtblClass, BaseOffset, BaseMorallyVirtual);
Mike Stump8b2d2d02009-11-11 00:35:07 +0000945 }
946 }
947
Mike Stump2cefe382009-11-12 20:47:57 +0000948 /// BuiltVTT - Add the VTT to Inits. Offset is the offset in bits to the
949 /// currnet object we're working on.
950 void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool MorallyVirtual) {
Mike Stump8b2d2d02009-11-11 00:35:07 +0000951 if (RD->getNumVBases() == 0 && !MorallyVirtual)
952 return;
953
Mike Stump2cefe382009-11-12 20:47:57 +0000954 llvm::Constant *init;
Mike Stump83066c82009-11-13 01:54:23 +0000955 const CXXRecordDecl *VtblClass;
956
Mike Stump8b2d2d02009-11-11 00:35:07 +0000957 // First comes the primary virtual table pointer...
Mike Stump83066c82009-11-13 01:54:23 +0000958 if (MorallyVirtual) {
959 init = BuildVtablePtr(ClassVtbl, Class, RD, Offset);
960 VtblClass = Class;
961 } else {
Mike Stump2cefe382009-11-12 20:47:57 +0000962 init = CGM.getVtableInfo().getCtorVtable(Class, RD, Offset);
Mike Stump83066c82009-11-13 01:54:23 +0000963 VtblClass = RD;
964 }
Mike Stump8677bc22009-11-12 22:56:32 +0000965 llvm::Constant *vtbl = dyn_cast<llvm::Constant>(init->getOperand(0));
Mike Stump2cefe382009-11-12 20:47:57 +0000966 Inits.push_back(init);
Mike Stump8b2d2d02009-11-11 00:35:07 +0000967
968 // then the secondary VTTs....
Mike Stump2cefe382009-11-12 20:47:57 +0000969 SecondaryVTTs(RD, Offset, MorallyVirtual);
Mike Stump8b2d2d02009-11-11 00:35:07 +0000970
971 // and last the secondary vtable pointers.
Mike Stump83066c82009-11-13 01:54:23 +0000972 Secondary(RD, vtbl, VtblClass, Offset, MorallyVirtual);
Mike Stump8b2d2d02009-11-11 00:35:07 +0000973 }
974
975 /// SecondaryVTTs - Add the secondary VTTs to Inits. The secondary VTTs are
976 /// built from each direct non-virtual proper base that requires a VTT in
977 /// declaration order.
Mike Stump2cefe382009-11-12 20:47:57 +0000978 void SecondaryVTTs(const CXXRecordDecl *RD, uint64_t Offset=0,
979 bool MorallyVirtual=false) {
Mike Stump8b2d2d02009-11-11 00:35:07 +0000980 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
981 e = RD->bases_end(); i != e; ++i) {
982 const CXXRecordDecl *Base =
983 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
984 if (i->isVirtual())
985 continue;
Mike Stump2cefe382009-11-12 20:47:57 +0000986 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
987 uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base);
988 BuildVTT(Base, BaseOffset, MorallyVirtual);
Mike Stump8b2d2d02009-11-11 00:35:07 +0000989 }
990 }
991
992 /// VirtualVTTs - Add the VTT for each proper virtual base in inheritance
993 /// graph preorder.
994 void VirtualVTTs(const CXXRecordDecl *RD) {
995 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
996 e = RD->bases_end(); i != e; ++i) {
997 const CXXRecordDecl *Base =
998 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
999 if (i->isVirtual() && !SeenVBase.count(Base)) {
1000 SeenVBase.insert(Base);
Mike Stump2cefe382009-11-12 20:47:57 +00001001 uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
1002 BuildVTT(Base, BaseOffset, true);
Mike Stump8b2d2d02009-11-11 00:35:07 +00001003 }
1004 VirtualVTTs(Base);
1005 }
1006 }
Mike Stump9f23a142009-11-10 02:30:51 +00001007public:
1008 VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c,
Mike Stumpc7b9f5e2009-11-11 03:08:24 +00001009 CodeGenModule &cgm)
1010 : Inits(inits), Class(c), CGM(cgm),
Mike Stump2cefe382009-11-12 20:47:57 +00001011 BLayout(cgm.getContext().getASTRecordLayout(c)),
Mike Stump83066c82009-11-13 01:54:23 +00001012 AddressPoints(*cgm.AddressPoints[c]),
Mike Stump2cefe382009-11-12 20:47:57 +00001013 VMContext(cgm.getModule().getContext()) {
Mike Stumpd846d082009-11-10 07:44:33 +00001014
Mike Stump8b2d2d02009-11-11 00:35:07 +00001015 // First comes the primary virtual table pointer for the complete class...
Mike Stump2cefe382009-11-12 20:47:57 +00001016 ClassVtbl = CGM.getVtableInfo().getVtable(Class);
1017 Inits.push_back(ClassVtbl);
1018 ClassVtbl = dyn_cast<llvm::Constant>(ClassVtbl->getOperand(0));
1019
Mike Stump8b2d2d02009-11-11 00:35:07 +00001020 // then the secondary VTTs...
1021 SecondaryVTTs(Class);
1022
1023 // then the secondary vtable pointers...
Mike Stump83066c82009-11-13 01:54:23 +00001024 Secondary(Class, ClassVtbl, Class);
Mike Stump8b2d2d02009-11-11 00:35:07 +00001025
1026 // and last, the virtual VTTs.
1027 VirtualVTTs(Class);
Mike Stump9f23a142009-11-10 02:30:51 +00001028 }
1029};
1030
Mike Stumpd846d082009-11-10 07:44:33 +00001031llvm::Constant *CodeGenModule::GenerateVTT(const CXXRecordDecl *RD) {
Mike Stumpb4722212009-11-10 19:13:04 +00001032 // Only classes that have virtual bases need a VTT.
1033 if (RD->getNumVBases() == 0)
1034 return 0;
1035
Mike Stump9f23a142009-11-10 02:30:51 +00001036 llvm::SmallString<256> OutName;
1037 llvm::raw_svector_ostream Out(OutName);
Mike Stumpd846d082009-11-10 07:44:33 +00001038 mangleCXXVTT(getMangleContext(), RD, Out);
Mike Stumpaa51ad62009-11-19 04:04:36 +00001039 llvm::StringRef Name = Out.str();
Mike Stump9f23a142009-11-10 02:30:51 +00001040
1041 llvm::GlobalVariable::LinkageTypes linktype;
1042 linktype = llvm::GlobalValue::LinkOnceODRLinkage;
Mike Stumpaa51ad62009-11-19 04:04:36 +00001043 if (RD->isInAnonymousNamespace())
1044 linktype = llvm::GlobalValue::InternalLinkage;
Mike Stump9f23a142009-11-10 02:30:51 +00001045 std::vector<llvm::Constant *> inits;
1046 llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0);
1047
Mike Stump9f23a142009-11-10 02:30:51 +00001048 D1(printf("vtt %s\n", RD->getNameAsCString()));
1049
Mike Stump8b2d2d02009-11-11 00:35:07 +00001050 VTTBuilder b(inits, RD, *this);
1051
Mike Stump9f23a142009-11-10 02:30:51 +00001052 llvm::Constant *C;
1053 llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, inits.size());
1054 C = llvm::ConstantArray::get(type, inits);
Mike Stumpc0f632d2009-11-18 04:00:48 +00001055 llvm::GlobalVariable *vtt = new llvm::GlobalVariable(getModule(), type, true,
Mike Stumpaa51ad62009-11-19 04:04:36 +00001056 linktype, C, Name);
Mike Stumpc0f632d2009-11-18 04:00:48 +00001057 bool Hidden = getDeclVisibilityMode(RD) == LangOptions::Hidden;
1058 if (Hidden)
1059 vtt->setVisibility(llvm::GlobalVariable::HiddenVisibility);
1060 return llvm::ConstantExpr::getBitCast(vtt, Ptr8Ty);
Mike Stump9f23a142009-11-10 02:30:51 +00001061}
Mike Stumpd846d082009-11-10 07:44:33 +00001062
Mike Stump1a139f82009-11-19 01:08:19 +00001063void CGVtableInfo::GenerateClassData(const CXXRecordDecl *RD) {
1064 Vtables[RD] = CGM.GenerateVtable(RD, RD);
1065 CGM.GenerateRtti(RD);
1066 CGM.GenerateVTT(RD);
1067}
1068
Mike Stumpeac45592009-11-11 20:26:26 +00001069llvm::Constant *CGVtableInfo::getVtable(const CXXRecordDecl *RD) {
Mike Stumpd846d082009-11-10 07:44:33 +00001070 llvm::Constant *&vtbl = Vtables[RD];
1071 if (vtbl)
1072 return vtbl;
Mike Stump2cefe382009-11-12 20:47:57 +00001073 vtbl = CGM.GenerateVtable(RD, RD);
Mike Stumpaa51ad62009-11-19 04:04:36 +00001074
1075 bool CreateDefinition = true;
1076 // We have to convert it to have a record layout.
1077 CGM.getTypes().ConvertTagDeclType(RD);
1078 const CGRecordLayout &CGLayout = CGM.getTypes().getCGRecordLayout(RD);
1079 if (const CXXMethodDecl *KeyFunction = CGLayout.getKeyFunction()) {
1080 if (!KeyFunction->getBody()) {
1081 // If there is a KeyFunction, and it isn't defined, just build a
1082 // reference to the vtable.
1083 CreateDefinition = false;
1084 }
1085 }
1086
1087 if (CreateDefinition) {
1088 CGM.GenerateRtti(RD);
1089 CGM.GenerateVTT(RD);
1090 }
Mike Stumpd846d082009-11-10 07:44:33 +00001091 return vtbl;
1092}
Mike Stumpeac45592009-11-11 20:26:26 +00001093
Mike Stump2cefe382009-11-12 20:47:57 +00001094llvm::Constant *CGVtableInfo::getCtorVtable(const CXXRecordDecl *LayoutClass,
1095 const CXXRecordDecl *RD,
Mike Stumpeac45592009-11-11 20:26:26 +00001096 uint64_t Offset) {
Mike Stump2cefe382009-11-12 20:47:57 +00001097 return CGM.GenerateVtable(LayoutClass, RD, Offset);
Mike Stumpeac45592009-11-11 20:26:26 +00001098}