1193326Sed//===--- RecordLayout.h - Layout information for a struct/union -*- C++ -*-===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10193326Sed// This file defines the RecordLayout interface. 11193326Sed// 12193326Sed//===----------------------------------------------------------------------===// 13193326Sed 14193326Sed#ifndef LLVM_CLANG_AST_LAYOUTINFO_H 15193326Sed#define LLVM_CLANG_AST_LAYOUTINFO_H 16193326Sed 17218893Sdim#include "clang/AST/CharUnits.h" 18199482Srdivacky#include "clang/AST/DeclCXX.h" 19239462Sdim#include "llvm/ADT/DenseMap.h" 20193326Sed 21193326Sednamespace clang { 22193326Sed class ASTContext; 23198092Srdivacky class FieldDecl; 24193326Sed class RecordDecl; 25198092Srdivacky class CXXRecordDecl; 26193326Sed 27198092Srdivacky/// ASTRecordLayout - 28193326Sed/// This class contains layout information for one RecordDecl, 29193326Sed/// which is a struct/union/class. The decl represented must be a definition, 30198092Srdivacky/// not a forward declaration. 31198092Srdivacky/// This class is also used to contain layout information for one 32193326Sed/// ObjCInterfaceDecl. FIXME - Find appropriate name. 33193326Sed/// These objects are managed by ASTContext. 34193326Sedclass ASTRecordLayout { 35239462Sdimpublic: 36239462Sdim struct VBaseInfo { 37239462Sdim /// The offset to this virtual base in the complete-object layout 38239462Sdim /// of this class. 39239462Sdim CharUnits VBaseOffset; 40239462Sdim 41239462Sdim private: 42239462Sdim /// Whether this virtual base requires a vtordisp field in the 43239462Sdim /// Microsoft ABI. These fields are required for certain operations 44239462Sdim /// in constructors and destructors. 45239462Sdim bool HasVtorDisp; 46239462Sdim 47239462Sdim public: 48239462Sdim bool hasVtorDisp() const { return HasVtorDisp; } 49239462Sdim 50239462Sdim VBaseInfo() : HasVtorDisp(false) {} 51239462Sdim 52239462Sdim VBaseInfo(CharUnits VBaseOffset, bool hasVtorDisp) : 53239462Sdim VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {} 54239462Sdim }; 55239462Sdim 56239462Sdim typedef llvm::DenseMap<const CXXRecordDecl *, VBaseInfo> 57239462Sdim VBaseOffsetsMapTy; 58239462Sdim 59239462Sdimprivate: 60218893Sdim /// Size - Size of record in characters. 61218893Sdim CharUnits Size; 62198092Srdivacky 63218893Sdim /// DataSize - Size of record in characters without tail padding. 64218893Sdim CharUnits DataSize; 65198092Srdivacky 66239462Sdim // Alignment - Alignment of record in characters. 67239462Sdim CharUnits Alignment; 68239462Sdim 69198092Srdivacky /// FieldOffsets - Array of field offsets in bits. 70193326Sed uint64_t *FieldOffsets; 71198092Srdivacky 72198092Srdivacky // FieldCount - Number of fields. 73198092Srdivacky unsigned FieldCount; 74198092Srdivacky 75199990Srdivacky /// CXXRecordLayoutInfo - Contains C++ specific layout information. 76198092Srdivacky struct CXXRecordLayoutInfo { 77218893Sdim /// NonVirtualSize - The non-virtual size (in chars) of an object, which is 78198092Srdivacky /// the size of the object without virtual bases. 79218893Sdim CharUnits NonVirtualSize; 80198092Srdivacky 81218893Sdim /// NonVirtualAlign - The non-virtual alignment (in chars) of an object, 82198092Srdivacky /// which is the alignment of the object without virtual bases. 83218893Sdim CharUnits NonVirtualAlign; 84198092Srdivacky 85208600Srdivacky /// SizeOfLargestEmptySubobject - The size of the largest empty subobject 86208600Srdivacky /// (either a base or a member). Will be zero if the class doesn't contain 87208600Srdivacky /// any empty subobjects. 88218893Sdim CharUnits SizeOfLargestEmptySubobject; 89234353Sdim 90234353Sdim /// VBPtrOffset - Virtual base table offset (Microsoft-only). 91226633Sdim CharUnits VBPtrOffset; 92239462Sdim 93239462Sdim /// HasOwnVFPtr - Does this class provide a virtual function table 94239462Sdim /// (vtable in Itanium, vftbl in Microsoft) that is independent from 95239462Sdim /// its base classes? 96263508Sdim bool HasOwnVFPtr : 1; 97263508Sdim 98263508Sdim /// HasVFPtr - Does this class have a vftable that could be extended by 99263508Sdim /// a derived class. The class may have inherited this pointer from 100263508Sdim /// a primary base class. 101263508Sdim bool HasExtendableVFPtr : 1; 102263508Sdim 103263508Sdim /// AlignAfterVBases - Force appropriate alignment after virtual bases are 104263508Sdim /// laid out in MS-C++-ABI. 105263508Sdim bool AlignAfterVBases : 1; 106226633Sdim 107199990Srdivacky /// PrimaryBase - The primary base info for this record. 108218893Sdim llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase; 109263508Sdim 110263508Sdim /// BaseSharingVBPtr - The base we share vbptr with. 111263508Sdim const CXXRecordDecl *BaseSharingVBPtr; 112199990Srdivacky 113205219Srdivacky /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) 114218893Sdim typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy; 115205219Srdivacky 116198092Srdivacky /// BaseOffsets - Contains a map from base classes to their offset. 117205219Srdivacky BaseOffsetsMapTy BaseOffsets; 118198092Srdivacky 119198092Srdivacky /// VBaseOffsets - Contains a map from vbase classes to their offset. 120239462Sdim VBaseOffsetsMapTy VBaseOffsets; 121198092Srdivacky }; 122198092Srdivacky 123198092Srdivacky /// CXXInfo - If the record layout is for a C++ record, this will have 124198092Srdivacky /// C++ specific information about the record. 125198092Srdivacky CXXRecordLayoutInfo *CXXInfo; 126198092Srdivacky 127193326Sed friend class ASTContext; 128193326Sed 129218893Sdim ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, 130218893Sdim CharUnits datasize, const uint64_t *fieldoffsets, 131204962Srdivacky unsigned fieldcount); 132193326Sed 133198092Srdivacky // Constructor for C++ records. 134205219Srdivacky typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy; 135218893Sdim ASTRecordLayout(const ASTContext &Ctx, 136234353Sdim CharUnits size, CharUnits alignment, 137263508Sdim bool hasOwnVFPtr, bool hasExtendableVFPtr, 138263508Sdim CharUnits vbptroffset, 139226633Sdim CharUnits datasize, 140198092Srdivacky const uint64_t *fieldoffsets, unsigned fieldcount, 141218893Sdim CharUnits nonvirtualsize, CharUnits nonvirtualalign, 142218893Sdim CharUnits SizeOfLargestEmptySubobject, 143208600Srdivacky const CXXRecordDecl *PrimaryBase, 144218893Sdim bool IsPrimaryBaseVirtual, 145263508Sdim const CXXRecordDecl *BaseSharingVBPtr, 146263508Sdim bool ForceAlign, 147205219Srdivacky const BaseOffsetsMapTy& BaseOffsets, 148239462Sdim const VBaseOffsetsMapTy& VBaseOffsets); 149193326Sed 150204962Srdivacky ~ASTRecordLayout() {} 151193326Sed 152204962Srdivacky void Destroy(ASTContext &Ctx); 153218893Sdim 154243830Sdim ASTRecordLayout(const ASTRecordLayout &) LLVM_DELETED_FUNCTION; 155243830Sdim void operator=(const ASTRecordLayout &) LLVM_DELETED_FUNCTION; 156193326Sedpublic: 157198092Srdivacky 158218893Sdim /// getAlignment - Get the record alignment in characters. 159218893Sdim CharUnits getAlignment() const { return Alignment; } 160193326Sed 161218893Sdim /// getSize - Get the record size in characters. 162218893Sdim CharUnits getSize() const { return Size; } 163198092Srdivacky 164193326Sed /// getFieldCount - Get the number of fields in the layout. 165193326Sed unsigned getFieldCount() const { return FieldCount; } 166198092Srdivacky 167193326Sed /// getFieldOffset - Get the offset of the given field index, in 168193326Sed /// bits. 169193326Sed uint64_t getFieldOffset(unsigned FieldNo) const { 170193326Sed assert (FieldNo < FieldCount && "Invalid Field No"); 171193326Sed return FieldOffsets[FieldNo]; 172193326Sed } 173198092Srdivacky 174198092Srdivacky /// getDataSize() - Get the record data size, which is the record size 175218893Sdim /// without tail padding, in characters. 176218893Sdim CharUnits getDataSize() const { 177198092Srdivacky return DataSize; 178193326Sed } 179198092Srdivacky 180218893Sdim /// getNonVirtualSize - Get the non-virtual size (in chars) of an object, 181198092Srdivacky /// which is the size of the object without virtual bases. 182218893Sdim CharUnits getNonVirtualSize() const { 183198092Srdivacky assert(CXXInfo && "Record layout does not have C++ specific info!"); 184198092Srdivacky 185198092Srdivacky return CXXInfo->NonVirtualSize; 186198092Srdivacky } 187198092Srdivacky 188218893Sdim /// getNonVirtualSize - Get the non-virtual alignment (in chars) of an object, 189198092Srdivacky /// which is the alignment of the object without virtual bases. 190218893Sdim CharUnits getNonVirtualAlign() const { 191198092Srdivacky assert(CXXInfo && "Record layout does not have C++ specific info!"); 192198092Srdivacky 193198092Srdivacky return CXXInfo->NonVirtualAlign; 194198092Srdivacky } 195198092Srdivacky 196218893Sdim /// getPrimaryBase - Get the primary base for this record. 197218893Sdim const CXXRecordDecl *getPrimaryBase() const { 198198092Srdivacky assert(CXXInfo && "Record layout does not have C++ specific info!"); 199198092Srdivacky 200218893Sdim return CXXInfo->PrimaryBase.getPointer(); 201198092Srdivacky } 202198092Srdivacky 203218893Sdim /// isPrimaryBaseVirtual - Get whether the primary base for this record 204218893Sdim /// is virtual or not. 205218893Sdim bool isPrimaryBaseVirtual() const { 206218893Sdim assert(CXXInfo && "Record layout does not have C++ specific info!"); 207198092Srdivacky 208218893Sdim return CXXInfo->PrimaryBase.getInt(); 209199990Srdivacky } 210199990Srdivacky 211218893Sdim /// getBaseClassOffset - Get the offset, in chars, for the given base class. 212218893Sdim CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const { 213198092Srdivacky assert(CXXInfo && "Record layout does not have C++ specific info!"); 214198092Srdivacky assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!"); 215198092Srdivacky 216198092Srdivacky return CXXInfo->BaseOffsets[Base]; 217198092Srdivacky } 218198092Srdivacky 219218893Sdim /// getVBaseClassOffset - Get the offset, in chars, for the given base class. 220218893Sdim CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const { 221198092Srdivacky assert(CXXInfo && "Record layout does not have C++ specific info!"); 222198092Srdivacky assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!"); 223198092Srdivacky 224239462Sdim return CXXInfo->VBaseOffsets[VBase].VBaseOffset; 225198092Srdivacky } 226218893Sdim 227218893Sdim CharUnits getSizeOfLargestEmptySubobject() const { 228199990Srdivacky assert(CXXInfo && "Record layout does not have C++ specific info!"); 229218893Sdim return CXXInfo->SizeOfLargestEmptySubobject; 230199990Srdivacky } 231226633Sdim 232239462Sdim /// hasOwnVFPtr - Does this class provide its own virtual-function 233239462Sdim /// table pointer, rather than inheriting one from a primary base 234239462Sdim /// class? If so, it is at offset zero. 235239462Sdim /// 236239462Sdim /// This implies that the ABI has no primary base class, meaning 237239462Sdim /// that it has no base classes that are suitable under the conditions 238239462Sdim /// of the ABI. 239239462Sdim bool hasOwnVFPtr() const { 240234353Sdim assert(CXXInfo && "Record layout does not have C++ specific info!"); 241239462Sdim return CXXInfo->HasOwnVFPtr; 242234353Sdim } 243234353Sdim 244263508Sdim /// hasVFPtr - Does this class have a virtual function table pointer 245263508Sdim /// that can be extended by a derived class? This is synonymous with 246263508Sdim /// this class having a VFPtr at offset zero. 247263508Sdim bool hasExtendableVFPtr() const { 248263508Sdim assert(CXXInfo && "Record layout does not have C++ specific info!"); 249263508Sdim return CXXInfo->HasExtendableVFPtr; 250263508Sdim } 251263508Sdim 252263508Sdim /// hasOwnVBPtr - Does this class provide its own virtual-base 253263508Sdim /// table pointer, rather than inheriting one from a primary base 254263508Sdim /// class? 255263508Sdim /// 256263508Sdim /// This implies that the ABI has no primary base class, meaning 257263508Sdim /// that it has no base classes that are suitable under the conditions 258263508Sdim /// of the ABI. 259263508Sdim bool hasOwnVBPtr() const { 260263508Sdim assert(CXXInfo && "Record layout does not have C++ specific info!"); 261263508Sdim return hasVBPtr() && !CXXInfo->BaseSharingVBPtr; 262263508Sdim } 263263508Sdim 264263508Sdim /// hasVBPtr - Does this class have a virtual function table pointer. 265263508Sdim bool hasVBPtr() const { 266263508Sdim assert(CXXInfo && "Record layout does not have C++ specific info!"); 267263508Sdim return !CXXInfo->VBPtrOffset.isNegative(); 268263508Sdim } 269263508Sdim 270263508Sdim bool getAlignAfterVBases() const { 271263508Sdim assert(CXXInfo && "Record layout does not have C++ specific info!"); 272263508Sdim return CXXInfo->AlignAfterVBases; 273263508Sdim } 274263508Sdim 275234353Sdim /// getVBPtrOffset - Get the offset for virtual base table pointer. 276234353Sdim /// This is only meaningful with the Microsoft ABI. 277226633Sdim CharUnits getVBPtrOffset() const { 278234353Sdim assert(CXXInfo && "Record layout does not have C++ specific info!"); 279226633Sdim return CXXInfo->VBPtrOffset; 280226633Sdim } 281239462Sdim 282263508Sdim const CXXRecordDecl *getBaseSharingVBPtr() const { 283263508Sdim assert(CXXInfo && "Record layout does not have C++ specific info!"); 284263508Sdim return CXXInfo->BaseSharingVBPtr; 285263508Sdim } 286263508Sdim 287239462Sdim const VBaseOffsetsMapTy &getVBaseOffsetsMap() const { 288239462Sdim assert(CXXInfo && "Record layout does not have C++ specific info!"); 289239462Sdim return CXXInfo->VBaseOffsets; 290239462Sdim } 291193326Sed}; 292193326Sed 293193326Sed} // end namespace clang 294193326Sed 295193326Sed#endif 296