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_LAYOUTINFO_H 15 #define LLVM_CLANG_AST_LAYOUTINFO_H 16 17 #include "llvm/Support/DataTypes.h" 18 #include "llvm/ADT/DenseMap.h" 19 #include "clang/AST/CharUnits.h" 20 #include "clang/AST/DeclCXX.h" 21 22 namespace clang { 23 class ASTContext; 24 class FieldDecl; 25 class RecordDecl; 26 class CXXRecordDecl; 27 28 /// ASTRecordLayout - 29 /// This class contains layout information for one RecordDecl, 30 /// which is a struct/union/class. The decl represented must be a definition, 31 /// not a forward declaration. 32 /// This class is also used to contain layout information for one 33 /// ObjCInterfaceDecl. FIXME - Find appropriate name. 34 /// These objects are managed by ASTContext. 35 class ASTRecordLayout { 36 /// Size - Size of record in characters. 37 CharUnits Size; 38 39 /// DataSize - Size of record in characters without tail padding. 40 CharUnits DataSize; 41 42 /// FieldOffsets - Array of field offsets in bits. 43 uint64_t *FieldOffsets; 44 45 // Alignment - Alignment of record in characters. 46 CharUnits Alignment; 47 48 // FieldCount - Number of fields. 49 unsigned FieldCount; 50 51 /// CXXRecordLayoutInfo - Contains C++ specific layout information. 52 struct CXXRecordLayoutInfo { 53 /// NonVirtualSize - The non-virtual size (in chars) of an object, which is 54 /// the size of the object without virtual bases. 55 CharUnits NonVirtualSize; 56 57 /// NonVirtualAlign - The non-virtual alignment (in chars) of an object, 58 /// which is the alignment of the object without virtual bases. 59 CharUnits NonVirtualAlign; 60 61 /// SizeOfLargestEmptySubobject - The size of the largest empty subobject 62 /// (either a base or a member). Will be zero if the class doesn't contain 63 /// any empty subobjects. 64 CharUnits SizeOfLargestEmptySubobject; 65 66 /// PrimaryBase - The primary base info for this record. 67 llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase; 68 69 /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) 70 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy; 71 72 /// BaseOffsets - Contains a map from base classes to their offset. 73 BaseOffsetsMapTy BaseOffsets; 74 75 /// VBaseOffsets - Contains a map from vbase classes to their offset. 76 BaseOffsetsMapTy VBaseOffsets; 77 }; 78 79 /// CXXInfo - If the record layout is for a C++ record, this will have 80 /// C++ specific information about the record. 81 CXXRecordLayoutInfo *CXXInfo; 82 83 friend class ASTContext; 84 85 ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, 86 CharUnits datasize, const uint64_t *fieldoffsets, 87 unsigned fieldcount); 88 89 // Constructor for C++ records. 90 typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy; 91 ASTRecordLayout(const ASTContext &Ctx, 92 CharUnits size, CharUnits alignment, CharUnits datasize, 93 const uint64_t *fieldoffsets, unsigned fieldcount, 94 CharUnits nonvirtualsize, CharUnits nonvirtualalign, 95 CharUnits SizeOfLargestEmptySubobject, 96 const CXXRecordDecl *PrimaryBase, 97 bool IsPrimaryBaseVirtual, 98 const BaseOffsetsMapTy& BaseOffsets, 99 const BaseOffsetsMapTy& VBaseOffsets); 100 ~ASTRecordLayout()101 ~ASTRecordLayout() {} 102 103 void Destroy(ASTContext &Ctx); 104 105 ASTRecordLayout(const ASTRecordLayout&); // DO NOT IMPLEMENT 106 void operator=(const ASTRecordLayout&); // DO NOT IMPLEMENT 107 public: 108 109 /// getAlignment - Get the record alignment in characters. getAlignment()110 CharUnits getAlignment() const { return Alignment; } 111 112 /// getSize - Get the record size in characters. getSize()113 CharUnits getSize() const { return Size; } 114 115 /// getFieldCount - Get the number of fields in the layout. getFieldCount()116 unsigned getFieldCount() const { return FieldCount; } 117 118 /// getFieldOffset - Get the offset of the given field index, in 119 /// bits. getFieldOffset(unsigned FieldNo)120 uint64_t getFieldOffset(unsigned FieldNo) const { 121 assert (FieldNo < FieldCount && "Invalid Field No"); 122 return FieldOffsets[FieldNo]; 123 } 124 125 /// getDataSize() - Get the record data size, which is the record size 126 /// without tail padding, in characters. getDataSize()127 CharUnits getDataSize() const { 128 return DataSize; 129 } 130 131 /// getNonVirtualSize - Get the non-virtual size (in chars) of an object, 132 /// which is the size of the object without virtual bases. getNonVirtualSize()133 CharUnits getNonVirtualSize() const { 134 assert(CXXInfo && "Record layout does not have C++ specific info!"); 135 136 return CXXInfo->NonVirtualSize; 137 } 138 139 /// getNonVirtualSize - Get the non-virtual alignment (in chars) of an object, 140 /// which is the alignment of the object without virtual bases. getNonVirtualAlign()141 CharUnits getNonVirtualAlign() const { 142 assert(CXXInfo && "Record layout does not have C++ specific info!"); 143 144 return CXXInfo->NonVirtualAlign; 145 } 146 147 /// getPrimaryBase - Get the primary base for this record. getPrimaryBase()148 const CXXRecordDecl *getPrimaryBase() const { 149 assert(CXXInfo && "Record layout does not have C++ specific info!"); 150 151 return CXXInfo->PrimaryBase.getPointer(); 152 } 153 154 /// isPrimaryBaseVirtual - Get whether the primary base for this record 155 /// is virtual or not. isPrimaryBaseVirtual()156 bool isPrimaryBaseVirtual() const { 157 assert(CXXInfo && "Record layout does not have C++ specific info!"); 158 159 return CXXInfo->PrimaryBase.getInt(); 160 } 161 162 /// getBaseClassOffset - Get the offset, in chars, for the given base class. getBaseClassOffset(const CXXRecordDecl * Base)163 CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const { 164 assert(CXXInfo && "Record layout does not have C++ specific info!"); 165 assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!"); 166 167 return CXXInfo->BaseOffsets[Base]; 168 } 169 170 /// getVBaseClassOffset - Get the offset, in chars, for the given base class. getVBaseClassOffset(const CXXRecordDecl * VBase)171 CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const { 172 assert(CXXInfo && "Record layout does not have C++ specific info!"); 173 assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!"); 174 175 return CXXInfo->VBaseOffsets[VBase]; 176 } 177 178 /// getBaseClassOffsetInBits - Get the offset, in bits, for the given 179 /// base class. getBaseClassOffsetInBits(const CXXRecordDecl * Base)180 uint64_t getBaseClassOffsetInBits(const CXXRecordDecl *Base) const { 181 assert(CXXInfo && "Record layout does not have C++ specific info!"); 182 assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!"); 183 184 return getBaseClassOffset(Base).getQuantity() * 185 Base->getASTContext().getCharWidth(); 186 } 187 188 /// getVBaseClassOffsetInBits - Get the offset, in bits, for the given 189 /// base class. getVBaseClassOffsetInBits(const CXXRecordDecl * VBase)190 uint64_t getVBaseClassOffsetInBits(const CXXRecordDecl *VBase) const { 191 assert(CXXInfo && "Record layout does not have C++ specific info!"); 192 assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!"); 193 194 return getVBaseClassOffset(VBase).getQuantity() * 195 VBase->getASTContext().getCharWidth(); 196 } 197 getSizeOfLargestEmptySubobject()198 CharUnits getSizeOfLargestEmptySubobject() const { 199 assert(CXXInfo && "Record layout does not have C++ specific info!"); 200 return CXXInfo->SizeOfLargestEmptySubobject; 201 } 202 }; 203 204 } // end namespace clang 205 206 #endif 207