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