RecordLayoutBuilder.cpp revision 6217b80b7a1379b74cced1c076338262c3c980b3
1bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson//=== ASTRecordLayoutBuilder.cpp - Helper class for building record layouts ==// 2bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson// 3bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson// The LLVM Compiler Infrastructure 4bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson// 5bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson// This file is distributed under the University of Illinois Open Source 6bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson// License. See LICENSE.TXT for details. 7bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson// 8bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson//===----------------------------------------------------------------------===// 9bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 10bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson#include "RecordLayoutBuilder.h" 11bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 12bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson#include "clang/AST/Attr.h" 13bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson#include "clang/AST/Decl.h" 1474cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson#include "clang/AST/DeclCXX.h" 1593fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson#include "clang/AST/DeclObjC.h" 16bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson#include "clang/AST/Expr.h" 17bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson#include "clang/AST/RecordLayout.h" 18bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson#include "clang/Basic/TargetInfo.h" 19bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson#include <llvm/Support/MathExtras.h> 20bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 21bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlssonusing namespace clang; 22bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 23bda4c1015e27ac82d31afb4519dd53586e61a51aAnders CarlssonASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx) 2474cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson : Ctx(Ctx), Size(0), Alignment(8), StructPacking(0), NextOffset(0), 25b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson IsUnion(false), NonVirtualSize(0), NonVirtualAlignment(8) {} 26bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 2774cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlssonvoid 2874cbe226207fd101623638dadfa7fbada04ff2a6Anders CarlssonASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { 2974cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson assert(!RD->isPolymorphic() && 3074cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson "FIXME: We don't support polymorphic classes yet!"); 3174cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson 3274cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), 3374cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson e = RD->bases_end(); i != e; ++i) { 3474cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson if (!i->isVirtual()) { 3574cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson const CXXRecordDecl *Base = 366217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); 3774cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson LayoutNonVirtualBase(Base); 3874cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson } 3974cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson } 4074cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson} 4174cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson 4274cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlssonvoid ASTRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *RD) { 4374cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD); 4474cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson assert(BaseInfo.getDataSize() > 0 && 4574cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson "FIXME: Handle empty classes."); 4674cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson 47b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson unsigned BaseAlign = BaseInfo.getNonVirtualAlign(); 48b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson uint64_t BaseSize = BaseInfo.getNonVirtualSize(); 4974cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson 5074cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson // Round up the current record size to the base's alignment boundary. 5174cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson Size = (Size + (BaseAlign-1)) & ~(BaseAlign-1); 5274cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson 53b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson // Add base class offsets. 54b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson Bases.push_back(RD); 55b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson BaseOffsets.push_back(Size); 56b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson 5774cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson // Reserve space for this base. 5874cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson Size += BaseSize; 5974cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson 6074cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson // Remember the next available offset. 6174cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson NextOffset = Size; 6274cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson 6374cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson // Remember max struct/class alignment. 6474cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson UpdateAlignment(BaseAlign); 6574cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson} 6674cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson 67bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlssonvoid ASTRecordLayoutBuilder::Layout(const RecordDecl *D) { 68bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson IsUnion = D->isUnion(); 69bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 70bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (const PackedAttr* PA = D->getAttr<PackedAttr>()) 71bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson StructPacking = PA->getAlignment(); 72bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 73bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) 74bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson UpdateAlignment(AA->getAlignment()); 7574cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson 7674cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson // If this is a C++ class, lay out the nonvirtual bases. 7774cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson if (Ctx.getLangOptions().CPlusPlus) 7874cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson LayoutNonVirtualBases(cast<CXXRecordDecl>(D)); 7974cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson 80a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson LayoutFields(D); 81bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 82b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson NonVirtualSize = Size; 83b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson NonVirtualAlignment = Alignment; 84b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson 85bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // Finally, round the size of the total struct up to the alignment of the 86bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // struct itself. 87bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FinishLayout(); 88bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson} 89bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 9093fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlssonvoid ASTRecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D, 9193fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson const ObjCImplementationDecl *Impl) { 9293fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson if (ObjCInterfaceDecl *SD = D->getSuperClass()) { 9393fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson const ASTRecordLayout &SL = Ctx.getASTObjCInterfaceLayout(SD); 9493fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson 9593fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson UpdateAlignment(SL.getAlignment()); 9693fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson 9793fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson // We start laying out ivars not at the end of the superclass 9893fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson // structure, but at the next byte following the last field. 99243a68551ac9ec71bf341e062418e33eb4f286ffAnders Carlsson Size = llvm::RoundUpToAlignment(SL.getDataSize(), 8); 10093fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson NextOffset = Size; 10193fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson } 10293fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson 10393fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson if (const PackedAttr *PA = D->getAttr<PackedAttr>()) 10493fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson StructPacking = PA->getAlignment(); 10593fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson 10693fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) 10793fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson UpdateAlignment(AA->getAlignment()); 10893fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson 10993fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson // Layout each ivar sequentially. 11093fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; 11193fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson Ctx.ShallowCollectObjCIvars(D, Ivars, Impl); 11293fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson for (unsigned i = 0, e = Ivars.size(); i != e; ++i) 11393fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson LayoutField(Ivars[i]); 11493fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson 11593fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson // Finally, round the size of the total struct up to the alignment of the 11693fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson // struct itself. 11793fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson FinishLayout(); 11893fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson} 11993fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson 120a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlssonvoid ASTRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { 121a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson // Layout each field, for now, just sequentially, respecting alignment. In 122a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson // the future, this will need to be tweakable by targets. 123a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson for (RecordDecl::field_iterator Field = D->field_begin(), 124a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson FieldEnd = D->field_end(); Field != FieldEnd; ++Field) 125a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson LayoutField(*Field); 126a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson} 127a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson 128bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlssonvoid ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) { 129bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson unsigned FieldPacking = StructPacking; 130bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson uint64_t FieldOffset = IsUnion ? 0 : Size; 131bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson uint64_t FieldSize; 132bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson unsigned FieldAlign; 133bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 134bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // FIXME: Should this override struct packing? Probably we want to 135bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // take the minimum? 136bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (const PackedAttr *PA = D->getAttr<PackedAttr>()) 137bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldPacking = PA->getAlignment(); 138bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 139bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (const Expr *BitWidthExpr = D->getBitWidth()) { 140bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // TODO: Need to check this algorithm on other targets! 141bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // (tested on Linux-X86) 142bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldSize = BitWidthExpr->EvaluateAsInt(Ctx).getZExtValue(); 143bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 144bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType()); 145bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson uint64_t TypeSize = FieldInfo.first; 146bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 147bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // Determine the alignment of this bitfield. The packing 148bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // attributes define a maximum and the alignment attribute defines 149bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // a minimum. 150bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // FIXME: What is the right behavior when the specified alignment 151bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // is smaller than the specified packing? 152bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldAlign = FieldInfo.second; 153bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (FieldPacking) 154bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldAlign = std::min(FieldAlign, FieldPacking); 155bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) 156bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldAlign = std::max(FieldAlign, AA->getAlignment()); 157bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 158bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // Check if we need to add padding to give the field the correct 159bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // alignment. 160bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize) 161bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1); 162bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 163bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // Padding members don't affect overall alignment 164bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (!D->getIdentifier()) 165bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldAlign = 1; 166bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson } else { 167bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (D->getType()->isIncompleteArrayType()) { 168bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // This is a flexible array member; we can't directly 169bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // query getTypeInfo about these, so we figure it out here. 170bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // Flexible array members don't have any size, but they 171bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // have to be aligned appropriately for their element type. 172bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldSize = 0; 173bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson const ArrayType* ATy = Ctx.getAsArrayType(D->getType()); 174bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldAlign = Ctx.getTypeAlign(ATy->getElementType()); 1756217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek } else if (const ReferenceType *RT = D->getType()->getAs<ReferenceType>()) { 176bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson unsigned AS = RT->getPointeeType().getAddressSpace(); 177bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldSize = Ctx.Target.getPointerWidth(AS); 178bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldAlign = Ctx.Target.getPointerAlign(AS); 179bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson } else { 180bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType()); 181bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldSize = FieldInfo.first; 182bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldAlign = FieldInfo.second; 183bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson } 184bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 185bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // Determine the alignment of this bitfield. The packing 186bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // attributes define a maximum and the alignment attribute defines 187bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // a minimum. Additionally, the packing alignment must be at least 188bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // a byte for non-bitfields. 189bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // 190bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // FIXME: What is the right behavior when the specified alignment 191bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // is smaller than the specified packing? 192bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (FieldPacking) 193bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldAlign = std::min(FieldAlign, std::max(8U, FieldPacking)); 194bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) 195bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldAlign = std::max(FieldAlign, AA->getAlignment()); 196bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 197bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // Round up the current record size to the field's alignment boundary. 198bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1); 199bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson } 200bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 201bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // Place this field at the current location. 202bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldOffsets.push_back(FieldOffset); 203bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 204bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // Reserve space for this field. 205bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (IsUnion) 206bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson Size = std::max(Size, FieldSize); 207bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson else 208bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson Size = FieldOffset + FieldSize; 209bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 210bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // Remember the next available offset. 211bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson NextOffset = Size; 212bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 213bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // Remember max struct/class alignment. 214bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson UpdateAlignment(FieldAlign); 215bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson} 216bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 217bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlssonvoid ASTRecordLayoutBuilder::FinishLayout() { 218bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // In C++, records cannot be of size 0. 219bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (Ctx.getLangOptions().CPlusPlus && Size == 0) 220bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson Size = 8; 221bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // Finally, round the size of the record up to the alignment of the 222bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // record itself. 223bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson Size = (Size + (Alignment-1)) & ~(Alignment-1); 224bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson} 225bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 226bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlssonvoid ASTRecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) { 227bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (NewAlignment <= Alignment) 228bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson return; 229bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 230bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson assert(llvm::isPowerOf2_32(NewAlignment && "Alignment not a power of 2")); 231bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 232bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson Alignment = NewAlignment; 233bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson} 234bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 235bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlssonconst ASTRecordLayout * 236bda4c1015e27ac82d31afb4519dd53586e61a51aAnders CarlssonASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, 237bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson const RecordDecl *D) { 238bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson ASTRecordLayoutBuilder Builder(Ctx); 239bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 240bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson Builder.Layout(D); 241bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 242b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson if (!isa<CXXRecordDecl>(D)) 243b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson return new ASTRecordLayout(Builder.Size, Builder.Alignment, Builder.Size, 244b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson Builder.FieldOffsets.data(), 245b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson Builder.FieldOffsets.size()); 246b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson 247b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson // FIXME: This is not always correct. See the part about bitfields at 248b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info. 249b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson // FIXME: IsPODForThePurposeOfLayout should be stored in the record layout. 250b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson bool IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD(); 25174cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson 252b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson assert(Builder.Bases.size() == Builder.BaseOffsets.size() && 253b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson "Base offsets vector must be same size as bases vector!"); 254b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson 255b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson // FIXME: This should be done in FinalizeLayout. 25674cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson uint64_t DataSize = 25774cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson IsPODForThePurposeOfLayout ? Builder.Size : Builder.NextOffset; 258b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson uint64_t NonVirtualSize = 259b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize; 26074cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson 26174cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson return new ASTRecordLayout(Builder.Size, Builder.Alignment, DataSize, 26293fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson Builder.FieldOffsets.data(), 263b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson Builder.FieldOffsets.size(), 264b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson NonVirtualSize, 265b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson Builder.NonVirtualAlignment, 266b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson Builder.Bases.data(), 267b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson Builder.BaseOffsets.data(), 268b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson Builder.Bases.size()); 26993fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson} 27093fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson 27193fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlssonconst ASTRecordLayout * 27293fab9d67ca62e3e291803e5a1309473d6e00344Anders CarlssonASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, 27393fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson const ObjCInterfaceDecl *D, 27493fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson const ObjCImplementationDecl *Impl) { 27593fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson ASTRecordLayoutBuilder Builder(Ctx); 27693fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson 27793fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson Builder.Layout(D, Impl); 27893fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson 27993fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson return new ASTRecordLayout(Builder.Size, Builder.Alignment, 28093fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson Builder.NextOffset, 281bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson Builder.FieldOffsets.data(), 282bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson Builder.FieldOffsets.size()); 283bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson} 284