CGRecordLayoutBuilder.cpp revision 219077
1206084Srdivacky//===--- CGRecordLayoutBuilder.cpp - CGRecordLayout builder ----*- C++ -*-===// 2198092Srdivacky// 3198092Srdivacky// The LLVM Compiler Infrastructure 4198092Srdivacky// 5198092Srdivacky// This file is distributed under the University of Illinois Open Source 6198092Srdivacky// License. See LICENSE.TXT for details. 7198092Srdivacky// 8198092Srdivacky//===----------------------------------------------------------------------===// 9198092Srdivacky// 10206084Srdivacky// Builder implementation for CGRecordLayout objects. 11198092Srdivacky// 12198092Srdivacky//===----------------------------------------------------------------------===// 13198092Srdivacky 14206084Srdivacky#include "CGRecordLayout.h" 15198092Srdivacky#include "clang/AST/ASTContext.h" 16198092Srdivacky#include "clang/AST/Attr.h" 17218893Sdim#include "clang/AST/CXXInheritance.h" 18198092Srdivacky#include "clang/AST/DeclCXX.h" 19198092Srdivacky#include "clang/AST/Expr.h" 20198092Srdivacky#include "clang/AST/RecordLayout.h" 21198092Srdivacky#include "CodeGenTypes.h" 22212904Sdim#include "CGCXXABI.h" 23207619Srdivacky#include "llvm/DerivedTypes.h" 24206084Srdivacky#include "llvm/Type.h" 25207619Srdivacky#include "llvm/Support/Debug.h" 26207619Srdivacky#include "llvm/Support/raw_ostream.h" 27198092Srdivacky#include "llvm/Target/TargetData.h" 28198092Srdivackyusing namespace clang; 29198092Srdivackyusing namespace CodeGen; 30198092Srdivacky 31218893Sdimnamespace { 32206084Srdivacky 33206084Srdivackyclass CGRecordLayoutBuilder { 34206084Srdivackypublic: 35206084Srdivacky /// FieldTypes - Holds the LLVM types that the struct is created from. 36218893Sdim /// 37206084Srdivacky std::vector<const llvm::Type *> FieldTypes; 38206084Srdivacky 39218893Sdim /// BaseSubobjectType - Holds the LLVM type for the non-virtual part 40218893Sdim /// of the struct. For example, consider: 41218893Sdim /// 42218893Sdim /// struct A { int i; }; 43218893Sdim /// struct B { void *v; }; 44218893Sdim /// struct C : virtual A, B { }; 45218893Sdim /// 46218893Sdim /// The LLVM type of C will be 47218893Sdim /// %struct.C = type { i32 (...)**, %struct.A, i32, %struct.B } 48218893Sdim /// 49218893Sdim /// And the LLVM type of the non-virtual base struct will be 50218893Sdim /// %struct.C.base = type { i32 (...)**, %struct.A, i32 } 51218893Sdim /// 52218893Sdim /// This only gets initialized if the base subobject type is 53218893Sdim /// different from the complete-object type. 54218893Sdim const llvm::StructType *BaseSubobjectType; 55206084Srdivacky 56218893Sdim /// FieldInfo - Holds a field and its corresponding LLVM field number. 57218893Sdim llvm::DenseMap<const FieldDecl *, unsigned> Fields; 58206084Srdivacky 59218893Sdim /// BitFieldInfo - Holds location and size information about a bit field. 60218893Sdim llvm::DenseMap<const FieldDecl *, CGBitFieldInfo> BitFields; 61218893Sdim 62218893Sdim llvm::DenseMap<const CXXRecordDecl *, unsigned> NonVirtualBases; 63218893Sdim llvm::DenseMap<const CXXRecordDecl *, unsigned> VirtualBases; 64218893Sdim 65218893Sdim /// IndirectPrimaryBases - Virtual base classes, direct or indirect, that are 66218893Sdim /// primary base classes for some other direct or indirect base class. 67218893Sdim CXXIndirectPrimaryBaseSet IndirectPrimaryBases; 68218893Sdim 69218893Sdim /// LaidOutVirtualBases - A set of all laid out virtual bases, used to avoid 70218893Sdim /// avoid laying out virtual bases more than once. 71218893Sdim llvm::SmallPtrSet<const CXXRecordDecl *, 4> LaidOutVirtualBases; 72208600Srdivacky 73212904Sdim /// IsZeroInitializable - Whether this struct can be C++ 74212904Sdim /// zero-initialized with an LLVM zeroinitializer. 75212904Sdim bool IsZeroInitializable; 76218893Sdim bool IsZeroInitializableAsBase; 77206084Srdivacky 78206084Srdivacky /// Packed - Whether the resulting LLVM struct will be packed or not. 79206084Srdivacky bool Packed; 80206084Srdivacky 81206084Srdivackyprivate: 82206084Srdivacky CodeGenTypes &Types; 83206084Srdivacky 84206084Srdivacky /// Alignment - Contains the alignment of the RecordDecl. 85206084Srdivacky // 86206084Srdivacky // FIXME: This is not needed and should be removed. 87218893Sdim CharUnits Alignment; 88206084Srdivacky 89206084Srdivacky /// BitsAvailableInLastField - If a bit field spans only part of a LLVM field, 90206084Srdivacky /// this will have the number of bits still available in the field. 91206084Srdivacky char BitsAvailableInLastField; 92206084Srdivacky 93218893Sdim /// NextFieldOffset - Holds the next field offset. 94218893Sdim CharUnits NextFieldOffset; 95206084Srdivacky 96207619Srdivacky /// LayoutUnionField - Will layout a field in an union and return the type 97207619Srdivacky /// that the field will have. 98207619Srdivacky const llvm::Type *LayoutUnionField(const FieldDecl *Field, 99207619Srdivacky const ASTRecordLayout &Layout); 100207619Srdivacky 101206084Srdivacky /// LayoutUnion - Will layout a union RecordDecl. 102206084Srdivacky void LayoutUnion(const RecordDecl *D); 103206084Srdivacky 104206084Srdivacky /// LayoutField - try to layout all fields in the record decl. 105206084Srdivacky /// Returns false if the operation failed because the struct is not packed. 106206084Srdivacky bool LayoutFields(const RecordDecl *D); 107206084Srdivacky 108218893Sdim /// Layout a single base, virtual or non-virtual 109218893Sdim void LayoutBase(const CXXRecordDecl *base, 110218893Sdim const CGRecordLayout &baseLayout, 111218893Sdim CharUnits baseOffset); 112218893Sdim 113218893Sdim /// LayoutVirtualBase - layout a single virtual base. 114218893Sdim void LayoutVirtualBase(const CXXRecordDecl *base, 115218893Sdim CharUnits baseOffset); 116218893Sdim 117218893Sdim /// LayoutVirtualBases - layout the virtual bases of a record decl. 118218893Sdim void LayoutVirtualBases(const CXXRecordDecl *RD, 119218893Sdim const ASTRecordLayout &Layout); 120218893Sdim 121208600Srdivacky /// LayoutNonVirtualBase - layout a single non-virtual base. 122218893Sdim void LayoutNonVirtualBase(const CXXRecordDecl *base, 123218893Sdim CharUnits baseOffset); 124208600Srdivacky 125218893Sdim /// LayoutNonVirtualBases - layout the virtual bases of a record decl. 126208600Srdivacky void LayoutNonVirtualBases(const CXXRecordDecl *RD, 127208600Srdivacky const ASTRecordLayout &Layout); 128206084Srdivacky 129218893Sdim /// ComputeNonVirtualBaseType - Compute the non-virtual base field types. 130218893Sdim bool ComputeNonVirtualBaseType(const CXXRecordDecl *RD); 131218893Sdim 132206084Srdivacky /// LayoutField - layout a single field. Returns false if the operation failed 133206084Srdivacky /// because the current struct is not packed. 134206084Srdivacky bool LayoutField(const FieldDecl *D, uint64_t FieldOffset); 135206084Srdivacky 136206084Srdivacky /// LayoutBitField - layout a single bit field. 137206084Srdivacky void LayoutBitField(const FieldDecl *D, uint64_t FieldOffset); 138206084Srdivacky 139206084Srdivacky /// AppendField - Appends a field with the given offset and type. 140218893Sdim void AppendField(CharUnits fieldOffset, const llvm::Type *FieldTy); 141206084Srdivacky 142206084Srdivacky /// AppendPadding - Appends enough padding bytes so that the total 143206084Srdivacky /// struct size is a multiple of the field alignment. 144218893Sdim void AppendPadding(CharUnits fieldOffset, CharUnits fieldAlignment); 145206084Srdivacky 146218893Sdim /// getByteArrayType - Returns a byte array type with the given number of 147218893Sdim /// elements. 148218893Sdim const llvm::Type *getByteArrayType(CharUnits NumBytes); 149218893Sdim 150206084Srdivacky /// AppendBytes - Append a given number of bytes to the record. 151218893Sdim void AppendBytes(CharUnits numBytes); 152206084Srdivacky 153206084Srdivacky /// AppendTailPadding - Append enough tail padding so that the type will have 154206084Srdivacky /// the passed size. 155206084Srdivacky void AppendTailPadding(uint64_t RecordSize); 156206084Srdivacky 157218893Sdim CharUnits getTypeAlignment(const llvm::Type *Ty) const; 158206084Srdivacky 159218893Sdim /// getAlignmentAsLLVMStruct - Returns the maximum alignment of all the 160218893Sdim /// LLVM element types. 161218893Sdim CharUnits getAlignmentAsLLVMStruct() const; 162218893Sdim 163212904Sdim /// CheckZeroInitializable - Check if the given type contains a pointer 164206084Srdivacky /// to data member. 165212904Sdim void CheckZeroInitializable(QualType T); 166206084Srdivacky 167206084Srdivackypublic: 168206084Srdivacky CGRecordLayoutBuilder(CodeGenTypes &Types) 169218893Sdim : BaseSubobjectType(0), 170218893Sdim IsZeroInitializable(true), IsZeroInitializableAsBase(true), 171218893Sdim Packed(false), Types(Types), BitsAvailableInLastField(0) { } 172206084Srdivacky 173206084Srdivacky /// Layout - Will layout a RecordDecl. 174206084Srdivacky void Layout(const RecordDecl *D); 175206084Srdivacky}; 176206084Srdivacky 177206084Srdivacky} 178206084Srdivacky 179198092Srdivackyvoid CGRecordLayoutBuilder::Layout(const RecordDecl *D) { 180218893Sdim Alignment = Types.getContext().getASTRecordLayout(D).getAlignment(); 181198092Srdivacky Packed = D->hasAttr<PackedAttr>(); 182198092Srdivacky 183198092Srdivacky if (D->isUnion()) { 184198092Srdivacky LayoutUnion(D); 185198092Srdivacky return; 186198092Srdivacky } 187198092Srdivacky 188198092Srdivacky if (LayoutFields(D)) 189198092Srdivacky return; 190198092Srdivacky 191198092Srdivacky // We weren't able to layout the struct. Try again with a packed struct 192198092Srdivacky Packed = true; 193218893Sdim NextFieldOffset = CharUnits::Zero(); 194198092Srdivacky FieldTypes.clear(); 195218893Sdim Fields.clear(); 196218893Sdim BitFields.clear(); 197218893Sdim NonVirtualBases.clear(); 198218893Sdim VirtualBases.clear(); 199198092Srdivacky 200198092Srdivacky LayoutFields(D); 201198092Srdivacky} 202198092Srdivacky 203212904SdimCGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types, 204212904Sdim const FieldDecl *FD, 205212904Sdim uint64_t FieldOffset, 206212904Sdim uint64_t FieldSize, 207212904Sdim uint64_t ContainingTypeSizeInBits, 208212904Sdim unsigned ContainingTypeAlign) { 209207619Srdivacky const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(FD->getType()); 210219077Sdim CharUnits TypeSizeInBytes = 211219077Sdim CharUnits::fromQuantity(Types.getTargetData().getTypeAllocSize(Ty)); 212219077Sdim uint64_t TypeSizeInBits = Types.getContext().toBits(TypeSizeInBytes); 213207619Srdivacky 214207619Srdivacky bool IsSigned = FD->getType()->isSignedIntegerType(); 215207619Srdivacky 216207619Srdivacky if (FieldSize > TypeSizeInBits) { 217207619Srdivacky // We have a wide bit-field. The extra bits are only used for padding, so 218207619Srdivacky // if we have a bitfield of type T, with size N: 219207619Srdivacky // 220207619Srdivacky // T t : N; 221207619Srdivacky // 222207619Srdivacky // We can just assume that it's: 223207619Srdivacky // 224207619Srdivacky // T t : sizeof(T); 225207619Srdivacky // 226207619Srdivacky FieldSize = TypeSizeInBits; 227207619Srdivacky } 228207619Srdivacky 229218893Sdim // in big-endian machines the first fields are in higher bit positions, 230218893Sdim // so revert the offset. The byte offsets are reversed(back) later. 231218893Sdim if (Types.getTargetData().isBigEndian()) { 232218893Sdim FieldOffset = ((ContainingTypeSizeInBits)-FieldOffset-FieldSize); 233218893Sdim } 234218893Sdim 235207619Srdivacky // Compute the access components. The policy we use is to start by attempting 236207619Srdivacky // to access using the width of the bit-field type itself and to always access 237207619Srdivacky // at aligned indices of that type. If such an access would fail because it 238207619Srdivacky // extends past the bound of the type, then we reduce size to the next smaller 239207619Srdivacky // power of two and retry. The current algorithm assumes pow2 sized types, 240207619Srdivacky // although this is easy to fix. 241207619Srdivacky // 242207619Srdivacky assert(llvm::isPowerOf2_32(TypeSizeInBits) && "Unexpected type size!"); 243207619Srdivacky CGBitFieldInfo::AccessInfo Components[3]; 244207619Srdivacky unsigned NumComponents = 0; 245207619Srdivacky unsigned AccessedTargetBits = 0; // The tumber of target bits accessed. 246207619Srdivacky unsigned AccessWidth = TypeSizeInBits; // The current access width to attempt. 247207619Srdivacky 248207619Srdivacky // Round down from the field offset to find the first access position that is 249207619Srdivacky // at an aligned offset of the initial access type. 250207619Srdivacky uint64_t AccessStart = FieldOffset - (FieldOffset % AccessWidth); 251207619Srdivacky 252207619Srdivacky // Adjust initial access size to fit within record. 253219077Sdim while (AccessWidth > Types.getTarget().getCharWidth() && 254207619Srdivacky AccessStart + AccessWidth > ContainingTypeSizeInBits) { 255207619Srdivacky AccessWidth >>= 1; 256207619Srdivacky AccessStart = FieldOffset - (FieldOffset % AccessWidth); 257207619Srdivacky } 258207619Srdivacky 259207619Srdivacky while (AccessedTargetBits < FieldSize) { 260207619Srdivacky // Check that we can access using a type of this size, without reading off 261207619Srdivacky // the end of the structure. This can occur with packed structures and 262207619Srdivacky // -fno-bitfield-type-align, for example. 263207619Srdivacky if (AccessStart + AccessWidth > ContainingTypeSizeInBits) { 264207619Srdivacky // If so, reduce access size to the next smaller power-of-two and retry. 265207619Srdivacky AccessWidth >>= 1; 266219077Sdim assert(AccessWidth >= Types.getTarget().getCharWidth() 267219077Sdim && "Cannot access under byte size!"); 268207619Srdivacky continue; 269207619Srdivacky } 270207619Srdivacky 271207619Srdivacky // Otherwise, add an access component. 272207619Srdivacky 273207619Srdivacky // First, compute the bits inside this access which are part of the 274207619Srdivacky // target. We are reading bits [AccessStart, AccessStart + AccessWidth); the 275207619Srdivacky // intersection with [FieldOffset, FieldOffset + FieldSize) gives the bits 276207619Srdivacky // in the target that we are reading. 277207619Srdivacky assert(FieldOffset < AccessStart + AccessWidth && "Invalid access start!"); 278207619Srdivacky assert(AccessStart < FieldOffset + FieldSize && "Invalid access start!"); 279207619Srdivacky uint64_t AccessBitsInFieldStart = std::max(AccessStart, FieldOffset); 280207619Srdivacky uint64_t AccessBitsInFieldSize = 281207619Srdivacky std::min(AccessWidth + AccessStart, 282207619Srdivacky FieldOffset + FieldSize) - AccessBitsInFieldStart; 283207619Srdivacky 284207619Srdivacky assert(NumComponents < 3 && "Unexpected number of components!"); 285207619Srdivacky CGBitFieldInfo::AccessInfo &AI = Components[NumComponents++]; 286207619Srdivacky AI.FieldIndex = 0; 287207619Srdivacky // FIXME: We still follow the old access pattern of only using the field 288207619Srdivacky // byte offset. We should switch this once we fix the struct layout to be 289207619Srdivacky // pretty. 290218893Sdim 291218893Sdim // on big-endian machines we reverted the bit offset because first fields are 292218893Sdim // in higher bits. But this also reverts the bytes, so fix this here by reverting 293218893Sdim // the byte offset on big-endian machines. 294218893Sdim if (Types.getTargetData().isBigEndian()) { 295218893Sdim AI.FieldByteOffset = (ContainingTypeSizeInBits - AccessStart - AccessWidth )/8; 296218893Sdim } else { 297218893Sdim AI.FieldByteOffset = AccessStart / 8; 298218893Sdim } 299207619Srdivacky AI.FieldBitStart = AccessBitsInFieldStart - AccessStart; 300207619Srdivacky AI.AccessWidth = AccessWidth; 301207619Srdivacky AI.AccessAlignment = llvm::MinAlign(ContainingTypeAlign, AccessStart) / 8; 302207619Srdivacky AI.TargetBitOffset = AccessedTargetBits; 303207619Srdivacky AI.TargetBitWidth = AccessBitsInFieldSize; 304207619Srdivacky 305207619Srdivacky AccessStart += AccessWidth; 306207619Srdivacky AccessedTargetBits += AI.TargetBitWidth; 307207619Srdivacky } 308207619Srdivacky 309207619Srdivacky assert(AccessedTargetBits == FieldSize && "Invalid bit-field access!"); 310207619Srdivacky return CGBitFieldInfo(FieldSize, NumComponents, Components, IsSigned); 311207619Srdivacky} 312207619Srdivacky 313212904SdimCGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types, 314212904Sdim const FieldDecl *FD, 315212904Sdim uint64_t FieldOffset, 316212904Sdim uint64_t FieldSize) { 317212904Sdim const RecordDecl *RD = FD->getParent(); 318212904Sdim const ASTRecordLayout &RL = Types.getContext().getASTRecordLayout(RD); 319218893Sdim uint64_t ContainingTypeSizeInBits = Types.getContext().toBits(RL.getSize()); 320218893Sdim unsigned ContainingTypeAlign = Types.getContext().toBits(RL.getAlignment()); 321212904Sdim 322212904Sdim return MakeInfo(Types, FD, FieldOffset, FieldSize, ContainingTypeSizeInBits, 323212904Sdim ContainingTypeAlign); 324212904Sdim} 325212904Sdim 326198092Srdivackyvoid CGRecordLayoutBuilder::LayoutBitField(const FieldDecl *D, 327218893Sdim uint64_t fieldOffset) { 328218893Sdim uint64_t fieldSize = 329198092Srdivacky D->getBitWidth()->EvaluateAsInt(Types.getContext()).getZExtValue(); 330198092Srdivacky 331218893Sdim if (fieldSize == 0) 332198092Srdivacky return; 333198092Srdivacky 334219077Sdim uint64_t nextFieldOffsetInBits = Types.getContext().toBits(NextFieldOffset); 335218893Sdim unsigned numBytesToAppend; 336198092Srdivacky 337218893Sdim if (fieldOffset < nextFieldOffsetInBits) { 338198092Srdivacky assert(BitsAvailableInLastField && "Bitfield size mismatch!"); 339218893Sdim assert(!NextFieldOffset.isZero() && "Must have laid out at least one byte"); 340198092Srdivacky 341198092Srdivacky // The bitfield begins in the previous bit-field. 342218893Sdim numBytesToAppend = 343218893Sdim llvm::RoundUpToAlignment(fieldSize - BitsAvailableInLastField, 8) / 8; 344198092Srdivacky } else { 345218893Sdim assert(fieldOffset % 8 == 0 && "Field offset not aligned correctly"); 346198092Srdivacky 347198092Srdivacky // Append padding if necessary. 348218893Sdim AppendPadding(CharUnits::fromQuantity(fieldOffset / 8), CharUnits::One()); 349198092Srdivacky 350218893Sdim numBytesToAppend = llvm::RoundUpToAlignment(fieldSize, 8) / 8; 351198092Srdivacky 352218893Sdim assert(numBytesToAppend && "No bytes to append!"); 353198092Srdivacky } 354198092Srdivacky 355207619Srdivacky // Add the bit field info. 356218893Sdim BitFields.insert(std::make_pair(D, 357218893Sdim CGBitFieldInfo::MakeInfo(Types, D, fieldOffset, fieldSize))); 358198092Srdivacky 359218893Sdim AppendBytes(CharUnits::fromQuantity(numBytesToAppend)); 360198092Srdivacky 361198092Srdivacky BitsAvailableInLastField = 362218893Sdim NextFieldOffset.getQuantity() * 8 - (fieldOffset + fieldSize); 363198092Srdivacky} 364198092Srdivacky 365198092Srdivackybool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D, 366218893Sdim uint64_t fieldOffset) { 367198092Srdivacky // If the field is packed, then we need a packed struct. 368198092Srdivacky if (!Packed && D->hasAttr<PackedAttr>()) 369198092Srdivacky return false; 370198092Srdivacky 371198092Srdivacky if (D->isBitField()) { 372198092Srdivacky // We must use packed structs for unnamed bit fields since they 373198092Srdivacky // don't affect the struct alignment. 374198092Srdivacky if (!Packed && !D->getDeclName()) 375198092Srdivacky return false; 376198092Srdivacky 377218893Sdim LayoutBitField(D, fieldOffset); 378198092Srdivacky return true; 379198092Srdivacky } 380198092Srdivacky 381212904Sdim CheckZeroInitializable(D->getType()); 382206084Srdivacky 383219077Sdim assert(fieldOffset % Types.getTarget().getCharWidth() == 0 384219077Sdim && "field offset is not on a byte boundary!"); 385219077Sdim CharUnits fieldOffsetInBytes 386219077Sdim = Types.getContext().toCharUnitsFromBits(fieldOffset); 387198092Srdivacky 388198092Srdivacky const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(D->getType()); 389218893Sdim CharUnits typeAlignment = getTypeAlignment(Ty); 390198092Srdivacky 391198092Srdivacky // If the type alignment is larger then the struct alignment, we must use 392198092Srdivacky // a packed struct. 393218893Sdim if (typeAlignment > Alignment) { 394198092Srdivacky assert(!Packed && "Alignment is wrong even with packed struct!"); 395198092Srdivacky return false; 396198092Srdivacky } 397198092Srdivacky 398218893Sdim if (!Packed) { 399218893Sdim if (const RecordType *RT = D->getType()->getAs<RecordType>()) { 400218893Sdim const RecordDecl *RD = cast<RecordDecl>(RT->getDecl()); 401218893Sdim if (const MaxFieldAlignmentAttr *MFAA = 402218893Sdim RD->getAttr<MaxFieldAlignmentAttr>()) { 403219077Sdim if (MFAA->getAlignment() != Types.getContext().toBits(typeAlignment)) 404218893Sdim return false; 405218893Sdim } 406198092Srdivacky } 407198092Srdivacky } 408198092Srdivacky 409198092Srdivacky // Round up the field offset to the alignment of the field type. 410218893Sdim CharUnits alignedNextFieldOffsetInBytes = 411218893Sdim NextFieldOffset.RoundUpToAlignment(typeAlignment); 412198092Srdivacky 413218893Sdim if (fieldOffsetInBytes < alignedNextFieldOffsetInBytes) { 414198092Srdivacky assert(!Packed && "Could not place field even with packed struct!"); 415198092Srdivacky return false; 416198092Srdivacky } 417198092Srdivacky 418218893Sdim AppendPadding(fieldOffsetInBytes, typeAlignment); 419198092Srdivacky 420198092Srdivacky // Now append the field. 421218893Sdim Fields[D] = FieldTypes.size(); 422218893Sdim AppendField(fieldOffsetInBytes, Ty); 423198092Srdivacky 424198092Srdivacky return true; 425198092Srdivacky} 426198092Srdivacky 427207619Srdivackyconst llvm::Type * 428207619SrdivackyCGRecordLayoutBuilder::LayoutUnionField(const FieldDecl *Field, 429207619Srdivacky const ASTRecordLayout &Layout) { 430207619Srdivacky if (Field->isBitField()) { 431207619Srdivacky uint64_t FieldSize = 432207619Srdivacky Field->getBitWidth()->EvaluateAsInt(Types.getContext()).getZExtValue(); 433207619Srdivacky 434207619Srdivacky // Ignore zero sized bit fields. 435207619Srdivacky if (FieldSize == 0) 436207619Srdivacky return 0; 437207619Srdivacky 438207619Srdivacky const llvm::Type *FieldTy = llvm::Type::getInt8Ty(Types.getLLVMContext()); 439207619Srdivacky unsigned NumBytesToAppend = 440207619Srdivacky llvm::RoundUpToAlignment(FieldSize, 8) / 8; 441207619Srdivacky 442207619Srdivacky if (NumBytesToAppend > 1) 443207619Srdivacky FieldTy = llvm::ArrayType::get(FieldTy, NumBytesToAppend); 444207619Srdivacky 445207619Srdivacky // Add the bit field info. 446218893Sdim BitFields.insert(std::make_pair(Field, 447218893Sdim CGBitFieldInfo::MakeInfo(Types, Field, 0, FieldSize))); 448207619Srdivacky return FieldTy; 449207619Srdivacky } 450207619Srdivacky 451207619Srdivacky // This is a regular union field. 452218893Sdim Fields[Field] = 0; 453207619Srdivacky return Types.ConvertTypeForMemRecursive(Field->getType()); 454207619Srdivacky} 455207619Srdivacky 456198092Srdivackyvoid CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) { 457198092Srdivacky assert(D->isUnion() && "Can't call LayoutUnion on a non-union record!"); 458198092Srdivacky 459218893Sdim const ASTRecordLayout &layout = Types.getContext().getASTRecordLayout(D); 460198092Srdivacky 461218893Sdim const llvm::Type *unionType = 0; 462218893Sdim CharUnits unionSize = CharUnits::Zero(); 463218893Sdim CharUnits unionAlign = CharUnits::Zero(); 464198092Srdivacky 465218893Sdim bool hasOnlyZeroSizedBitFields = true; 466206084Srdivacky 467218893Sdim unsigned fieldNo = 0; 468218893Sdim for (RecordDecl::field_iterator field = D->field_begin(), 469218893Sdim fieldEnd = D->field_end(); field != fieldEnd; ++field, ++fieldNo) { 470218893Sdim assert(layout.getFieldOffset(fieldNo) == 0 && 471198092Srdivacky "Union field offset did not start at the beginning of record!"); 472218893Sdim const llvm::Type *fieldType = LayoutUnionField(*field, layout); 473198092Srdivacky 474218893Sdim if (!fieldType) 475207619Srdivacky continue; 476198092Srdivacky 477218893Sdim hasOnlyZeroSizedBitFields = false; 478206084Srdivacky 479218893Sdim CharUnits fieldAlign = CharUnits::fromQuantity( 480218893Sdim Types.getTargetData().getABITypeAlignment(fieldType)); 481218893Sdim CharUnits fieldSize = CharUnits::fromQuantity( 482218893Sdim Types.getTargetData().getTypeAllocSize(fieldType)); 483198092Srdivacky 484218893Sdim if (fieldAlign < unionAlign) 485198092Srdivacky continue; 486198092Srdivacky 487218893Sdim if (fieldAlign > unionAlign || fieldSize > unionSize) { 488218893Sdim unionType = fieldType; 489218893Sdim unionAlign = fieldAlign; 490218893Sdim unionSize = fieldSize; 491198092Srdivacky } 492198092Srdivacky } 493198092Srdivacky 494198092Srdivacky // Now add our field. 495218893Sdim if (unionType) { 496218893Sdim AppendField(CharUnits::Zero(), unionType); 497198092Srdivacky 498218893Sdim if (getTypeAlignment(unionType) > layout.getAlignment()) { 499198092Srdivacky // We need a packed struct. 500198092Srdivacky Packed = true; 501218893Sdim unionAlign = CharUnits::One(); 502198092Srdivacky } 503198092Srdivacky } 504218893Sdim if (unionAlign.isZero()) { 505218893Sdim assert(hasOnlyZeroSizedBitFields && 506203955Srdivacky "0-align record did not have all zero-sized bit-fields!"); 507218893Sdim unionAlign = CharUnits::One(); 508199482Srdivacky } 509206084Srdivacky 510198092Srdivacky // Append tail padding. 511218893Sdim CharUnits recordSize = layout.getSize(); 512218893Sdim if (recordSize > unionSize) 513218893Sdim AppendPadding(recordSize, unionAlign); 514198092Srdivacky} 515198092Srdivacky 516218893Sdimvoid CGRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *base, 517218893Sdim const CGRecordLayout &baseLayout, 518218893Sdim CharUnits baseOffset) { 519218893Sdim AppendPadding(baseOffset, CharUnits::One()); 520208600Srdivacky 521218893Sdim const ASTRecordLayout &baseASTLayout 522218893Sdim = Types.getContext().getASTRecordLayout(base); 523208600Srdivacky 524218893Sdim // Fields and bases can be laid out in the tail padding of previous 525218893Sdim // bases. If this happens, we need to allocate the base as an i8 526218893Sdim // array; otherwise, we can use the subobject type. However, 527218893Sdim // actually doing that would require knowledge of what immediately 528218893Sdim // follows this base in the layout, so instead we do a conservative 529218893Sdim // approximation, which is to use the base subobject type if it 530218893Sdim // has the same LLVM storage size as the nvsize. 531218893Sdim 532218893Sdim // The nvsize, i.e. the unpadded size of the base class. 533218893Sdim CharUnits nvsize = baseASTLayout.getNonVirtualSize(); 534218893Sdim 535218893Sdim#if 0 536218893Sdim const llvm::StructType *subobjectType = baseLayout.getBaseSubobjectLLVMType(); 537218893Sdim const llvm::StructLayout *baseLLVMLayout = 538218893Sdim Types.getTargetData().getStructLayout(subobjectType); 539218893Sdim CharUnits stsize = CharUnits::fromQuantity(baseLLVMLayout->getSizeInBytes()); 540218893Sdim 541218893Sdim if (nvsize == stsize) 542218893Sdim AppendField(baseOffset, subobjectType); 543218893Sdim else 544218893Sdim#endif 545218893Sdim AppendBytes(nvsize); 546218893Sdim} 547218893Sdim 548218893Sdimvoid CGRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *base, 549218893Sdim CharUnits baseOffset) { 550218893Sdim // Ignore empty bases. 551218893Sdim if (base->isEmpty()) return; 552218893Sdim 553218893Sdim const CGRecordLayout &baseLayout = Types.getCGRecordLayout(base); 554218893Sdim if (IsZeroInitializableAsBase) { 555218893Sdim assert(IsZeroInitializable && 556218893Sdim "class zero-initializable as base but not as complete object"); 557218893Sdim 558218893Sdim IsZeroInitializable = IsZeroInitializableAsBase = 559218893Sdim baseLayout.isZeroInitializableAsBase(); 560208600Srdivacky } 561208600Srdivacky 562218893Sdim LayoutBase(base, baseLayout, baseOffset); 563218893Sdim NonVirtualBases[base] = (FieldTypes.size() - 1); 564218893Sdim} 565208600Srdivacky 566218893Sdimvoid 567218893SdimCGRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *base, 568218893Sdim CharUnits baseOffset) { 569218893Sdim // Ignore empty bases. 570218893Sdim if (base->isEmpty()) return; 571208600Srdivacky 572218893Sdim const CGRecordLayout &baseLayout = Types.getCGRecordLayout(base); 573218893Sdim if (IsZeroInitializable) 574218893Sdim IsZeroInitializable = baseLayout.isZeroInitializableAsBase(); 575218893Sdim 576218893Sdim LayoutBase(base, baseLayout, baseOffset); 577218893Sdim VirtualBases[base] = (FieldTypes.size() - 1); 578208600Srdivacky} 579208600Srdivacky 580218893Sdim/// LayoutVirtualBases - layout the non-virtual bases of a record decl. 581208600Srdivackyvoid 582218893SdimCGRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD, 583218893Sdim const ASTRecordLayout &Layout) { 584218893Sdim for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), 585218893Sdim E = RD->bases_end(); I != E; ++I) { 586218893Sdim const CXXRecordDecl *BaseDecl = 587218893Sdim cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); 588218893Sdim 589218893Sdim // We only want to lay out virtual bases that aren't indirect primary bases 590218893Sdim // of some other base. 591218893Sdim if (I->isVirtual() && !IndirectPrimaryBases.count(BaseDecl)) { 592218893Sdim // Only lay out the base once. 593218893Sdim if (!LaidOutVirtualBases.insert(BaseDecl)) 594218893Sdim continue; 595218893Sdim 596218893Sdim CharUnits vbaseOffset = Layout.getVBaseClassOffset(BaseDecl); 597218893Sdim LayoutVirtualBase(BaseDecl, vbaseOffset); 598218893Sdim } 599218893Sdim 600218893Sdim if (!BaseDecl->getNumVBases()) { 601218893Sdim // This base isn't interesting since it doesn't have any virtual bases. 602218893Sdim continue; 603218893Sdim } 604218893Sdim 605218893Sdim LayoutVirtualBases(BaseDecl, Layout); 606218893Sdim } 607218893Sdim} 608218893Sdim 609218893Sdimvoid 610208600SrdivackyCGRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD, 611208600Srdivacky const ASTRecordLayout &Layout) { 612208600Srdivacky const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); 613208600Srdivacky 614201361Srdivacky // Check if we need to add a vtable pointer. 615208600Srdivacky if (RD->isDynamicClass()) { 616208600Srdivacky if (!PrimaryBase) { 617208600Srdivacky const llvm::Type *FunctionType = 618208600Srdivacky llvm::FunctionType::get(llvm::Type::getInt32Ty(Types.getLLVMContext()), 619208600Srdivacky /*isVarArg=*/true); 620208600Srdivacky const llvm::Type *VTableTy = FunctionType->getPointerTo(); 621206084Srdivacky 622218893Sdim assert(NextFieldOffset.isZero() && 623208600Srdivacky "VTable pointer must come first!"); 624218893Sdim AppendField(CharUnits::Zero(), VTableTy->getPointerTo()); 625208600Srdivacky } else { 626218893Sdim if (!Layout.isPrimaryBaseVirtual()) 627218893Sdim LayoutNonVirtualBase(PrimaryBase, CharUnits::Zero()); 628218893Sdim else 629218893Sdim LayoutVirtualBase(PrimaryBase, CharUnits::Zero()); 630208600Srdivacky } 631201361Srdivacky } 632208600Srdivacky 633208600Srdivacky // Layout the non-virtual bases. 634208600Srdivacky for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), 635208600Srdivacky E = RD->bases_end(); I != E; ++I) { 636208600Srdivacky if (I->isVirtual()) 637208600Srdivacky continue; 638208600Srdivacky 639208600Srdivacky const CXXRecordDecl *BaseDecl = 640208600Srdivacky cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); 641208600Srdivacky 642208600Srdivacky // We've already laid out the primary base. 643218893Sdim if (BaseDecl == PrimaryBase && !Layout.isPrimaryBaseVirtual()) 644208600Srdivacky continue; 645208600Srdivacky 646208600Srdivacky LayoutNonVirtualBase(BaseDecl, Layout.getBaseClassOffset(BaseDecl)); 647208600Srdivacky } 648201361Srdivacky} 649201361Srdivacky 650218893Sdimbool 651218893SdimCGRecordLayoutBuilder::ComputeNonVirtualBaseType(const CXXRecordDecl *RD) { 652218893Sdim const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(RD); 653218893Sdim 654218893Sdim CharUnits NonVirtualSize = Layout.getNonVirtualSize(); 655218893Sdim CharUnits NonVirtualAlign = Layout.getNonVirtualAlign(); 656218893Sdim CharUnits AlignedNonVirtualTypeSize = 657218893Sdim NonVirtualSize.RoundUpToAlignment(NonVirtualAlign); 658218893Sdim 659218893Sdim // First check if we can use the same fields as for the complete class. 660218893Sdim CharUnits RecordSize = Layout.getSize(); 661218893Sdim if (AlignedNonVirtualTypeSize == RecordSize) 662218893Sdim return true; 663218893Sdim 664218893Sdim // Check if we need padding. 665218893Sdim CharUnits AlignedNextFieldOffset = 666218893Sdim NextFieldOffset.RoundUpToAlignment(getAlignmentAsLLVMStruct()); 667218893Sdim 668218893Sdim if (AlignedNextFieldOffset > AlignedNonVirtualTypeSize) { 669218893Sdim assert(!Packed && "cannot layout even as packed struct"); 670218893Sdim return false; // Needs packing. 671218893Sdim } 672218893Sdim 673218893Sdim bool needsPadding = (AlignedNonVirtualTypeSize != AlignedNextFieldOffset); 674218893Sdim if (needsPadding) { 675218893Sdim CharUnits NumBytes = AlignedNonVirtualTypeSize - AlignedNextFieldOffset; 676218893Sdim FieldTypes.push_back(getByteArrayType(NumBytes)); 677218893Sdim } 678218893Sdim 679218893Sdim BaseSubobjectType = llvm::StructType::get(Types.getLLVMContext(), 680218893Sdim FieldTypes, Packed); 681218893Sdim 682218893Sdim if (needsPadding) { 683218893Sdim // Pull the padding back off. 684218893Sdim FieldTypes.pop_back(); 685218893Sdim } 686218893Sdim 687218893Sdim return true; 688218893Sdim} 689218893Sdim 690198092Srdivackybool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { 691198092Srdivacky assert(!D->isUnion() && "Can't call LayoutFields on a union!"); 692218893Sdim assert(!Alignment.isZero() && "Did not set alignment!"); 693198092Srdivacky 694198092Srdivacky const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D); 695198092Srdivacky 696218893Sdim const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D); 697218893Sdim if (RD) 698208600Srdivacky LayoutNonVirtualBases(RD, Layout); 699206084Srdivacky 700198092Srdivacky unsigned FieldNo = 0; 701198092Srdivacky 702198092Srdivacky for (RecordDecl::field_iterator Field = D->field_begin(), 703198092Srdivacky FieldEnd = D->field_end(); Field != FieldEnd; ++Field, ++FieldNo) { 704198092Srdivacky if (!LayoutField(*Field, Layout.getFieldOffset(FieldNo))) { 705198092Srdivacky assert(!Packed && 706198092Srdivacky "Could not layout fields even with a packed LLVM struct!"); 707198092Srdivacky return false; 708198092Srdivacky } 709198092Srdivacky } 710198092Srdivacky 711218893Sdim if (RD) { 712218893Sdim // We've laid out the non-virtual bases and the fields, now compute the 713218893Sdim // non-virtual base field types. 714218893Sdim if (!ComputeNonVirtualBaseType(RD)) { 715218893Sdim assert(!Packed && "Could not layout even with a packed LLVM struct!"); 716218893Sdim return false; 717218893Sdim } 718218893Sdim 719218893Sdim // And lay out the virtual bases. 720218893Sdim RD->getIndirectPrimaryBases(IndirectPrimaryBases); 721218893Sdim if (Layout.isPrimaryBaseVirtual()) 722218893Sdim IndirectPrimaryBases.insert(Layout.getPrimaryBase()); 723218893Sdim LayoutVirtualBases(RD, Layout); 724218893Sdim } 725218893Sdim 726198092Srdivacky // Append tail padding if necessary. 727218893Sdim AppendTailPadding(Types.getContext().toBits(Layout.getSize())); 728198092Srdivacky 729198092Srdivacky return true; 730198092Srdivacky} 731198092Srdivacky 732198092Srdivackyvoid CGRecordLayoutBuilder::AppendTailPadding(uint64_t RecordSize) { 733198092Srdivacky assert(RecordSize % 8 == 0 && "Invalid record size!"); 734198092Srdivacky 735219077Sdim CharUnits RecordSizeInBytes = 736219077Sdim Types.getContext().toCharUnitsFromBits(RecordSize); 737218893Sdim assert(NextFieldOffset <= RecordSizeInBytes && "Size mismatch!"); 738198092Srdivacky 739218893Sdim CharUnits AlignedNextFieldOffset = 740218893Sdim NextFieldOffset.RoundUpToAlignment(getAlignmentAsLLVMStruct()); 741200583Srdivacky 742200583Srdivacky if (AlignedNextFieldOffset == RecordSizeInBytes) { 743200583Srdivacky // We don't need any padding. 744200583Srdivacky return; 745200583Srdivacky } 746206084Srdivacky 747218893Sdim CharUnits NumPadBytes = RecordSizeInBytes - NextFieldOffset; 748198092Srdivacky AppendBytes(NumPadBytes); 749198092Srdivacky} 750198092Srdivacky 751218893Sdimvoid CGRecordLayoutBuilder::AppendField(CharUnits fieldOffset, 752218893Sdim const llvm::Type *fieldType) { 753218893Sdim CharUnits fieldSize = 754218893Sdim CharUnits::fromQuantity(Types.getTargetData().getTypeAllocSize(fieldType)); 755198092Srdivacky 756218893Sdim FieldTypes.push_back(fieldType); 757198092Srdivacky 758218893Sdim NextFieldOffset = fieldOffset + fieldSize; 759198092Srdivacky BitsAvailableInLastField = 0; 760198092Srdivacky} 761198092Srdivacky 762218893Sdimvoid CGRecordLayoutBuilder::AppendPadding(CharUnits fieldOffset, 763218893Sdim CharUnits fieldAlignment) { 764218893Sdim assert(NextFieldOffset <= fieldOffset && 765198092Srdivacky "Incorrect field layout!"); 766198092Srdivacky 767198092Srdivacky // Round up the field offset to the alignment of the field type. 768218893Sdim CharUnits alignedNextFieldOffset = 769218893Sdim NextFieldOffset.RoundUpToAlignment(fieldAlignment); 770198092Srdivacky 771218893Sdim if (alignedNextFieldOffset < fieldOffset) { 772198092Srdivacky // Even with alignment, the field offset is not at the right place, 773198092Srdivacky // insert padding. 774218893Sdim CharUnits padding = fieldOffset - NextFieldOffset; 775198092Srdivacky 776218893Sdim AppendBytes(padding); 777198092Srdivacky } 778198092Srdivacky} 779198092Srdivacky 780218893Sdimconst llvm::Type *CGRecordLayoutBuilder::getByteArrayType(CharUnits numBytes) { 781218893Sdim assert(!numBytes.isZero() && "Empty byte arrays aren't allowed."); 782198092Srdivacky 783198092Srdivacky const llvm::Type *Ty = llvm::Type::getInt8Ty(Types.getLLVMContext()); 784218893Sdim if (numBytes > CharUnits::One()) 785218893Sdim Ty = llvm::ArrayType::get(Ty, numBytes.getQuantity()); 786198092Srdivacky 787218893Sdim return Ty; 788218893Sdim} 789218893Sdim 790218893Sdimvoid CGRecordLayoutBuilder::AppendBytes(CharUnits numBytes) { 791218893Sdim if (numBytes.isZero()) 792218893Sdim return; 793218893Sdim 794198092Srdivacky // Append the padding field 795218893Sdim AppendField(NextFieldOffset, getByteArrayType(numBytes)); 796198092Srdivacky} 797198092Srdivacky 798218893SdimCharUnits CGRecordLayoutBuilder::getTypeAlignment(const llvm::Type *Ty) const { 799198092Srdivacky if (Packed) 800218893Sdim return CharUnits::One(); 801198092Srdivacky 802218893Sdim return CharUnits::fromQuantity(Types.getTargetData().getABITypeAlignment(Ty)); 803198092Srdivacky} 804198092Srdivacky 805218893SdimCharUnits CGRecordLayoutBuilder::getAlignmentAsLLVMStruct() const { 806218893Sdim if (Packed) 807218893Sdim return CharUnits::One(); 808218893Sdim 809218893Sdim CharUnits maxAlignment = CharUnits::One(); 810218893Sdim for (size_t i = 0; i != FieldTypes.size(); ++i) 811218893Sdim maxAlignment = std::max(maxAlignment, getTypeAlignment(FieldTypes[i])); 812218893Sdim 813218893Sdim return maxAlignment; 814218893Sdim} 815218893Sdim 816218893Sdim/// Merge in whether a field of the given type is zero-initializable. 817212904Sdimvoid CGRecordLayoutBuilder::CheckZeroInitializable(QualType T) { 818198092Srdivacky // This record already contains a member pointer. 819218893Sdim if (!IsZeroInitializableAsBase) 820198092Srdivacky return; 821198092Srdivacky 822198092Srdivacky // Can only have member pointers if we're compiling C++. 823198092Srdivacky if (!Types.getContext().getLangOptions().CPlusPlus) 824198092Srdivacky return; 825198092Srdivacky 826218893Sdim const Type *elementType = T->getBaseElementTypeUnsafe(); 827198092Srdivacky 828218893Sdim if (const MemberPointerType *MPT = elementType->getAs<MemberPointerType>()) { 829212904Sdim if (!Types.getCXXABI().isZeroInitializable(MPT)) 830218893Sdim IsZeroInitializable = IsZeroInitializableAsBase = false; 831218893Sdim } else if (const RecordType *RT = elementType->getAs<RecordType>()) { 832203955Srdivacky const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); 833218893Sdim const CGRecordLayout &Layout = Types.getCGRecordLayout(RD); 834218893Sdim if (!Layout.isZeroInitializable()) 835218893Sdim IsZeroInitializable = IsZeroInitializableAsBase = false; 836208600Srdivacky } 837208600Srdivacky} 838206084Srdivacky 839206084SrdivackyCGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) { 840206084Srdivacky CGRecordLayoutBuilder Builder(*this); 841198092Srdivacky 842198092Srdivacky Builder.Layout(D); 843198092Srdivacky 844218893Sdim const llvm::StructType *Ty = llvm::StructType::get(getLLVMContext(), 845218893Sdim Builder.FieldTypes, 846218893Sdim Builder.Packed); 847198092Srdivacky 848218893Sdim // If we're in C++, compute the base subobject type. 849218893Sdim const llvm::StructType *BaseTy = 0; 850218893Sdim if (isa<CXXRecordDecl>(D)) { 851218893Sdim BaseTy = Builder.BaseSubobjectType; 852218893Sdim if (!BaseTy) BaseTy = Ty; 853218893Sdim } 854218893Sdim 855206084Srdivacky CGRecordLayout *RL = 856218893Sdim new CGRecordLayout(Ty, BaseTy, Builder.IsZeroInitializable, 857218893Sdim Builder.IsZeroInitializableAsBase); 858206084Srdivacky 859218893Sdim RL->NonVirtualBases.swap(Builder.NonVirtualBases); 860218893Sdim RL->CompleteObjectVirtualBases.swap(Builder.VirtualBases); 861208600Srdivacky 862198092Srdivacky // Add all the field numbers. 863218893Sdim RL->FieldInfo.swap(Builder.Fields); 864198092Srdivacky 865198092Srdivacky // Add bitfield info. 866218893Sdim RL->BitFields.swap(Builder.BitFields); 867198092Srdivacky 868207619Srdivacky // Dump the layout, if requested. 869207619Srdivacky if (getContext().getLangOptions().DumpRecordLayouts) { 870207619Srdivacky llvm::errs() << "\n*** Dumping IRgen Record Layout\n"; 871207619Srdivacky llvm::errs() << "Record: "; 872207619Srdivacky D->dump(); 873207619Srdivacky llvm::errs() << "\nLayout: "; 874207619Srdivacky RL->dump(); 875207619Srdivacky } 876207619Srdivacky 877207619Srdivacky#ifndef NDEBUG 878207619Srdivacky // Verify that the computed LLVM struct size matches the AST layout size. 879218893Sdim const ASTRecordLayout &Layout = getContext().getASTRecordLayout(D); 880218893Sdim 881218893Sdim uint64_t TypeSizeInBits = getContext().toBits(Layout.getSize()); 882207619Srdivacky assert(TypeSizeInBits == getTargetData().getTypeAllocSizeInBits(Ty) && 883207619Srdivacky "Type size mismatch!"); 884207619Srdivacky 885218893Sdim if (BaseTy) { 886218893Sdim CharUnits NonVirtualSize = Layout.getNonVirtualSize(); 887218893Sdim CharUnits NonVirtualAlign = Layout.getNonVirtualAlign(); 888218893Sdim CharUnits AlignedNonVirtualTypeSize = 889218893Sdim NonVirtualSize.RoundUpToAlignment(NonVirtualAlign); 890218893Sdim 891218893Sdim uint64_t AlignedNonVirtualTypeSizeInBits = 892218893Sdim getContext().toBits(AlignedNonVirtualTypeSize); 893218893Sdim 894218893Sdim assert(AlignedNonVirtualTypeSizeInBits == 895218893Sdim getTargetData().getTypeAllocSizeInBits(BaseTy) && 896218893Sdim "Type size mismatch!"); 897218893Sdim } 898218893Sdim 899207619Srdivacky // Verify that the LLVM and AST field offsets agree. 900207619Srdivacky const llvm::StructType *ST = 901207619Srdivacky dyn_cast<llvm::StructType>(RL->getLLVMType()); 902207619Srdivacky const llvm::StructLayout *SL = getTargetData().getStructLayout(ST); 903207619Srdivacky 904207619Srdivacky const ASTRecordLayout &AST_RL = getContext().getASTRecordLayout(D); 905207619Srdivacky RecordDecl::field_iterator it = D->field_begin(); 906207619Srdivacky for (unsigned i = 0, e = AST_RL.getFieldCount(); i != e; ++i, ++it) { 907207619Srdivacky const FieldDecl *FD = *it; 908207619Srdivacky 909207619Srdivacky // For non-bit-fields, just check that the LLVM struct offset matches the 910207619Srdivacky // AST offset. 911207619Srdivacky if (!FD->isBitField()) { 912207619Srdivacky unsigned FieldNo = RL->getLLVMFieldNo(FD); 913207619Srdivacky assert(AST_RL.getFieldOffset(i) == SL->getElementOffsetInBits(FieldNo) && 914207619Srdivacky "Invalid field offset!"); 915207619Srdivacky continue; 916207619Srdivacky } 917207619Srdivacky 918207619Srdivacky // Ignore unnamed bit-fields. 919207619Srdivacky if (!FD->getDeclName()) 920207619Srdivacky continue; 921207619Srdivacky 922207619Srdivacky const CGBitFieldInfo &Info = RL->getBitFieldInfo(FD); 923207619Srdivacky for (unsigned i = 0, e = Info.getNumComponents(); i != e; ++i) { 924207619Srdivacky const CGBitFieldInfo::AccessInfo &AI = Info.getComponent(i); 925207619Srdivacky 926207619Srdivacky // Verify that every component access is within the structure. 927207619Srdivacky uint64_t FieldOffset = SL->getElementOffsetInBits(AI.FieldIndex); 928219077Sdim uint64_t AccessBitOffset = FieldOffset + 929219077Sdim getContext().toBits(CharUnits::fromQuantity(AI.FieldByteOffset)); 930207619Srdivacky assert(AccessBitOffset + AI.AccessWidth <= TypeSizeInBits && 931207619Srdivacky "Invalid bit-field access (out of range)!"); 932207619Srdivacky } 933207619Srdivacky } 934207619Srdivacky#endif 935207619Srdivacky 936206084Srdivacky return RL; 937198092Srdivacky} 938207619Srdivacky 939207619Srdivackyvoid CGRecordLayout::print(llvm::raw_ostream &OS) const { 940207619Srdivacky OS << "<CGRecordLayout\n"; 941218893Sdim OS << " LLVMType:" << *CompleteObjectType << "\n"; 942218893Sdim if (BaseSubobjectType) 943218893Sdim OS << " NonVirtualBaseLLVMType:" << *BaseSubobjectType << "\n"; 944212904Sdim OS << " IsZeroInitializable:" << IsZeroInitializable << "\n"; 945207619Srdivacky OS << " BitFields:[\n"; 946207619Srdivacky 947207619Srdivacky // Print bit-field infos in declaration order. 948207619Srdivacky std::vector<std::pair<unsigned, const CGBitFieldInfo*> > BFIs; 949207619Srdivacky for (llvm::DenseMap<const FieldDecl*, CGBitFieldInfo>::const_iterator 950207619Srdivacky it = BitFields.begin(), ie = BitFields.end(); 951207619Srdivacky it != ie; ++it) { 952207619Srdivacky const RecordDecl *RD = it->first->getParent(); 953207619Srdivacky unsigned Index = 0; 954207619Srdivacky for (RecordDecl::field_iterator 955207619Srdivacky it2 = RD->field_begin(); *it2 != it->first; ++it2) 956207619Srdivacky ++Index; 957207619Srdivacky BFIs.push_back(std::make_pair(Index, &it->second)); 958207619Srdivacky } 959207619Srdivacky llvm::array_pod_sort(BFIs.begin(), BFIs.end()); 960207619Srdivacky for (unsigned i = 0, e = BFIs.size(); i != e; ++i) { 961207619Srdivacky OS.indent(4); 962207619Srdivacky BFIs[i].second->print(OS); 963207619Srdivacky OS << "\n"; 964207619Srdivacky } 965207619Srdivacky 966207619Srdivacky OS << "]>\n"; 967207619Srdivacky} 968207619Srdivacky 969207619Srdivackyvoid CGRecordLayout::dump() const { 970207619Srdivacky print(llvm::errs()); 971207619Srdivacky} 972207619Srdivacky 973207619Srdivackyvoid CGBitFieldInfo::print(llvm::raw_ostream &OS) const { 974207619Srdivacky OS << "<CGBitFieldInfo"; 975207619Srdivacky OS << " Size:" << Size; 976207619Srdivacky OS << " IsSigned:" << IsSigned << "\n"; 977207619Srdivacky 978207619Srdivacky OS.indent(4 + strlen("<CGBitFieldInfo")); 979207619Srdivacky OS << " NumComponents:" << getNumComponents(); 980207619Srdivacky OS << " Components: ["; 981207619Srdivacky if (getNumComponents()) { 982207619Srdivacky OS << "\n"; 983207619Srdivacky for (unsigned i = 0, e = getNumComponents(); i != e; ++i) { 984207619Srdivacky const AccessInfo &AI = getComponent(i); 985207619Srdivacky OS.indent(8); 986207619Srdivacky OS << "<AccessInfo" 987207619Srdivacky << " FieldIndex:" << AI.FieldIndex 988207619Srdivacky << " FieldByteOffset:" << AI.FieldByteOffset 989207619Srdivacky << " FieldBitStart:" << AI.FieldBitStart 990207619Srdivacky << " AccessWidth:" << AI.AccessWidth << "\n"; 991207619Srdivacky OS.indent(8 + strlen("<AccessInfo")); 992207619Srdivacky OS << " AccessAlignment:" << AI.AccessAlignment 993207619Srdivacky << " TargetBitOffset:" << AI.TargetBitOffset 994207619Srdivacky << " TargetBitWidth:" << AI.TargetBitWidth 995207619Srdivacky << ">\n"; 996207619Srdivacky } 997207619Srdivacky OS.indent(4); 998207619Srdivacky } 999207619Srdivacky OS << "]>"; 1000207619Srdivacky} 1001207619Srdivacky 1002207619Srdivackyvoid CGBitFieldInfo::dump() const { 1003207619Srdivacky print(llvm::errs()); 1004207619Srdivacky} 1005