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