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