Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 14 | pmbaty | 1 | //===- RecordLayout.h - Layout information for a struct/union ---*- C++ -*-===// | 
| 2 | // | ||
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| 4 | // See https://llvm.org/LICENSE.txt for license information. | ||
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| 6 | // | ||
| 7 | //===----------------------------------------------------------------------===// | ||
| 8 | // | ||
| 9 | //  This file defines the RecordLayout interface. | ||
| 10 | // | ||
| 11 | //===----------------------------------------------------------------------===// | ||
| 12 | |||
| 13 | #ifndef LLVM_CLANG_AST_RECORDLAYOUT_H | ||
| 14 | #define LLVM_CLANG_AST_RECORDLAYOUT_H | ||
| 15 | |||
| 16 | #include "clang/AST/ASTVector.h" | ||
| 17 | #include "clang/AST/CharUnits.h" | ||
| 18 | #include "clang/AST/DeclCXX.h" | ||
| 19 | #include "clang/Basic/LLVM.h" | ||
| 20 | #include "llvm/ADT/ArrayRef.h" | ||
| 21 | #include "llvm/ADT/DenseMap.h" | ||
| 22 | #include "llvm/ADT/PointerIntPair.h" | ||
| 23 | #include <cassert> | ||
| 24 | #include <cstdint> | ||
| 25 | |||
| 26 | namespace clang { | ||
| 27 | |||
| 28 | class ASTContext; | ||
| 29 | class CXXRecordDecl; | ||
| 30 | |||
| 31 | /// ASTRecordLayout - | ||
| 32 | /// This class contains layout information for one RecordDecl, | ||
| 33 | /// which is a struct/union/class.  The decl represented must be a definition, | ||
| 34 | /// not a forward declaration. | ||
| 35 | /// This class is also used to contain layout information for one | ||
| 36 | /// ObjCInterfaceDecl. FIXME - Find appropriate name. | ||
| 37 | /// These objects are managed by ASTContext. | ||
| 38 | class ASTRecordLayout { | ||
| 39 | public: | ||
| 40 | struct VBaseInfo { | ||
| 41 |     /// The offset to this virtual base in the complete-object layout | ||
| 42 |     /// of this class. | ||
| 43 |     CharUnits VBaseOffset; | ||
| 44 | |||
| 45 | private: | ||
| 46 |     /// Whether this virtual base requires a vtordisp field in the | ||
| 47 |     /// Microsoft ABI.  These fields are required for certain operations | ||
| 48 |     /// in constructors and destructors. | ||
| 49 | bool HasVtorDisp = false; | ||
| 50 | |||
| 51 | public: | ||
| 52 | VBaseInfo() = default; | ||
| 53 | VBaseInfo(CharUnits VBaseOffset, bool hasVtorDisp) | ||
| 54 | : VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {} | ||
| 55 | |||
| 56 | bool hasVtorDisp() const { return HasVtorDisp; } | ||
| 57 | }; | ||
| 58 | |||
| 59 | using VBaseOffsetsMapTy = llvm::DenseMap<const CXXRecordDecl *, VBaseInfo>; | ||
| 60 | |||
| 61 | private: | ||
| 62 | friend class ASTContext; | ||
| 63 | |||
| 64 |   /// Size - Size of record in characters. | ||
| 65 |   CharUnits Size; | ||
| 66 | |||
| 67 |   /// DataSize - Size of record in characters without tail padding. | ||
| 68 |   CharUnits DataSize; | ||
| 69 | |||
| 70 |   // Alignment - Alignment of record in characters. | ||
| 71 |   CharUnits Alignment; | ||
| 72 | |||
| 73 |   // PreferredAlignment - Preferred alignment of record in characters. This | ||
| 74 |   // can be different than Alignment in cases where it is beneficial for | ||
| 75 |   // performance or backwards compatibility preserving (e.g. AIX-ABI). | ||
| 76 |   CharUnits PreferredAlignment; | ||
| 77 | |||
| 78 |   // UnadjustedAlignment - Maximum of the alignments of the record members in | ||
| 79 |   // characters. | ||
| 80 |   CharUnits UnadjustedAlignment; | ||
| 81 | |||
| 82 |   /// RequiredAlignment - The required alignment of the object.  In the MS-ABI | ||
| 83 |   /// the __declspec(align()) trumps #pramga pack and must always be obeyed. | ||
| 84 |   CharUnits RequiredAlignment; | ||
| 85 | |||
| 86 |   /// FieldOffsets - Array of field offsets in bits. | ||
| 87 | ASTVector<uint64_t> FieldOffsets; | ||
| 88 | |||
| 89 |   /// CXXRecordLayoutInfo - Contains C++ specific layout information. | ||
| 90 | struct CXXRecordLayoutInfo { | ||
| 91 |     /// NonVirtualSize - The non-virtual size (in chars) of an object, which is | ||
| 92 |     /// the size of the object without virtual bases. | ||
| 93 |     CharUnits NonVirtualSize; | ||
| 94 | |||
| 95 |     /// NonVirtualAlignment - The non-virtual alignment (in chars) of an object, | ||
| 96 |     /// which is the alignment of the object without virtual bases. | ||
| 97 |     CharUnits NonVirtualAlignment; | ||
| 98 | |||
| 99 |     /// PreferredNVAlignment - The preferred non-virtual alignment (in chars) of | ||
| 100 |     /// an object, which is the preferred alignment of the object without | ||
| 101 |     /// virtual bases. | ||
| 102 |     CharUnits PreferredNVAlignment; | ||
| 103 | |||
| 104 |     /// SizeOfLargestEmptySubobject - The size of the largest empty subobject | ||
| 105 |     /// (either a base or a member). Will be zero if the class doesn't contain | ||
| 106 |     /// any empty subobjects. | ||
| 107 |     CharUnits SizeOfLargestEmptySubobject; | ||
| 108 | |||
| 109 |     /// VBPtrOffset - Virtual base table offset (Microsoft-only). | ||
| 110 |     CharUnits VBPtrOffset; | ||
| 111 | |||
| 112 |     /// HasOwnVFPtr - Does this class provide a virtual function table | ||
| 113 |     /// (vtable in Itanium, vftbl in Microsoft) that is independent from | ||
| 114 |     /// its base classes? | ||
| 115 | bool HasOwnVFPtr : 1; | ||
| 116 | |||
| 117 |     /// HasVFPtr - Does this class have a vftable that could be extended by | ||
| 118 |     /// a derived class.  The class may have inherited this pointer from | ||
| 119 |     /// a primary base class. | ||
| 120 | bool HasExtendableVFPtr : 1; | ||
| 121 | |||
| 122 |     /// EndsWithZeroSizedObject - True if this class contains a zero sized | ||
| 123 |     /// member or base or a base with a zero sized member or base. | ||
| 124 |     /// Only used for MS-ABI. | ||
| 125 | bool EndsWithZeroSizedObject : 1; | ||
| 126 | |||
| 127 |     /// True if this class is zero sized or first base is zero sized or | ||
| 128 |     /// has this property.  Only used for MS-ABI. | ||
| 129 | bool LeadsWithZeroSizedBase : 1; | ||
| 130 | |||
| 131 |     /// PrimaryBase - The primary base info for this record. | ||
| 132 | llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase; | ||
| 133 | |||
| 134 |     /// BaseSharingVBPtr - The base we share vbptr with. | ||
| 135 | const CXXRecordDecl *BaseSharingVBPtr; | ||
| 136 | |||
| 137 |     /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) | ||
| 138 | using BaseOffsetsMapTy = llvm::DenseMap<const CXXRecordDecl *, CharUnits>; | ||
| 139 | |||
| 140 |     /// BaseOffsets - Contains a map from base classes to their offset. | ||
| 141 |     BaseOffsetsMapTy BaseOffsets; | ||
| 142 | |||
| 143 |     /// VBaseOffsets - Contains a map from vbase classes to their offset. | ||
| 144 |     VBaseOffsetsMapTy VBaseOffsets; | ||
| 145 | }; | ||
| 146 | |||
| 147 |   /// CXXInfo - If the record layout is for a C++ record, this will have | ||
| 148 |   /// C++ specific information about the record. | ||
| 149 | CXXRecordLayoutInfo *CXXInfo = nullptr; | ||
| 150 | |||
| 151 | ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, | ||
| 152 | CharUnits preferredAlignment, CharUnits unadjustedAlignment, | ||
| 153 | CharUnits requiredAlignment, CharUnits datasize, | ||
| 154 | ArrayRef<uint64_t> fieldoffsets); | ||
| 155 | |||
| 156 | using BaseOffsetsMapTy = CXXRecordLayoutInfo::BaseOffsetsMapTy; | ||
| 157 | |||
| 158 |   // Constructor for C++ records. | ||
| 159 | ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, | ||
| 160 | CharUnits preferredAlignment, CharUnits unadjustedAlignment, | ||
| 161 |                   CharUnits requiredAlignment, bool hasOwnVFPtr, | ||
| 162 |                   bool hasExtendableVFPtr, CharUnits vbptroffset, | ||
| 163 | CharUnits datasize, ArrayRef<uint64_t> fieldoffsets, | ||
| 164 | CharUnits nonvirtualsize, CharUnits nonvirtualalignment, | ||
| 165 | CharUnits preferrednvalignment, | ||
| 166 | CharUnits SizeOfLargestEmptySubobject, | ||
| 167 | const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual, | ||
| 168 | const CXXRecordDecl *BaseSharingVBPtr, | ||
| 169 | bool EndsWithZeroSizedObject, bool LeadsWithZeroSizedBase, | ||
| 170 | const BaseOffsetsMapTy &BaseOffsets, | ||
| 171 | const VBaseOffsetsMapTy &VBaseOffsets); | ||
| 172 | |||
| 173 | ~ASTRecordLayout() = default; | ||
| 174 | |||
| 175 | void Destroy(ASTContext &Ctx); | ||
| 176 | |||
| 177 | public: | ||
| 178 | ASTRecordLayout(const ASTRecordLayout &) = delete; | ||
| 179 | ASTRecordLayout &operator=(const ASTRecordLayout &) = delete; | ||
| 180 | |||
| 181 |   /// getAlignment - Get the record alignment in characters. | ||
| 182 | CharUnits getAlignment() const { return Alignment; } | ||
| 183 | |||
| 184 |   /// getPreferredFieldAlignment - Get the record preferred alignment in | ||
| 185 |   /// characters. | ||
| 186 | CharUnits getPreferredAlignment() const { return PreferredAlignment; } | ||
| 187 | |||
| 188 |   /// getUnadjustedAlignment - Get the record alignment in characters, before | ||
| 189 |   /// alignment adjustement. | ||
| 190 | CharUnits getUnadjustedAlignment() const { return UnadjustedAlignment; } | ||
| 191 | |||
| 192 |   /// getSize - Get the record size in characters. | ||
| 193 | CharUnits getSize() const { return Size; } | ||
| 194 | |||
| 195 |   /// getFieldCount - Get the number of fields in the layout. | ||
| 196 | unsigned getFieldCount() const { return FieldOffsets.size(); } | ||
| 197 | |||
| 198 |   /// getFieldOffset - Get the offset of the given field index, in | ||
| 199 |   /// bits. | ||
| 200 | uint64_t getFieldOffset(unsigned FieldNo) const { | ||
| 201 | return FieldOffsets[FieldNo]; | ||
| 202 |   } | ||
| 203 | |||
| 204 |   /// getDataSize() - Get the record data size, which is the record size | ||
| 205 |   /// without tail padding, in characters. | ||
| 206 | CharUnits getDataSize() const { return DataSize; } | ||
| 207 | |||
| 208 |   /// getNonVirtualSize - Get the non-virtual size (in chars) of an object, | ||
| 209 |   /// which is the size of the object without virtual bases. | ||
| 210 | CharUnits getNonVirtualSize() const { | ||
| 211 | assert(CXXInfo && "Record layout does not have C++ specific info!"); | ||
| 212 | |||
| 213 | return CXXInfo->NonVirtualSize; | ||
| 214 |   } | ||
| 215 | |||
| 216 |   /// getNonVirtualAlignment - Get the non-virtual alignment (in chars) of an | ||
| 217 |   /// object, which is the alignment of the object without virtual bases. | ||
| 218 | CharUnits getNonVirtualAlignment() const { | ||
| 219 | assert(CXXInfo && "Record layout does not have C++ specific info!"); | ||
| 220 | |||
| 221 | return CXXInfo->NonVirtualAlignment; | ||
| 222 |   } | ||
| 223 | |||
| 224 |   /// getPreferredNVAlignment - Get the preferred non-virtual alignment (in | ||
| 225 |   /// chars) of an object, which is the preferred alignment of the object | ||
| 226 |   /// without virtual bases. | ||
| 227 | CharUnits getPreferredNVAlignment() const { | ||
| 228 | assert(CXXInfo && "Record layout does not have C++ specific info!"); | ||
| 229 | |||
| 230 | return CXXInfo->PreferredNVAlignment; | ||
| 231 |   } | ||
| 232 | |||
| 233 |   /// getPrimaryBase - Get the primary base for this record. | ||
| 234 | const CXXRecordDecl *getPrimaryBase() const { | ||
| 235 | assert(CXXInfo && "Record layout does not have C++ specific info!"); | ||
| 236 | |||
| 237 | return CXXInfo->PrimaryBase.getPointer(); | ||
| 238 |   } | ||
| 239 | |||
| 240 |   /// isPrimaryBaseVirtual - Get whether the primary base for this record | ||
| 241 |   /// is virtual or not. | ||
| 242 | bool isPrimaryBaseVirtual() const { | ||
| 243 | assert(CXXInfo && "Record layout does not have C++ specific info!"); | ||
| 244 | |||
| 245 | return CXXInfo->PrimaryBase.getInt(); | ||
| 246 |   } | ||
| 247 | |||
| 248 |   /// getBaseClassOffset - Get the offset, in chars, for the given base class. | ||
| 249 | CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const { | ||
| 250 | assert(CXXInfo && "Record layout does not have C++ specific info!"); | ||
| 251 | |||
| 252 | Base = Base->getDefinition(); | ||
| 253 | assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!"); | ||
| 254 | |||
| 255 | return CXXInfo->BaseOffsets[Base]; | ||
| 256 |   } | ||
| 257 | |||
| 258 |   /// getVBaseClassOffset - Get the offset, in chars, for the given base class. | ||
| 259 | CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const { | ||
| 260 | assert(CXXInfo && "Record layout does not have C++ specific info!"); | ||
| 261 | |||
| 262 | VBase = VBase->getDefinition(); | ||
| 263 | assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!"); | ||
| 264 | |||
| 265 | return CXXInfo->VBaseOffsets[VBase].VBaseOffset; | ||
| 266 |   } | ||
| 267 | |||
| 268 | CharUnits getSizeOfLargestEmptySubobject() const { | ||
| 269 | assert(CXXInfo && "Record layout does not have C++ specific info!"); | ||
| 270 | return CXXInfo->SizeOfLargestEmptySubobject; | ||
| 271 |   } | ||
| 272 | |||
| 273 |   /// hasOwnVFPtr - Does this class provide its own virtual-function | ||
| 274 |   /// table pointer, rather than inheriting one from a primary base | ||
| 275 |   /// class?  If so, it is at offset zero. | ||
| 276 |   /// | ||
| 277 |   /// This implies that the ABI has no primary base class, meaning | ||
| 278 |   /// that it has no base classes that are suitable under the conditions | ||
| 279 |   /// of the ABI. | ||
| 280 | bool hasOwnVFPtr() const { | ||
| 281 | assert(CXXInfo && "Record layout does not have C++ specific info!"); | ||
| 282 | return CXXInfo->HasOwnVFPtr; | ||
| 283 |   } | ||
| 284 | |||
| 285 |   /// hasVFPtr - Does this class have a virtual function table pointer | ||
| 286 |   /// that can be extended by a derived class?  This is synonymous with | ||
| 287 |   /// this class having a VFPtr at offset zero. | ||
| 288 | bool hasExtendableVFPtr() const { | ||
| 289 | assert(CXXInfo && "Record layout does not have C++ specific info!"); | ||
| 290 | return CXXInfo->HasExtendableVFPtr; | ||
| 291 |   } | ||
| 292 | |||
| 293 |   /// hasOwnVBPtr - Does this class provide its own virtual-base | ||
| 294 |   /// table pointer, rather than inheriting one from a primary base | ||
| 295 |   /// class? | ||
| 296 |   /// | ||
| 297 |   /// This implies that the ABI has no primary base class, meaning | ||
| 298 |   /// that it has no base classes that are suitable under the conditions | ||
| 299 |   /// of the ABI. | ||
| 300 | bool hasOwnVBPtr() const { | ||
| 301 | assert(CXXInfo && "Record layout does not have C++ specific info!"); | ||
| 302 | return hasVBPtr() && !CXXInfo->BaseSharingVBPtr; | ||
| 303 |   } | ||
| 304 | |||
| 305 |   /// hasVBPtr - Does this class have a virtual function table pointer. | ||
| 306 | bool hasVBPtr() const { | ||
| 307 | assert(CXXInfo && "Record layout does not have C++ specific info!"); | ||
| 308 | return !CXXInfo->VBPtrOffset.isNegative(); | ||
| 309 |   } | ||
| 310 | |||
| 311 | CharUnits getRequiredAlignment() const { return RequiredAlignment; } | ||
| 312 | |||
| 313 | bool endsWithZeroSizedObject() const { | ||
| 314 | return CXXInfo && CXXInfo->EndsWithZeroSizedObject; | ||
| 315 |   } | ||
| 316 | |||
| 317 | bool leadsWithZeroSizedBase() const { | ||
| 318 | assert(CXXInfo && "Record layout does not have C++ specific info!"); | ||
| 319 | return CXXInfo->LeadsWithZeroSizedBase; | ||
| 320 |   } | ||
| 321 | |||
| 322 |   /// getVBPtrOffset - Get the offset for virtual base table pointer. | ||
| 323 |   /// This is only meaningful with the Microsoft ABI. | ||
| 324 | CharUnits getVBPtrOffset() const { | ||
| 325 | assert(CXXInfo && "Record layout does not have C++ specific info!"); | ||
| 326 | return CXXInfo->VBPtrOffset; | ||
| 327 |   } | ||
| 328 | |||
| 329 | const CXXRecordDecl *getBaseSharingVBPtr() const { | ||
| 330 | assert(CXXInfo && "Record layout does not have C++ specific info!"); | ||
| 331 | return CXXInfo->BaseSharingVBPtr; | ||
| 332 |   } | ||
| 333 | |||
| 334 | const VBaseOffsetsMapTy &getVBaseOffsetsMap() const { | ||
| 335 | assert(CXXInfo && "Record layout does not have C++ specific info!"); | ||
| 336 | return CXXInfo->VBaseOffsets; | ||
| 337 |   } | ||
| 338 | }; | ||
| 339 | |||
| 340 | } // namespace clang | ||
| 341 | |||
| 342 | #endif // LLVM_CLANG_AST_RECORDLAYOUT_H |