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 /// VBPtrOffset - Virtual base table offset. 67 CharUnits VBPtrOffset; 68 69 /// PrimaryBase - The primary base info for this record. 70 llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase; 71 72 /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) 73 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy; 74 75 /// BaseOffsets - Contains a map from base classes to their offset. 76 BaseOffsetsMapTy BaseOffsets; 77 78 /// VBaseOffsets - Contains a map from vbase classes to their offset. 79 BaseOffsetsMapTy VBaseOffsets; 80 }; 81 82 /// CXXInfo - If the record layout is for a C++ record, this will have 83 /// C++ specific information about the record. 84 CXXRecordLayoutInfo *CXXInfo; 85 86 friend class ASTContext; 87 88 ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, 89 CharUnits datasize, const uint64_t *fieldoffsets, 90 unsigned fieldcount); 91 92 // Constructor for C++ records. 93 typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy; 94 ASTRecordLayout(const ASTContext &Ctx, 95 CharUnits size, CharUnits alignment, CharUnits vbptroffset, 96 CharUnits datasize, 97 const uint64_t *fieldoffsets, unsigned fieldcount, 98 CharUnits nonvirtualsize, CharUnits nonvirtualalign, 99 CharUnits SizeOfLargestEmptySubobject, 100 const CXXRecordDecl *PrimaryBase, 101 bool IsPrimaryBaseVirtual, 102 const BaseOffsetsMapTy& BaseOffsets, 103 const BaseOffsetsMapTy& VBaseOffsets); 104 105 ~ASTRecordLayout() {} 106 107 void Destroy(ASTContext &Ctx); 108 109 ASTRecordLayout(const ASTRecordLayout&); // DO NOT IMPLEMENT 110 void operator=(const ASTRecordLayout&); // DO NOT IMPLEMENT 111 public: 112 113 /// getAlignment - Get the record alignment in characters. 114 CharUnits getAlignment() const { return Alignment; } 115 116 /// getSize - Get the record size in characters. 117 CharUnits getSize() const { return Size; } 118 119 /// getFieldCount - Get the number of fields in the layout. 120 unsigned getFieldCount() const { return FieldCount; } 121 122 /// getFieldOffset - Get the offset of the given field index, in 123 /// bits. 124 uint64_t getFieldOffset(unsigned FieldNo) const { 125 assert (FieldNo < FieldCount && "Invalid Field No"); 126 return FieldOffsets[FieldNo]; 127 } 128 129 /// getDataSize() - Get the record data size, which is the record size 130 /// without tail padding, in characters. 131 CharUnits getDataSize() const { 132 return DataSize; 133 } 134 135 /// getNonVirtualSize - Get the non-virtual size (in chars) of an object, 136 /// which is the size of the object without virtual bases. 137 CharUnits getNonVirtualSize() const { 138 assert(CXXInfo && "Record layout does not have C++ specific info!"); 139 140 return CXXInfo->NonVirtualSize; 141 } 142 143 /// getNonVirtualSize - Get the non-virtual alignment (in chars) of an object, 144 /// which is the alignment of the object without virtual bases. 145 CharUnits getNonVirtualAlign() const { 146 assert(CXXInfo && "Record layout does not have C++ specific info!"); 147 148 return CXXInfo->NonVirtualAlign; 149 } 150 151 /// getPrimaryBase - Get the primary base for this record. 152 const CXXRecordDecl *getPrimaryBase() const { 153 assert(CXXInfo && "Record layout does not have C++ specific info!"); 154 155 return CXXInfo->PrimaryBase.getPointer(); 156 } 157 158 /// isPrimaryBaseVirtual - Get whether the primary base for this record 159 /// is virtual or not. 160 bool isPrimaryBaseVirtual() const { 161 assert(CXXInfo && "Record layout does not have C++ specific info!"); 162 163 return CXXInfo->PrimaryBase.getInt(); 164 } 165 166 /// getBaseClassOffset - Get the offset, in chars, for the given base class. 167 CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const { 168 assert(CXXInfo && "Record layout does not have C++ specific info!"); 169 assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!"); 170 171 return CXXInfo->BaseOffsets[Base]; 172 } 173 174 /// getVBaseClassOffset - Get the offset, in chars, for the given base class. 175 CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const { 176 assert(CXXInfo && "Record layout does not have C++ specific info!"); 177 assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!"); 178 179 return CXXInfo->VBaseOffsets[VBase]; 180 } 181 182 /// getBaseClassOffsetInBits - Get the offset, in bits, for the given 183 /// base class. 184 uint64_t getBaseClassOffsetInBits(const CXXRecordDecl *Base) const { 185 assert(CXXInfo && "Record layout does not have C++ specific info!"); 186 assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!"); 187 188 return getBaseClassOffset(Base).getQuantity() * 189 Base->getASTContext().getCharWidth(); 190 } 191 192 /// getVBaseClassOffsetInBits - Get the offset, in bits, for the given 193 /// base class. 194 uint64_t getVBaseClassOffsetInBits(const CXXRecordDecl *VBase) const { 195 assert(CXXInfo && "Record layout does not have C++ specific info!"); 196 assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!"); 197 198 return getVBaseClassOffset(VBase).getQuantity() * 199 VBase->getASTContext().getCharWidth(); 200 } 201 202 CharUnits getSizeOfLargestEmptySubobject() const { 203 assert(CXXInfo && "Record layout does not have C++ specific info!"); 204 return CXXInfo->SizeOfLargestEmptySubobject; 205 } 206 207 CharUnits getVBPtrOffset() const { 208 return CXXInfo->VBPtrOffset; 209 } 210 }; 211 212 } // end namespace clang 213 214 #endif 215