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