blob: 77687488be4a616456e210f3d24892b0798dd984 [file] [log] [blame]
Anders Carlssondbd920c2009-10-11 22:13:54 +00001//===--- CGVtable.h - 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#ifndef CLANG_CODEGEN_CGVTABLE_H
15#define CLANG_CODEGEN_CGVTABLE_H
16
17#include "llvm/ADT/DenseMap.h"
Eli Friedman72649ed2009-12-06 22:01:30 +000018#include "llvm/ADT/DenseSet.h"
Anders Carlsson35272252009-12-06 00:23:49 +000019#include "llvm/GlobalVariable.h"
Anders Carlssona0fdd912009-11-13 17:08:56 +000020#include "GlobalDecl.h"
Anders Carlssondbd920c2009-10-11 22:13:54 +000021
22namespace clang {
Anders Carlssondbd920c2009-10-11 22:13:54 +000023 class CXXRecordDecl;
Benjamin Kramer39411b92009-11-26 13:09:03 +000024
Anders Carlssondbd920c2009-10-11 22:13:54 +000025namespace CodeGen {
26 class CodeGenModule;
Anders Carlssona94822e2009-11-26 02:32:05 +000027
Anders Carlsson80d8d7d2010-03-23 15:13:06 +000028/// ReturnAdjustment - A return adjustment.
29struct ReturnAdjustment {
30 /// NonVirtual - The non-virtual adjustment from the derived object to its
31 /// nearest virtual base.
32 int64_t NonVirtual;
33
34 /// VBaseOffsetOffset - The offset (in bytes), relative to the address point
35 /// of the virtual base class offset.
36 int64_t VBaseOffsetOffset;
37
38 ReturnAdjustment() : NonVirtual(0), VBaseOffsetOffset(0) { }
39
40 bool isEmpty() const { return !NonVirtual && !VBaseOffsetOffset; }
41
42 friend bool operator==(const ReturnAdjustment &LHS,
43 const ReturnAdjustment &RHS) {
44 return LHS.NonVirtual == RHS.NonVirtual &&
45 LHS.VBaseOffsetOffset == RHS.VBaseOffsetOffset;
46 }
47
48 friend bool operator<(const ReturnAdjustment &LHS,
49 const ReturnAdjustment &RHS) {
50 if (LHS.NonVirtual < RHS.NonVirtual)
51 return true;
52
53 return LHS.NonVirtual == RHS.NonVirtual &&
54 LHS.VBaseOffsetOffset < RHS.VBaseOffsetOffset;
55 }
56};
57
58/// ThisAdjustment - A 'this' pointer adjustment.
59struct ThisAdjustment {
60 /// NonVirtual - The non-virtual adjustment from the derived object to its
61 /// nearest virtual base.
62 int64_t NonVirtual;
63
64 /// VCallOffsetOffset - The offset (in bytes), relative to the address point,
65 /// of the virtual call offset.
66 int64_t VCallOffsetOffset;
67
68 ThisAdjustment() : NonVirtual(0), VCallOffsetOffset(0) { }
69
70 bool isEmpty() const { return !NonVirtual && !VCallOffsetOffset; }
71
72 friend bool operator==(const ThisAdjustment &LHS,
73 const ThisAdjustment &RHS) {
74 return LHS.NonVirtual == RHS.NonVirtual &&
75 LHS.VCallOffsetOffset == RHS.VCallOffsetOffset;
76 }
77
78 friend bool operator<(const ThisAdjustment &LHS,
79 const ThisAdjustment &RHS) {
80 if (LHS.NonVirtual < RHS.NonVirtual)
81 return true;
82
83 return LHS.NonVirtual == RHS.NonVirtual &&
84 LHS.VCallOffsetOffset < RHS.VCallOffsetOffset;
85 }
86
87};
88
Benjamin Kramer39411b92009-11-26 13:09:03 +000089/// ThunkAdjustment - Virtual and non-virtual adjustment for thunks.
90class ThunkAdjustment {
91public:
Anders Carlssona94822e2009-11-26 02:32:05 +000092 ThunkAdjustment(int64_t NonVirtual, int64_t Virtual)
Benjamin Kramer39411b92009-11-26 13:09:03 +000093 : NonVirtual(NonVirtual),
Anders Carlssona94822e2009-11-26 02:32:05 +000094 Virtual(Virtual) { }
Benjamin Kramer39411b92009-11-26 13:09:03 +000095
Anders Carlssona94822e2009-11-26 02:32:05 +000096 ThunkAdjustment()
97 : NonVirtual(0), Virtual(0) { }
Benjamin Kramer39411b92009-11-26 13:09:03 +000098
Anders Carlssona94822e2009-11-26 02:32:05 +000099 // isEmpty - Return whether this thunk adjustment is empty.
Benjamin Kramer39411b92009-11-26 13:09:03 +0000100 bool isEmpty() const {
Anders Carlssona94822e2009-11-26 02:32:05 +0000101 return NonVirtual == 0 && Virtual == 0;
102 }
Benjamin Kramer39411b92009-11-26 13:09:03 +0000103
Anders Carlssona94822e2009-11-26 02:32:05 +0000104 /// NonVirtual - The non-virtual adjustment.
105 int64_t NonVirtual;
Benjamin Kramer39411b92009-11-26 13:09:03 +0000106
Anders Carlssona94822e2009-11-26 02:32:05 +0000107 /// Virtual - The virtual adjustment.
108 int64_t Virtual;
109};
110
Anders Carlsson7622cd32009-11-26 03:09:37 +0000111/// CovariantThunkAdjustment - Adjustment of the 'this' pointer and the
112/// return pointer for covariant thunks.
Benjamin Kramer39411b92009-11-26 13:09:03 +0000113class CovariantThunkAdjustment {
114public:
Anders Carlsson7622cd32009-11-26 03:09:37 +0000115 CovariantThunkAdjustment(const ThunkAdjustment &ThisAdjustment,
116 const ThunkAdjustment &ReturnAdjustment)
117 : ThisAdjustment(ThisAdjustment), ReturnAdjustment(ReturnAdjustment) { }
118
119 CovariantThunkAdjustment() { }
120
121 ThunkAdjustment ThisAdjustment;
122 ThunkAdjustment ReturnAdjustment;
123};
124
Anders Carlsson6b4333d2010-01-13 20:11:15 +0000125// BaseSubobject - Uniquely identifies a direct or indirect base class.
126// Stores both the base class decl and the offset from the most derived class to
127// the base class.
128class BaseSubobject {
129 /// Base - The base class declaration.
130 const CXXRecordDecl *Base;
131
132 /// BaseOffset - The offset from the most derived class to the base class.
133 uint64_t BaseOffset;
134
135public:
136 BaseSubobject(const CXXRecordDecl *Base, uint64_t BaseOffset)
137 : Base(Base), BaseOffset(BaseOffset) { }
138
139 /// getBase - Returns the base class declaration.
140 const CXXRecordDecl *getBase() const { return Base; }
141
142 /// getBaseOffset - Returns the base class offset.
143 uint64_t getBaseOffset() const { return BaseOffset; }
Anders Carlsson7e37a692010-01-14 01:39:42 +0000144
Anders Carlsson6b4333d2010-01-13 20:11:15 +0000145 friend bool operator==(const BaseSubobject &LHS, const BaseSubobject &RHS) {
146 return LHS.Base == RHS.Base && LHS.BaseOffset == RHS.BaseOffset;
147 }
148};
Anders Carlsson7e37a692010-01-14 01:39:42 +0000149
150} // end namespace CodeGen
151} // end namespace clang
152
153namespace llvm {
154
155template<> struct DenseMapInfo<clang::CodeGen::BaseSubobject> {
156 static clang::CodeGen::BaseSubobject getEmptyKey() {
157 return clang::CodeGen::BaseSubobject(
158 DenseMapInfo<const clang::CXXRecordDecl *>::getEmptyKey(),
159 DenseMapInfo<uint64_t>::getEmptyKey());
160 }
161
162 static clang::CodeGen::BaseSubobject getTombstoneKey() {
163 return clang::CodeGen::BaseSubobject(
164 DenseMapInfo<const clang::CXXRecordDecl *>::getTombstoneKey(),
165 DenseMapInfo<uint64_t>::getTombstoneKey());
166 }
167
168 static unsigned getHashValue(const clang::CodeGen::BaseSubobject &Base) {
169 return
170 DenseMapInfo<const clang::CXXRecordDecl *>::getHashValue(Base.getBase()) ^
171 DenseMapInfo<uint64_t>::getHashValue(Base.getBaseOffset());
172 }
173
174 static bool isEqual(const clang::CodeGen::BaseSubobject &LHS,
175 const clang::CodeGen::BaseSubobject &RHS) {
176 return LHS == RHS;
177 }
178};
179
Anders Carlsson1bb60992010-01-14 02:29:07 +0000180// It's OK to treat BaseSubobject as a POD type.
181template <> struct isPodLike<clang::CodeGen::BaseSubobject> {
182 static const bool value = true;
183};
184
Anders Carlsson7e37a692010-01-14 01:39:42 +0000185}
186
187namespace clang {
188namespace CodeGen {
189
Anders Carlssonaf440352010-03-23 04:11:45 +0000190class CodeGenVTables {
Eli Friedmanb455f0e2009-12-07 23:56:34 +0000191public:
192 typedef std::vector<std::pair<GlobalDecl, ThunkAdjustment> >
193 AdjustmentVectorTy;
194
Anders Carlsson21431c52010-01-02 18:02:32 +0000195 typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
196 typedef llvm::DenseMap<CtorVtable_t, int64_t> AddrSubMap_t;
197 typedef llvm::DenseMap<const CXXRecordDecl *, AddrSubMap_t *> AddrMap_t;
198 llvm::DenseMap<const CXXRecordDecl *, AddrMap_t*> AddressPoints;
199
Anders Carlsson1bb60992010-01-14 02:29:07 +0000200 typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
201
Eli Friedmanb455f0e2009-12-07 23:56:34 +0000202private:
Anders Carlssondbd920c2009-10-11 22:13:54 +0000203 CodeGenModule &CGM;
Benjamin Kramer39411b92009-11-26 13:09:03 +0000204
Anders Carlssondbd920c2009-10-11 22:13:54 +0000205 /// MethodVtableIndices - Contains the index (relative to the vtable address
206 /// point) where the function pointer for a virtual function is stored.
Anders Carlssona0fdd912009-11-13 17:08:56 +0000207 typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVtableIndicesTy;
Anders Carlssondbd920c2009-10-11 22:13:54 +0000208 MethodVtableIndicesTy MethodVtableIndices;
Benjamin Kramer39411b92009-11-26 13:09:03 +0000209
Anders Carlssondbd920c2009-10-11 22:13:54 +0000210 typedef std::pair<const CXXRecordDecl *,
211 const CXXRecordDecl *> ClassPairTy;
Benjamin Kramer39411b92009-11-26 13:09:03 +0000212
Anders Carlssonbba16072010-03-11 07:15:17 +0000213 /// VirtualBaseClassOffsetOffsets - Contains the vtable offset (relative to
214 /// the address point) in bytes where the offsets for virtual bases of a class
215 /// are stored.
216 typedef llvm::DenseMap<ClassPairTy, int64_t>
217 VirtualBaseClassOffsetOffsetsMapTy;
218 VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets;
Mike Stump380dd752009-11-10 07:44:33 +0000219
Anders Carlsson8c2d36f2009-12-06 00:01:05 +0000220 /// Vtables - All the vtables which have been defined.
221 llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> Vtables;
Anders Carlssond6b07fb2009-11-27 20:47:55 +0000222
223 /// NumVirtualFunctionPointers - Contains the number of virtual function
224 /// pointers in the vtable for a given record decl.
225 llvm::DenseMap<const CXXRecordDecl *, uint64_t> NumVirtualFunctionPointers;
226
Eli Friedmanb455f0e2009-12-07 23:56:34 +0000227 typedef llvm::DenseMap<GlobalDecl, AdjustmentVectorTy> SavedAdjustmentsTy;
228 SavedAdjustmentsTy SavedAdjustments;
229 llvm::DenseSet<const CXXRecordDecl*> SavedAdjustmentRecords;
Eli Friedman72649ed2009-12-06 22:01:30 +0000230
Anders Carlssonc997d422010-01-02 01:01:18 +0000231 typedef llvm::DenseMap<ClassPairTy, uint64_t> SubVTTIndiciesTy;
232 SubVTTIndiciesTy SubVTTIndicies;
233
Anders Carlssond6b07fb2009-11-27 20:47:55 +0000234 /// getNumVirtualFunctionPointers - Return the number of virtual function
235 /// pointers in the vtable for a given record decl.
236 uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD);
237
238 void ComputeMethodVtableIndices(const CXXRecordDecl *RD);
Rafael Espindolabbf58bb2010-03-10 02:19:29 +0000239
Anders Carlsson35272252009-12-06 00:23:49 +0000240 llvm::GlobalVariable *
Anders Carlsson35272252009-12-06 00:23:49 +0000241 GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
Anders Carlsson5794c972009-12-06 00:53:22 +0000242 bool GenerateDefinition, const CXXRecordDecl *LayoutClass,
Anders Carlsson5d7af6b2010-02-28 00:36:23 +0000243 const CXXRecordDecl *RD, uint64_t Offset, bool IsVirtual,
Anders Carlsson1bb60992010-01-14 02:29:07 +0000244 AddressPointsMapTy& AddressPoints);
Anders Carlssonc3a46ef2009-12-06 01:09:21 +0000245
246 llvm::GlobalVariable *GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
Anders Carlssonc997d422010-01-02 01:01:18 +0000247 bool GenerateDefinition,
Anders Carlssonc3a46ef2009-12-06 01:09:21 +0000248 const CXXRecordDecl *RD);
249
Anders Carlssonee5ab9f2010-03-23 04:59:02 +0000250 /// EmitThunks - Emit the associated thunks for the given global decl.
251 void EmitThunks(GlobalDecl GD);
252
Anders Carlssondbd920c2009-10-11 22:13:54 +0000253public:
Anders Carlssonaf440352010-03-23 04:11:45 +0000254 CodeGenVTables(CodeGenModule &CGM)
Anders Carlssondbd920c2009-10-11 22:13:54 +0000255 : CGM(CGM) { }
256
Anders Carlssonc997d422010-01-02 01:01:18 +0000257 /// needsVTTParameter - Return whether the given global decl needs a VTT
258 /// parameter, which it does if it's a base constructor or destructor with
259 /// virtual bases.
260 static bool needsVTTParameter(GlobalDecl GD);
261
262 /// getSubVTTIndex - Return the index of the sub-VTT for the base class of the
263 /// given record decl.
264 uint64_t getSubVTTIndex(const CXXRecordDecl *RD, const CXXRecordDecl *Base);
265
Anders Carlssondbd920c2009-10-11 22:13:54 +0000266 /// getMethodVtableIndex - Return the index (relative to the vtable address
Benjamin Kramer39411b92009-11-26 13:09:03 +0000267 /// point) where the function pointer for the given virtual function is
Anders Carlssondbd920c2009-10-11 22:13:54 +0000268 /// stored.
Anders Carlssond6b07fb2009-11-27 20:47:55 +0000269 uint64_t getMethodVtableIndex(GlobalDecl GD);
Benjamin Kramer39411b92009-11-26 13:09:03 +0000270
Anders Carlssonbba16072010-03-11 07:15:17 +0000271 /// getVirtualBaseOffsetOffset - Return the offset in bytes (relative to the
272 /// vtable address point) where the offset of the virtual base that contains
273 /// the given base is stored, otherwise, if no virtual base contains the given
Mike Stumpab28c132009-10-13 22:54:56 +0000274 /// class, return 0. Base must be a virtual base class or an unambigious
275 /// base.
Anders Carlssonbba16072010-03-11 07:15:17 +0000276 int64_t getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
277 const CXXRecordDecl *VBase);
Mike Stump380dd752009-11-10 07:44:33 +0000278
Eli Friedmanb455f0e2009-12-07 23:56:34 +0000279 AdjustmentVectorTy *getAdjustments(GlobalDecl GD);
Eli Friedman72649ed2009-12-06 22:01:30 +0000280
Anders Carlsson8c2d36f2009-12-06 00:01:05 +0000281 llvm::GlobalVariable *getVtable(const CXXRecordDecl *RD);
Anders Carlsson1bb60992010-01-14 02:29:07 +0000282
283 /// CtorVtableInfo - Information about a constructor vtable.
284 struct CtorVtableInfo {
285 /// Vtable - The vtable itself.
286 llvm::GlobalVariable *Vtable;
287
288 /// AddressPoints - The address points in this constructor vtable.
289 AddressPointsMapTy AddressPoints;
290
291 CtorVtableInfo() : Vtable(0) { }
292 };
293
294 CtorVtableInfo getCtorVtable(const CXXRecordDecl *RD,
Anders Carlsson5d7af6b2010-02-28 00:36:23 +0000295 const BaseSubobject &Base,
296 bool BaseIsVirtual);
Anders Carlsson1a5e0d72009-11-30 23:41:22 +0000297
Anders Carlssonc997d422010-01-02 01:01:18 +0000298 llvm::GlobalVariable *getVTT(const CXXRecordDecl *RD);
Anders Carlsson1a5e0d72009-11-30 23:41:22 +0000299
Anders Carlsson13189d02010-03-23 04:15:00 +0000300 // EmitVTableRelatedData - Will emit any thunks that the global decl might
301 // have, as well as the vtable itself if the global decl is the key function.
302 void EmitVTableRelatedData(GlobalDecl GD);
Rafael Espindolabbf58bb2010-03-10 02:19:29 +0000303
304 /// GenerateClassData - Generate all the class data requires to be generated
305 /// upon definition of a KeyFunction. This includes the vtable, the
306 /// rtti data structure and the VTT.
307 ///
308 /// \param Linkage - The desired linkage of the vtable, the RTTI and the VTT.
309 void GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
310 const CXXRecordDecl *RD);
Anders Carlssondbd920c2009-10-11 22:13:54 +0000311};
Benjamin Kramer39411b92009-11-26 13:09:03 +0000312
Anders Carlsson1bb60992010-01-14 02:29:07 +0000313} // end namespace CodeGen
314} // end namespace clang
Anders Carlssondbd920c2009-10-11 22:13:54 +0000315#endif