John McCall | bda0d6b | 2011-03-27 09:00:25 +0000 | [diff] [blame] | 1 | //===--- CGVTables.h - Emit LLVM Code for C++ vtables -----------*- C++ -*-===// |
Anders Carlsson | dbd920c | 2009-10-11 22:13:54 +0000 | [diff] [blame] | 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" |
Anders Carlsson | 3527225 | 2009-12-06 00:23:49 +0000 | [diff] [blame] | 18 | #include "llvm/GlobalVariable.h" |
Peter Collingbourne | 1411047 | 2011-01-13 18:57:25 +0000 | [diff] [blame] | 19 | #include "clang/Basic/ABI.h" |
Peter Collingbourne | 33446f1 | 2011-09-26 01:56:16 +0000 | [diff] [blame] | 20 | #include "clang/AST/BaseSubobject.h" |
Ken Dyck | 4230d52 | 2011-03-24 01:21:01 +0000 | [diff] [blame] | 21 | #include "clang/AST/CharUnits.h" |
Peter Collingbourne | fd05ca0 | 2011-06-14 04:02:39 +0000 | [diff] [blame] | 22 | #include "clang/AST/GlobalDecl.h" |
Anders Carlsson | dbd920c | 2009-10-11 22:13:54 +0000 | [diff] [blame] | 23 | |
| 24 | namespace clang { |
Anders Carlsson | dbd920c | 2009-10-11 22:13:54 +0000 | [diff] [blame] | 25 | class CXXRecordDecl; |
Benjamin Kramer | 39411b9 | 2009-11-26 13:09:03 +0000 | [diff] [blame] | 26 | |
Anders Carlsson | dbd920c | 2009-10-11 22:13:54 +0000 | [diff] [blame] | 27 | namespace CodeGen { |
| 28 | class CodeGenModule; |
Anders Carlsson | a94822e | 2009-11-26 02:32:05 +0000 | [diff] [blame] | 29 | |
Peter Collingbourne | ba6ffeb | 2011-09-26 01:56:45 +0000 | [diff] [blame] | 30 | /// VTableComponent - Represents a single component in a vtable. |
| 31 | class VTableComponent { |
| 32 | public: |
| 33 | enum Kind { |
| 34 | CK_VCallOffset, |
| 35 | CK_VBaseOffset, |
| 36 | CK_OffsetToTop, |
| 37 | CK_RTTI, |
| 38 | CK_FunctionPointer, |
| 39 | |
| 40 | /// CK_CompleteDtorPointer - A pointer to the complete destructor. |
| 41 | CK_CompleteDtorPointer, |
| 42 | |
| 43 | /// CK_DeletingDtorPointer - A pointer to the deleting destructor. |
| 44 | CK_DeletingDtorPointer, |
| 45 | |
| 46 | /// CK_UnusedFunctionPointer - In some cases, a vtable function pointer |
| 47 | /// will end up never being called. Such vtable function pointers are |
| 48 | /// represented as a CK_UnusedFunctionPointer. |
| 49 | CK_UnusedFunctionPointer |
| 50 | }; |
| 51 | |
Peter Collingbourne | e09cdf4 | 2011-09-26 01:56:50 +0000 | [diff] [blame] | 52 | VTableComponent() { } |
| 53 | |
Peter Collingbourne | ba6ffeb | 2011-09-26 01:56:45 +0000 | [diff] [blame] | 54 | static VTableComponent MakeVCallOffset(CharUnits Offset) { |
| 55 | return VTableComponent(CK_VCallOffset, Offset); |
| 56 | } |
| 57 | |
| 58 | static VTableComponent MakeVBaseOffset(CharUnits Offset) { |
| 59 | return VTableComponent(CK_VBaseOffset, Offset); |
| 60 | } |
| 61 | |
| 62 | static VTableComponent MakeOffsetToTop(CharUnits Offset) { |
| 63 | return VTableComponent(CK_OffsetToTop, Offset); |
| 64 | } |
| 65 | |
| 66 | static VTableComponent MakeRTTI(const CXXRecordDecl *RD) { |
| 67 | return VTableComponent(CK_RTTI, reinterpret_cast<uintptr_t>(RD)); |
| 68 | } |
| 69 | |
| 70 | static VTableComponent MakeFunction(const CXXMethodDecl *MD) { |
| 71 | assert(!isa<CXXDestructorDecl>(MD) && |
| 72 | "Don't use MakeFunction with destructors!"); |
| 73 | |
| 74 | return VTableComponent(CK_FunctionPointer, |
| 75 | reinterpret_cast<uintptr_t>(MD)); |
| 76 | } |
| 77 | |
| 78 | static VTableComponent MakeCompleteDtor(const CXXDestructorDecl *DD) { |
| 79 | return VTableComponent(CK_CompleteDtorPointer, |
| 80 | reinterpret_cast<uintptr_t>(DD)); |
| 81 | } |
| 82 | |
| 83 | static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD) { |
| 84 | return VTableComponent(CK_DeletingDtorPointer, |
| 85 | reinterpret_cast<uintptr_t>(DD)); |
| 86 | } |
| 87 | |
| 88 | static VTableComponent MakeUnusedFunction(const CXXMethodDecl *MD) { |
| 89 | assert(!isa<CXXDestructorDecl>(MD) && |
| 90 | "Don't use MakeUnusedFunction with destructors!"); |
| 91 | return VTableComponent(CK_UnusedFunctionPointer, |
| 92 | reinterpret_cast<uintptr_t>(MD)); |
| 93 | } |
| 94 | |
| 95 | static VTableComponent getFromOpaqueInteger(uint64_t I) { |
| 96 | return VTableComponent(I); |
| 97 | } |
| 98 | |
| 99 | /// getKind - Get the kind of this vtable component. |
| 100 | Kind getKind() const { |
| 101 | return (Kind)(Value & 0x7); |
| 102 | } |
| 103 | |
| 104 | CharUnits getVCallOffset() const { |
| 105 | assert(getKind() == CK_VCallOffset && "Invalid component kind!"); |
| 106 | |
| 107 | return getOffset(); |
| 108 | } |
| 109 | |
| 110 | CharUnits getVBaseOffset() const { |
| 111 | assert(getKind() == CK_VBaseOffset && "Invalid component kind!"); |
| 112 | |
| 113 | return getOffset(); |
| 114 | } |
| 115 | |
| 116 | CharUnits getOffsetToTop() const { |
| 117 | assert(getKind() == CK_OffsetToTop && "Invalid component kind!"); |
| 118 | |
| 119 | return getOffset(); |
| 120 | } |
| 121 | |
| 122 | const CXXRecordDecl *getRTTIDecl() const { |
| 123 | assert(getKind() == CK_RTTI && "Invalid component kind!"); |
| 124 | |
| 125 | return reinterpret_cast<CXXRecordDecl *>(getPointer()); |
| 126 | } |
| 127 | |
| 128 | const CXXMethodDecl *getFunctionDecl() const { |
| 129 | assert(getKind() == CK_FunctionPointer); |
| 130 | |
| 131 | return reinterpret_cast<CXXMethodDecl *>(getPointer()); |
| 132 | } |
| 133 | |
| 134 | const CXXDestructorDecl *getDestructorDecl() const { |
| 135 | assert((getKind() == CK_CompleteDtorPointer || |
| 136 | getKind() == CK_DeletingDtorPointer) && "Invalid component kind!"); |
| 137 | |
| 138 | return reinterpret_cast<CXXDestructorDecl *>(getPointer()); |
| 139 | } |
| 140 | |
| 141 | const CXXMethodDecl *getUnusedFunctionDecl() const { |
| 142 | assert(getKind() == CK_UnusedFunctionPointer); |
| 143 | |
| 144 | return reinterpret_cast<CXXMethodDecl *>(getPointer()); |
| 145 | } |
| 146 | |
| 147 | private: |
| 148 | VTableComponent(Kind ComponentKind, CharUnits Offset) { |
| 149 | assert((ComponentKind == CK_VCallOffset || |
| 150 | ComponentKind == CK_VBaseOffset || |
| 151 | ComponentKind == CK_OffsetToTop) && "Invalid component kind!"); |
| 152 | assert(Offset.getQuantity() <= ((1LL << 56) - 1) && "Offset is too big!"); |
| 153 | |
| 154 | Value = ((Offset.getQuantity() << 3) | ComponentKind); |
| 155 | } |
| 156 | |
| 157 | VTableComponent(Kind ComponentKind, uintptr_t Ptr) { |
| 158 | assert((ComponentKind == CK_RTTI || |
| 159 | ComponentKind == CK_FunctionPointer || |
| 160 | ComponentKind == CK_CompleteDtorPointer || |
| 161 | ComponentKind == CK_DeletingDtorPointer || |
| 162 | ComponentKind == CK_UnusedFunctionPointer) && |
| 163 | "Invalid component kind!"); |
| 164 | |
| 165 | assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!"); |
| 166 | |
| 167 | Value = Ptr | ComponentKind; |
| 168 | } |
| 169 | |
| 170 | CharUnits getOffset() const { |
| 171 | assert((getKind() == CK_VCallOffset || getKind() == CK_VBaseOffset || |
| 172 | getKind() == CK_OffsetToTop) && "Invalid component kind!"); |
| 173 | |
| 174 | return CharUnits::fromQuantity(Value >> 3); |
| 175 | } |
| 176 | |
| 177 | uintptr_t getPointer() const { |
| 178 | assert((getKind() == CK_RTTI || |
| 179 | getKind() == CK_FunctionPointer || |
| 180 | getKind() == CK_CompleteDtorPointer || |
| 181 | getKind() == CK_DeletingDtorPointer || |
| 182 | getKind() == CK_UnusedFunctionPointer) && |
| 183 | "Invalid component kind!"); |
| 184 | |
| 185 | return static_cast<uintptr_t>(Value & ~7ULL); |
| 186 | } |
| 187 | |
| 188 | explicit VTableComponent(uint64_t Value) |
| 189 | : Value(Value) { } |
| 190 | |
| 191 | /// The kind is stored in the lower 3 bits of the value. For offsets, we |
| 192 | /// make use of the facts that classes can't be larger than 2^55 bytes, |
| 193 | /// so we store the offset in the lower part of the 61 bytes that remain. |
| 194 | /// (The reason that we're not simply using a PointerIntPair here is that we |
| 195 | /// need the offsets to be 64-bit, even when on a 32-bit machine). |
| 196 | int64_t Value; |
| 197 | }; |
| 198 | |
Peter Collingbourne | e09cdf4 | 2011-09-26 01:56:50 +0000 | [diff] [blame] | 199 | class VTableLayout { |
| 200 | public: |
| 201 | typedef std::pair<uint64_t, ThunkInfo> VTableThunkTy; |
| 202 | typedef llvm::SmallVector<ThunkInfo, 1> ThunkInfoVectorTy; |
| 203 | |
| 204 | typedef const VTableComponent *vtable_component_iterator; |
| 205 | typedef const VTableThunkTy *vtable_thunk_iterator; |
| 206 | |
| 207 | typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy; |
| 208 | private: |
| 209 | uint64_t NumVTableComponents; |
| 210 | VTableComponent *VTableComponents; |
| 211 | |
| 212 | /// VTableThunks - Contains thunks needed by vtables. |
| 213 | uint64_t NumVTableThunks; |
| 214 | VTableThunkTy *VTableThunks; |
| 215 | |
| 216 | /// Address points - Address points for all vtables. |
| 217 | AddressPointsMapTy AddressPoints; |
| 218 | |
| 219 | public: |
| 220 | VTableLayout(uint64_t NumVTableComponents, |
| 221 | const VTableComponent *VTableComponents, |
| 222 | uint64_t NumVTableThunks, |
| 223 | const VTableThunkTy *VTableThunks, |
| 224 | const AddressPointsMapTy &AddressPoints); |
| 225 | ~VTableLayout(); |
| 226 | |
| 227 | uint64_t getNumVTableComponents() const { |
| 228 | return NumVTableComponents; |
| 229 | } |
| 230 | |
| 231 | vtable_component_iterator vtable_component_begin() const { |
| 232 | return VTableComponents; |
| 233 | } |
| 234 | |
| 235 | vtable_component_iterator vtable_component_end() const { |
| 236 | return VTableComponents+NumVTableComponents; |
| 237 | } |
| 238 | |
| 239 | uint64_t getNumVTableThunks() const { |
| 240 | return NumVTableThunks; |
| 241 | } |
| 242 | |
| 243 | vtable_thunk_iterator vtable_thunk_begin() const { |
| 244 | return VTableThunks; |
| 245 | } |
| 246 | |
| 247 | vtable_thunk_iterator vtable_thunk_end() const { |
| 248 | return VTableThunks+NumVTableThunks; |
| 249 | } |
| 250 | |
| 251 | uint64_t getAddressPoint(BaseSubobject Base) const { |
| 252 | assert(AddressPoints.count(Base) && |
| 253 | "Did not find address point!"); |
| 254 | |
| 255 | uint64_t AddressPoint = AddressPoints.lookup(Base); |
| 256 | assert(AddressPoint && "Address point must not be zero!"); |
| 257 | |
| 258 | return AddressPoint; |
| 259 | } |
Peter Collingbourne | ab172b5 | 2011-09-26 01:57:04 +0000 | [diff] [blame^] | 260 | |
| 261 | const AddressPointsMapTy &getAddressPoints() const { |
| 262 | return AddressPoints; |
| 263 | } |
Peter Collingbourne | e09cdf4 | 2011-09-26 01:56:50 +0000 | [diff] [blame] | 264 | }; |
| 265 | |
Peter Collingbourne | 1d2b317 | 2011-09-26 01:56:30 +0000 | [diff] [blame] | 266 | class VTableContext { |
| 267 | ASTContext &Context; |
Benjamin Kramer | 39411b9 | 2009-11-26 13:09:03 +0000 | [diff] [blame] | 268 | |
Peter Collingbourne | 84fcc48 | 2011-09-26 01:56:41 +0000 | [diff] [blame] | 269 | public: |
| 270 | typedef SmallVector<std::pair<uint64_t, ThunkInfo>, 1> |
| 271 | VTableThunksTy; |
| 272 | typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy; |
| 273 | |
| 274 | private: |
Anders Carlsson | 046c294 | 2010-04-17 20:15:18 +0000 | [diff] [blame] | 275 | /// MethodVTableIndices - Contains the index (relative to the vtable address |
Anders Carlsson | dbd920c | 2009-10-11 22:13:54 +0000 | [diff] [blame] | 276 | /// point) where the function pointer for a virtual function is stored. |
Anders Carlsson | 046c294 | 2010-04-17 20:15:18 +0000 | [diff] [blame] | 277 | typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy; |
| 278 | MethodVTableIndicesTy MethodVTableIndices; |
Benjamin Kramer | 39411b9 | 2009-11-26 13:09:03 +0000 | [diff] [blame] | 279 | |
Peter Collingbourne | e09cdf4 | 2011-09-26 01:56:50 +0000 | [diff] [blame] | 280 | typedef llvm::DenseMap<const CXXRecordDecl *, const VTableLayout *> |
| 281 | VTableLayoutMapTy; |
| 282 | VTableLayoutMapTy VTableLayouts; |
| 283 | |
Peter Collingbourne | 1d2b317 | 2011-09-26 01:56:30 +0000 | [diff] [blame] | 284 | /// NumVirtualFunctionPointers - Contains the number of virtual function |
| 285 | /// pointers in the vtable for a given record decl. |
| 286 | llvm::DenseMap<const CXXRecordDecl *, uint64_t> NumVirtualFunctionPointers; |
| 287 | |
Anders Carlsson | dbd920c | 2009-10-11 22:13:54 +0000 | [diff] [blame] | 288 | typedef std::pair<const CXXRecordDecl *, |
| 289 | const CXXRecordDecl *> ClassPairTy; |
Benjamin Kramer | 39411b9 | 2009-11-26 13:09:03 +0000 | [diff] [blame] | 290 | |
Anders Carlsson | bba1607 | 2010-03-11 07:15:17 +0000 | [diff] [blame] | 291 | /// VirtualBaseClassOffsetOffsets - Contains the vtable offset (relative to |
Ken Dyck | 1a7f752 | 2011-04-07 01:22:42 +0000 | [diff] [blame] | 292 | /// the address point) in chars where the offsets for virtual bases of a class |
Anders Carlsson | bba1607 | 2010-03-11 07:15:17 +0000 | [diff] [blame] | 293 | /// are stored. |
Ken Dyck | 1a7f752 | 2011-04-07 01:22:42 +0000 | [diff] [blame] | 294 | typedef llvm::DenseMap<ClassPairTy, CharUnits> |
Anders Carlsson | bba1607 | 2010-03-11 07:15:17 +0000 | [diff] [blame] | 295 | VirtualBaseClassOffsetOffsetsMapTy; |
| 296 | VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets; |
Mike Stump | 380dd75 | 2009-11-10 07:44:33 +0000 | [diff] [blame] | 297 | |
Peter Collingbourne | 84fcc48 | 2011-09-26 01:56:41 +0000 | [diff] [blame] | 298 | typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy; |
| 299 | |
| 300 | /// Thunks - Contains all thunks that a given method decl will need. |
| 301 | ThunksMapTy Thunks; |
| 302 | |
Peter Collingbourne | 1d2b317 | 2011-09-26 01:56:30 +0000 | [diff] [blame] | 303 | void ComputeMethodVTableIndices(const CXXRecordDecl *RD); |
| 304 | |
Peter Collingbourne | 84fcc48 | 2011-09-26 01:56:41 +0000 | [diff] [blame] | 305 | /// ComputeVTableRelatedInformation - Compute and store all vtable related |
| 306 | /// information (vtable layout, vbase offset offsets, thunks etc) for the |
| 307 | /// given record decl. |
| 308 | void ComputeVTableRelatedInformation(const CXXRecordDecl *RD); |
| 309 | |
Peter Collingbourne | 1d2b317 | 2011-09-26 01:56:30 +0000 | [diff] [blame] | 310 | public: |
| 311 | VTableContext(ASTContext &Context) : Context(Context) {} |
Peter Collingbourne | e09cdf4 | 2011-09-26 01:56:50 +0000 | [diff] [blame] | 312 | ~VTableContext(); |
Peter Collingbourne | 1d2b317 | 2011-09-26 01:56:30 +0000 | [diff] [blame] | 313 | |
Peter Collingbourne | e09cdf4 | 2011-09-26 01:56:50 +0000 | [diff] [blame] | 314 | const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) { |
Peter Collingbourne | 84fcc48 | 2011-09-26 01:56:41 +0000 | [diff] [blame] | 315 | ComputeVTableRelatedInformation(RD); |
Peter Collingbourne | e09cdf4 | 2011-09-26 01:56:50 +0000 | [diff] [blame] | 316 | assert(VTableLayouts.count(RD) && "No layout for this record decl!"); |
Peter Collingbourne | 84fcc48 | 2011-09-26 01:56:41 +0000 | [diff] [blame] | 317 | |
Peter Collingbourne | e09cdf4 | 2011-09-26 01:56:50 +0000 | [diff] [blame] | 318 | return *VTableLayouts[RD]; |
Peter Collingbourne | 84fcc48 | 2011-09-26 01:56:41 +0000 | [diff] [blame] | 319 | } |
| 320 | |
Peter Collingbourne | e00fe69 | 2011-09-26 01:56:55 +0000 | [diff] [blame] | 321 | VTableLayout * |
| 322 | createConstructionVTableLayout(const CXXRecordDecl *MostDerivedClass, |
| 323 | CharUnits MostDerivedClassOffset, |
| 324 | bool MostDerivedClassIsVirtual, |
| 325 | const CXXRecordDecl *LayoutClass); |
| 326 | |
Peter Collingbourne | 84fcc48 | 2011-09-26 01:56:41 +0000 | [diff] [blame] | 327 | const ThunkInfoVectorTy *getThunkInfo(const CXXMethodDecl *MD) { |
| 328 | ComputeVTableRelatedInformation(MD->getParent()); |
| 329 | |
| 330 | ThunksMapTy::const_iterator I = Thunks.find(MD); |
| 331 | if (I == Thunks.end()) { |
| 332 | // We did not find a thunk for this method. |
| 333 | return 0; |
| 334 | } |
| 335 | |
| 336 | return &I->second; |
| 337 | } |
| 338 | |
Peter Collingbourne | 1d2b317 | 2011-09-26 01:56:30 +0000 | [diff] [blame] | 339 | /// getNumVirtualFunctionPointers - Return the number of virtual function |
| 340 | /// pointers in the vtable for a given record decl. |
| 341 | uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD); |
| 342 | |
| 343 | /// getMethodVTableIndex - Return the index (relative to the vtable address |
| 344 | /// point) where the function pointer for the given virtual function is |
| 345 | /// stored. |
| 346 | uint64_t getMethodVTableIndex(GlobalDecl GD); |
| 347 | |
| 348 | /// getVirtualBaseOffsetOffset - Return the offset in chars (relative to the |
| 349 | /// vtable address point) where the offset of the virtual base that contains |
| 350 | /// the given base is stored, otherwise, if no virtual base contains the given |
| 351 | /// class, return 0. Base must be a virtual base class or an unambigious |
| 352 | /// base. |
| 353 | CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, |
| 354 | const CXXRecordDecl *VBase); |
Peter Collingbourne | 1d2b317 | 2011-09-26 01:56:30 +0000 | [diff] [blame] | 355 | }; |
| 356 | |
| 357 | class CodeGenVTables { |
| 358 | CodeGenModule &CGM; |
| 359 | |
| 360 | VTableContext VTContext; |
| 361 | |
Anders Carlsson | 046c294 | 2010-04-17 20:15:18 +0000 | [diff] [blame] | 362 | /// VTables - All the vtables which have been defined. |
| 363 | llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables; |
Anders Carlsson | d6b07fb | 2009-11-27 20:47:55 +0000 | [diff] [blame] | 364 | |
Anders Carlsson | 2c822f1 | 2010-03-26 03:56:54 +0000 | [diff] [blame] | 365 | /// VTableAddressPointsMapTy - Address points for a single vtable. |
| 366 | typedef llvm::DenseMap<BaseSubobject, uint64_t> VTableAddressPointsMapTy; |
| 367 | |
Peter Collingbourne | 84fcc48 | 2011-09-26 01:56:41 +0000 | [diff] [blame] | 368 | typedef std::pair<const CXXRecordDecl *, BaseSubobject> BaseSubobjectPairTy; |
Anders Carlsson | 3855a07 | 2010-05-03 00:55:11 +0000 | [diff] [blame] | 369 | typedef llvm::DenseMap<BaseSubobjectPairTy, uint64_t> SubVTTIndiciesMapTy; |
Anders Carlsson | e1dcc22 | 2010-03-26 04:23:58 +0000 | [diff] [blame] | 370 | |
| 371 | /// SubVTTIndicies - Contains indices into the various sub-VTTs. |
| 372 | SubVTTIndiciesMapTy SubVTTIndicies; |
| 373 | |
Anders Carlsson | 3855a07 | 2010-05-03 00:55:11 +0000 | [diff] [blame] | 374 | typedef llvm::DenseMap<BaseSubobjectPairTy, uint64_t> |
Anders Carlsson | e1dcc22 | 2010-03-26 04:23:58 +0000 | [diff] [blame] | 375 | SecondaryVirtualPointerIndicesMapTy; |
| 376 | |
| 377 | /// SecondaryVirtualPointerIndices - Contains the secondary virtual pointer |
| 378 | /// indices. |
| 379 | SecondaryVirtualPointerIndicesMapTy SecondaryVirtualPointerIndices; |
Anders Carlsson | c997d42 | 2010-01-02 01:01:18 +0000 | [diff] [blame] | 380 | |
Anders Carlsson | fbf6ed4 | 2010-03-23 16:36:50 +0000 | [diff] [blame] | 381 | /// EmitThunk - Emit a single thunk. |
Anders Carlsson | 14e82fd | 2011-02-06 18:31:40 +0000 | [diff] [blame] | 382 | void EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk, |
| 383 | bool UseAvailableExternallyLinkage); |
| 384 | |
| 385 | /// MaybeEmitThunkAvailableExternally - Try to emit the given thunk with |
| 386 | /// available_externally linkage to allow for inlining of thunks. |
| 387 | /// This will be done iff optimizations are enabled and the member function |
| 388 | /// doesn't contain any incomplete types. |
| 389 | void MaybeEmitThunkAvailableExternally(GlobalDecl GD, const ThunkInfo &Thunk); |
| 390 | |
Anders Carlsson | 0d1407e | 2010-03-25 15:26:28 +0000 | [diff] [blame] | 391 | /// CreateVTableInitializer - Create a vtable initializer for the given record |
| 392 | /// decl. |
| 393 | /// \param Components - The vtable components; this is really an array of |
| 394 | /// VTableComponents. |
| 395 | llvm::Constant *CreateVTableInitializer(const CXXRecordDecl *RD, |
Peter Collingbourne | e09cdf4 | 2011-09-26 01:56:50 +0000 | [diff] [blame] | 396 | const VTableComponent *Components, |
Anders Carlsson | 0d1407e | 2010-03-25 15:26:28 +0000 | [diff] [blame] | 397 | unsigned NumComponents, |
Peter Collingbourne | e09cdf4 | 2011-09-26 01:56:50 +0000 | [diff] [blame] | 398 | const VTableLayout::VTableThunkTy *VTableThunks, |
| 399 | unsigned NumVTableThunks); |
Anders Carlsson | 2c822f1 | 2010-03-26 03:56:54 +0000 | [diff] [blame] | 400 | |
Anders Carlsson | dbd920c | 2009-10-11 22:13:54 +0000 | [diff] [blame] | 401 | public: |
Peter Collingbourne | 1d2b317 | 2011-09-26 01:56:30 +0000 | [diff] [blame] | 402 | CodeGenVTables(CodeGenModule &CGM); |
| 403 | |
| 404 | VTableContext &getVTableContext() { return VTContext; } |
Anders Carlsson | dbd920c | 2009-10-11 22:13:54 +0000 | [diff] [blame] | 405 | |
Argyrios Kyrtzidis | d2c47bd | 2010-10-11 03:25:57 +0000 | [diff] [blame] | 406 | /// \brief True if the VTable of this record must be emitted in the |
| 407 | /// translation unit. |
| 408 | bool ShouldEmitVTableInThisTU(const CXXRecordDecl *RD); |
Rafael Espindola | b8cab18 | 2010-04-19 00:44:22 +0000 | [diff] [blame] | 409 | |
Anders Carlsson | c997d42 | 2010-01-02 01:01:18 +0000 | [diff] [blame] | 410 | /// needsVTTParameter - Return whether the given global decl needs a VTT |
| 411 | /// parameter, which it does if it's a base constructor or destructor with |
| 412 | /// virtual bases. |
| 413 | static bool needsVTTParameter(GlobalDecl GD); |
| 414 | |
| 415 | /// getSubVTTIndex - Return the index of the sub-VTT for the base class of the |
| 416 | /// given record decl. |
Anders Carlsson | c11bb21 | 2010-05-02 23:53:25 +0000 | [diff] [blame] | 417 | uint64_t getSubVTTIndex(const CXXRecordDecl *RD, BaseSubobject Base); |
Anders Carlsson | c997d42 | 2010-01-02 01:01:18 +0000 | [diff] [blame] | 418 | |
Anders Carlsson | e1dcc22 | 2010-03-26 04:23:58 +0000 | [diff] [blame] | 419 | /// getSecondaryVirtualPointerIndex - Return the index in the VTT where the |
| 420 | /// virtual pointer for the given subobject is located. |
| 421 | uint64_t getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD, |
| 422 | BaseSubobject Base); |
| 423 | |
Anders Carlsson | 64c9eca | 2010-03-29 02:08:26 +0000 | [diff] [blame] | 424 | /// getAddressPoint - Get the address point of the given subobject in the |
| 425 | /// class decl. |
| 426 | uint64_t getAddressPoint(BaseSubobject Base, const CXXRecordDecl *RD); |
| 427 | |
Anders Carlsson | 5eea876 | 2010-03-24 05:32:05 +0000 | [diff] [blame] | 428 | /// GetAddrOfVTable - Get the address of the vtable for the given record decl. |
Anders Carlsson | 9dc338a | 2010-03-30 03:35:35 +0000 | [diff] [blame] | 429 | llvm::GlobalVariable *GetAddrOfVTable(const CXXRecordDecl *RD); |
Anders Carlsson | 5c6c1d9 | 2010-03-24 03:57:14 +0000 | [diff] [blame] | 430 | |
Anders Carlsson | a7cde3b | 2010-03-29 03:38:52 +0000 | [diff] [blame] | 431 | /// EmitVTableDefinition - Emit the definition of the given vtable. |
| 432 | void EmitVTableDefinition(llvm::GlobalVariable *VTable, |
| 433 | llvm::GlobalVariable::LinkageTypes Linkage, |
| 434 | const CXXRecordDecl *RD); |
| 435 | |
Anders Carlsson | ff143f8 | 2010-03-25 00:35:49 +0000 | [diff] [blame] | 436 | /// GenerateConstructionVTable - Generate a construction vtable for the given |
| 437 | /// base subobject. |
| 438 | llvm::GlobalVariable * |
| 439 | GenerateConstructionVTable(const CXXRecordDecl *RD, const BaseSubobject &Base, |
| 440 | bool BaseIsVirtual, |
John McCall | bda0d6b | 2011-03-27 09:00:25 +0000 | [diff] [blame] | 441 | llvm::GlobalVariable::LinkageTypes Linkage, |
Anders Carlsson | 2c822f1 | 2010-03-26 03:56:54 +0000 | [diff] [blame] | 442 | VTableAddressPointsMapTy& AddressPoints); |
Anders Carlsson | 1cbce12 | 2011-01-29 19:16:51 +0000 | [diff] [blame] | 443 | |
| 444 | |
| 445 | /// GetAddrOfVTable - Get the address of the VTT for the given record decl. |
| 446 | llvm::GlobalVariable *GetAddrOfVTT(const CXXRecordDecl *RD); |
| 447 | |
| 448 | /// EmitVTTDefinition - Emit the definition of the given vtable. |
| 449 | void EmitVTTDefinition(llvm::GlobalVariable *VTT, |
| 450 | llvm::GlobalVariable::LinkageTypes Linkage, |
| 451 | const CXXRecordDecl *RD); |
Rafael Espindola | bbf58bb | 2010-03-10 02:19:29 +0000 | [diff] [blame] | 452 | |
Douglas Gregor | 6fb745b | 2010-05-13 16:44:06 +0000 | [diff] [blame] | 453 | /// EmitThunks - Emit the associated thunks for the given global decl. |
| 454 | void EmitThunks(GlobalDecl GD); |
| 455 | |
Anders Carlsson | 7986ad5 | 2010-03-23 18:18:41 +0000 | [diff] [blame] | 456 | /// GenerateClassData - Generate all the class data required to be generated |
Rafael Espindola | bbf58bb | 2010-03-10 02:19:29 +0000 | [diff] [blame] | 457 | /// upon definition of a KeyFunction. This includes the vtable, the |
| 458 | /// rtti data structure and the VTT. |
| 459 | /// |
| 460 | /// \param Linkage - The desired linkage of the vtable, the RTTI and the VTT. |
| 461 | void GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage, |
| 462 | const CXXRecordDecl *RD); |
Anders Carlsson | dbd920c | 2009-10-11 22:13:54 +0000 | [diff] [blame] | 463 | }; |
Benjamin Kramer | 39411b9 | 2009-11-26 13:09:03 +0000 | [diff] [blame] | 464 | |
Anders Carlsson | 1bb6099 | 2010-01-14 02:29:07 +0000 | [diff] [blame] | 465 | } // end namespace CodeGen |
| 466 | } // end namespace clang |
Anders Carlsson | dbd920c | 2009-10-11 22:13:54 +0000 | [diff] [blame] | 467 | #endif |