RecordLayoutBuilder.cpp revision 49520944c688a9d5fc78d0c2af544b825873477b
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"
196f376336138ea719e3c4757ae046a5768043b276Mike Stump#include <llvm/ADT/SmallSet.h>
20bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson#include <llvm/Support/MathExtras.h>
21bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
22bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlssonusing namespace clang;
23bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
24bda4c1015e27ac82d31afb4519dd53586e61a51aAnders CarlssonASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx)
25a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson  : Ctx(Ctx), Size(0), Alignment(8), Packed(false), MaxFieldAlignment(0),
26a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson  NextOffset(0), IsUnion(false), NonVirtualSize(0), NonVirtualAlignment(8) {}
27bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
282effeca6b4461c56c9b2d38778cd718be006f90eMike Stump/// LayoutVtable - Lay out the vtable and set PrimaryBase.
293dee6efcad9ad56d14f7edd1c29924f0b876a7f9Mike Stumpvoid ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) {
306f376336138ea719e3c4757ae046a5768043b276Mike Stump  // FIXME: audit indirect virtual bases
312effeca6b4461c56c9b2d38778cd718be006f90eMike Stump  if (!RD->isPolymorphic() && !RD->getNumVBases()) {
322effeca6b4461c56c9b2d38778cd718be006f90eMike Stump    // There is no primary base in this case.
33928f1506eb38bb26a1284b876213a8f5244f6933Mike Stump    setPrimaryBase(0, false);
346f376336138ea719e3c4757ae046a5768043b276Mike Stump    return;
352effeca6b4461c56c9b2d38778cd718be006f90eMike Stump  }
366f376336138ea719e3c4757ae046a5768043b276Mike Stump
376f376336138ea719e3c4757ae046a5768043b276Mike Stump  SelectPrimaryBase(RD);
386f376336138ea719e3c4757ae046a5768043b276Mike Stump  if (PrimaryBase == 0) {
396f376336138ea719e3c4757ae046a5768043b276Mike Stump    int AS = 0;
406f376336138ea719e3c4757ae046a5768043b276Mike Stump    UpdateAlignment(Ctx.Target.getPointerAlign(AS));
416f376336138ea719e3c4757ae046a5768043b276Mike Stump    Size += Ctx.Target.getPointerWidth(AS);
426f376336138ea719e3c4757ae046a5768043b276Mike Stump    NextOffset = Size;
436f376336138ea719e3c4757ae046a5768043b276Mike Stump  }
443dee6efcad9ad56d14f7edd1c29924f0b876a7f9Mike Stump}
453dee6efcad9ad56d14f7edd1c29924f0b876a7f9Mike Stump
4674cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlssonvoid
4774cbe226207fd101623638dadfa7fbada04ff2a6Anders CarlssonASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
4874cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
4974cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson       e = RD->bases_end(); i != e; ++i) {
5074cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson    if (!i->isVirtual()) {
5174cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson      const CXXRecordDecl *Base =
526217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek        cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
532effeca6b4461c56c9b2d38778cd718be006f90eMike Stump      // Skip the PrimaryBase here, as it is laid down first.
542effeca6b4461c56c9b2d38778cd718be006f90eMike Stump      if (Base != PrimaryBase)
55eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump        LayoutBaseNonVirtually(Base);
5674cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson    }
5774cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson  }
5874cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson}
5974cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson
606f376336138ea719e3c4757ae046a5768043b276Mike Stump// Helper routines related to the abi definition from:
616f376336138ea719e3c4757ae046a5768043b276Mike Stump//   http://www.codesourcery.com/public/cxx-abi/abi.html
626f376336138ea719e3c4757ae046a5768043b276Mike Stump//
636f376336138ea719e3c4757ae046a5768043b276Mike Stump/// IsNearlyEmpty - Indicates when a class has a vtable pointer, but
646f376336138ea719e3c4757ae046a5768043b276Mike Stump/// no other data.
656f376336138ea719e3c4757ae046a5768043b276Mike Stumpbool ASTRecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) {
666f376336138ea719e3c4757ae046a5768043b276Mike Stump  // FIXME: Audit the corners
676f376336138ea719e3c4757ae046a5768043b276Mike Stump  if (!RD->isDynamicClass())
686f376336138ea719e3c4757ae046a5768043b276Mike Stump    return false;
696f376336138ea719e3c4757ae046a5768043b276Mike Stump  const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD);
706f376336138ea719e3c4757ae046a5768043b276Mike Stump  if (BaseInfo.getNonVirtualSize() == Ctx.Target.getPointerWidth(0))
716f376336138ea719e3c4757ae046a5768043b276Mike Stump    return true;
726f376336138ea719e3c4757ae046a5768043b276Mike Stump  return false;
736f376336138ea719e3c4757ae046a5768043b276Mike Stump}
746f376336138ea719e3c4757ae046a5768043b276Mike Stump
756f376336138ea719e3c4757ae046a5768043b276Mike Stumpvoid ASTRecordLayoutBuilder::SelectPrimaryForBase(const CXXRecordDecl *RD,
766f376336138ea719e3c4757ae046a5768043b276Mike Stump                    llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary) {
7749520944c688a9d5fc78d0c2af544b825873477bMike Stump  const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
7849520944c688a9d5fc78d0c2af544b825873477bMike Stump  const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
7949520944c688a9d5fc78d0c2af544b825873477bMike Stump  const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
8049520944c688a9d5fc78d0c2af544b825873477bMike Stump  if (PrimaryBaseWasVirtual) {
8149520944c688a9d5fc78d0c2af544b825873477bMike Stump    IndirectPrimary.insert(PrimaryBase);
8249520944c688a9d5fc78d0c2af544b825873477bMike Stump  }
836f376336138ea719e3c4757ae046a5768043b276Mike Stump  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
846f376336138ea719e3c4757ae046a5768043b276Mike Stump       e = RD->bases_end(); i != e; ++i) {
8549520944c688a9d5fc78d0c2af544b825873477bMike Stump    const CXXRecordDecl *Base =
8649520944c688a9d5fc78d0c2af544b825873477bMike Stump      cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
8749520944c688a9d5fc78d0c2af544b825873477bMike Stump    // Only bases with virtual bases participate in computing the
8849520944c688a9d5fc78d0c2af544b825873477bMike Stump    // indirect primary virtual base classes.
8949520944c688a9d5fc78d0c2af544b825873477bMike Stump    // FIXME: audit indirect virtual bases
9049520944c688a9d5fc78d0c2af544b825873477bMike Stump    if (Base->getNumVBases() == 0)
9149520944c688a9d5fc78d0c2af544b825873477bMike Stump      continue;
9249520944c688a9d5fc78d0c2af544b825873477bMike Stump    SelectPrimaryForBase(Base, IndirectPrimary);
936f376336138ea719e3c4757ae046a5768043b276Mike Stump  }
946f376336138ea719e3c4757ae046a5768043b276Mike Stump}
956f376336138ea719e3c4757ae046a5768043b276Mike Stump
966f376336138ea719e3c4757ae046a5768043b276Mike Stump/// SelectPrimaryBase - Selects the primary base for the given class and
9749520944c688a9d5fc78d0c2af544b825873477bMike Stump/// record that with setPrimaryBase.
986f376336138ea719e3c4757ae046a5768043b276Mike Stumpvoid ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) {
996f376336138ea719e3c4757ae046a5768043b276Mike Stump  // The primary base is the first non-virtual indirect or direct base class,
1006f376336138ea719e3c4757ae046a5768043b276Mike Stump  // if one exists.
1016f376336138ea719e3c4757ae046a5768043b276Mike Stump  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
1026f376336138ea719e3c4757ae046a5768043b276Mike Stump       e = RD->bases_end(); i != e; ++i) {
1036f376336138ea719e3c4757ae046a5768043b276Mike Stump    if (!i->isVirtual()) {
1046f376336138ea719e3c4757ae046a5768043b276Mike Stump      const CXXRecordDecl *Base =
1056f376336138ea719e3c4757ae046a5768043b276Mike Stump        cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
1066f376336138ea719e3c4757ae046a5768043b276Mike Stump      if (Base->isDynamicClass()) {
107928f1506eb38bb26a1284b876213a8f5244f6933Mike Stump        setPrimaryBase(Base, false);
1086f376336138ea719e3c4757ae046a5768043b276Mike Stump        return;
1096f376336138ea719e3c4757ae046a5768043b276Mike Stump      }
1106f376336138ea719e3c4757ae046a5768043b276Mike Stump    }
1116f376336138ea719e3c4757ae046a5768043b276Mike Stump  }
1126f376336138ea719e3c4757ae046a5768043b276Mike Stump
1136f376336138ea719e3c4757ae046a5768043b276Mike Stump  // Otherwise, it is the first nearly empty virtual base that is not an
11449520944c688a9d5fc78d0c2af544b825873477bMike Stump  // indirect primary virtual base class, if one exists.
1156f376336138ea719e3c4757ae046a5768043b276Mike Stump
1166f376336138ea719e3c4757ae046a5768043b276Mike Stump  // If we have no virtual bases at this point, bail out as the searching below
1176f376336138ea719e3c4757ae046a5768043b276Mike Stump  // is expensive.
1186f376336138ea719e3c4757ae046a5768043b276Mike Stump  // FIXME: audit indirect virtual bases
1196f376336138ea719e3c4757ae046a5768043b276Mike Stump  if (RD->getNumVBases() == 0) {
120928f1506eb38bb26a1284b876213a8f5244f6933Mike Stump    setPrimaryBase(0, false);
1216f376336138ea719e3c4757ae046a5768043b276Mike Stump    return;
1226f376336138ea719e3c4757ae046a5768043b276Mike Stump  }
1236f376336138ea719e3c4757ae046a5768043b276Mike Stump
12449520944c688a9d5fc78d0c2af544b825873477bMike Stump  // First, we compute all the primary virtual bases for all of our direct and
12549520944c688a9d5fc78d0c2af544b825873477bMike Stump  // indirect bases, and record all their primary virtual base classes.
1266f376336138ea719e3c4757ae046a5768043b276Mike Stump  const CXXRecordDecl *FirstPrimary = 0;
1276f376336138ea719e3c4757ae046a5768043b276Mike Stump  llvm::SmallSet<const CXXRecordDecl*, 32> IndirectPrimary;
1286f376336138ea719e3c4757ae046a5768043b276Mike Stump  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
1296f376336138ea719e3c4757ae046a5768043b276Mike Stump       e = RD->bases_end(); i != e; ++i) {
13049520944c688a9d5fc78d0c2af544b825873477bMike Stump    const CXXRecordDecl *Base =
13149520944c688a9d5fc78d0c2af544b825873477bMike Stump      cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
13249520944c688a9d5fc78d0c2af544b825873477bMike Stump    SelectPrimaryForBase(Base, IndirectPrimary);
1336f376336138ea719e3c4757ae046a5768043b276Mike Stump  }
1346f376336138ea719e3c4757ae046a5768043b276Mike Stump
1356f376336138ea719e3c4757ae046a5768043b276Mike Stump  // Then we can search for the first nearly empty virtual base itself.
13649520944c688a9d5fc78d0c2af544b825873477bMike Stump  // FIXME: audit indirect virtual bases and order (backwards?)
1376f376336138ea719e3c4757ae046a5768043b276Mike Stump  for (CXXRecordDecl::base_class_const_iterator i = RD->vbases_begin(),
1386f376336138ea719e3c4757ae046a5768043b276Mike Stump       e = RD->vbases_end(); i != e; ++i) {
1396f376336138ea719e3c4757ae046a5768043b276Mike Stump    const CXXRecordDecl *Base =
1406f376336138ea719e3c4757ae046a5768043b276Mike Stump      cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
1416f376336138ea719e3c4757ae046a5768043b276Mike Stump    if (IsNearlyEmpty(Base)) {
1426f376336138ea719e3c4757ae046a5768043b276Mike Stump      if (FirstPrimary==0)
1436f376336138ea719e3c4757ae046a5768043b276Mike Stump        FirstPrimary = Base;
1446f376336138ea719e3c4757ae046a5768043b276Mike Stump      if (!IndirectPrimary.count(Base)) {
145928f1506eb38bb26a1284b876213a8f5244f6933Mike Stump        setPrimaryBase(Base, true);
1466f376336138ea719e3c4757ae046a5768043b276Mike Stump        return;
1476f376336138ea719e3c4757ae046a5768043b276Mike Stump      }
1486f376336138ea719e3c4757ae046a5768043b276Mike Stump    }
1496f376336138ea719e3c4757ae046a5768043b276Mike Stump  }
1506f376336138ea719e3c4757ae046a5768043b276Mike Stump
151928f1506eb38bb26a1284b876213a8f5244f6933Mike Stump  // Otherwise if is the first nearly empty virtual base, if one exists,
152928f1506eb38bb26a1284b876213a8f5244f6933Mike Stump  // otherwise there is no primary base class.
153928f1506eb38bb26a1284b876213a8f5244f6933Mike Stump  setPrimaryBase(FirstPrimary, true);
1546f376336138ea719e3c4757ae046a5768043b276Mike Stump  return;
1556f376336138ea719e3c4757ae046a5768043b276Mike Stump}
1566f376336138ea719e3c4757ae046a5768043b276Mike Stump
157eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stumpvoid ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) {
158eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump  LayoutBaseNonVirtually(RD);
159eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump}
160eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump
161eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stumpvoid ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD) {
162eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump  // FIXME: audit indirect virtual bases
163eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump  for (CXXRecordDecl::base_class_const_iterator i = RD->vbases_begin(),
164eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump         e = RD->vbases_end(); i != e; ++i) {
165eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump    const CXXRecordDecl *Base =
166eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump      cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
167eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump    if (Base != PrimaryBase)
168eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump      LayoutVirtualBase(Base);
169eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump  }
170eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump}
171eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump
172eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stumpvoid ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD) {
17374cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson  const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD);
17474cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson    assert(BaseInfo.getDataSize() > 0 &&
17574cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson           "FIXME: Handle empty classes.");
17674cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson
177b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson  unsigned BaseAlign = BaseInfo.getNonVirtualAlign();
178b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson  uint64_t BaseSize = BaseInfo.getNonVirtualSize();
17974cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson
18074cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson  // Round up the current record size to the base's alignment boundary.
18174cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson  Size = (Size + (BaseAlign-1)) & ~(BaseAlign-1);
18274cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson
183b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson  // Add base class offsets.
184b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson  Bases.push_back(RD);
185b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson  BaseOffsets.push_back(Size);
186b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson
18774cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson  // Reserve space for this base.
18874cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson  Size += BaseSize;
18974cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson
19074cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson  // Remember the next available offset.
19174cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson  NextOffset = Size;
19274cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson
19374cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson  // Remember max struct/class alignment.
19474cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson  UpdateAlignment(BaseAlign);
19574cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson}
19674cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson
197bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlssonvoid ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
198bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  IsUnion = D->isUnion();
199a860e755f1f9f071b6a6a2f96128a6a258f5c331Anders Carlsson
200a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson  Packed = D->hasAttr<PackedAttr>();
201a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson
202a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson  // The #pragma pack attribute specifies the maximum field alignment.
203a860e755f1f9f071b6a6a2f96128a6a258f5c331Anders Carlsson  if (const PragmaPackAttr *PPA = D->getAttr<PragmaPackAttr>())
204a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson    MaxFieldAlignment = PPA->getAlignment();
205bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
206bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
207bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    UpdateAlignment(AA->getAlignment());
20874cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson
20974cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson  // If this is a C++ class, lay out the nonvirtual bases.
210eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump  const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D);
211eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump  if (RD) {
2123dee6efcad9ad56d14f7edd1c29924f0b876a7f9Mike Stump    LayoutVtable(RD);
2132effeca6b4461c56c9b2d38778cd718be006f90eMike Stump    // PrimaryBase goes first.
2142effeca6b4461c56c9b2d38778cd718be006f90eMike Stump    if (PrimaryBase)
215eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump      LayoutBaseNonVirtually(PrimaryBase);
2163dee6efcad9ad56d14f7edd1c29924f0b876a7f9Mike Stump    LayoutNonVirtualBases(RD);
2173dee6efcad9ad56d14f7edd1c29924f0b876a7f9Mike Stump  }
21874cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson
219a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson  LayoutFields(D);
220bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
221b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson  NonVirtualSize = Size;
222b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson  NonVirtualAlignment = Alignment;
2233dee6efcad9ad56d14f7edd1c29924f0b876a7f9Mike Stump
224eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump  if (RD)
225eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump    LayoutVirtualBases(RD);
226eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump
227bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  // Finally, round the size of the total struct up to the alignment of the
228bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  // struct itself.
229bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  FinishLayout();
230bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson}
231bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
23293fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlssonvoid ASTRecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D,
23393fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson                                    const ObjCImplementationDecl *Impl) {
23493fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson  if (ObjCInterfaceDecl *SD = D->getSuperClass()) {
23593fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson    const ASTRecordLayout &SL = Ctx.getASTObjCInterfaceLayout(SD);
23693fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson
23793fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson    UpdateAlignment(SL.getAlignment());
23893fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson
23993fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson    // We start laying out ivars not at the end of the superclass
24093fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson    // structure, but at the next byte following the last field.
241243a68551ac9ec71bf341e062418e33eb4f286ffAnders Carlsson    Size = llvm::RoundUpToAlignment(SL.getDataSize(), 8);
24293fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson    NextOffset = Size;
24393fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson  }
24493fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson
245a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson  Packed = D->hasAttr<PackedAttr>();
246a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson
247a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson  // The #pragma pack attribute specifies the maximum field alignment.
248a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson  if (const PragmaPackAttr *PPA = D->getAttr<PragmaPackAttr>())
249a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson    MaxFieldAlignment = PPA->getAlignment();
25093fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson
25193fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson  if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
25293fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson    UpdateAlignment(AA->getAlignment());
25393fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson
25493fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson  // Layout each ivar sequentially.
25593fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson  llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
25693fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson  Ctx.ShallowCollectObjCIvars(D, Ivars, Impl);
25793fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson  for (unsigned i = 0, e = Ivars.size(); i != e; ++i)
25893fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson    LayoutField(Ivars[i]);
25993fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson
26093fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson  // Finally, round the size of the total struct up to the alignment of the
26193fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson  // struct itself.
26293fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson  FinishLayout();
26393fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson}
26493fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson
265a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlssonvoid ASTRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
266a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson  // Layout each field, for now, just sequentially, respecting alignment.  In
267a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson  // the future, this will need to be tweakable by targets.
268a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson  for (RecordDecl::field_iterator Field = D->field_begin(),
269a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson       FieldEnd = D->field_end(); Field != FieldEnd; ++Field)
270a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson    LayoutField(*Field);
271a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson}
272a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson
273bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlssonvoid ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) {
274a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson  bool FieldPacked = Packed;
275bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  uint64_t FieldOffset = IsUnion ? 0 : Size;
276bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  uint64_t FieldSize;
277bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  unsigned FieldAlign;
278bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
279a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson  FieldPacked |= D->hasAttr<PackedAttr>();
280bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
281bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  if (const Expr *BitWidthExpr = D->getBitWidth()) {
282bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    // TODO: Need to check this algorithm on other targets!
283bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    //       (tested on Linux-X86)
284bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    FieldSize = BitWidthExpr->EvaluateAsInt(Ctx).getZExtValue();
285bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
286bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType());
287bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    uint64_t TypeSize = FieldInfo.first;
288a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson
289bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    FieldAlign = FieldInfo.second;
290a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson
291a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson    if (FieldPacked)
292a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson      FieldAlign = 1;
293bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
294bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson      FieldAlign = std::max(FieldAlign, AA->getAlignment());
295a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson    // The maximum field alignment overrides the aligned attribute.
296a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson    if (MaxFieldAlignment)
297a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson      FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
298a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson
299bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    // Check if we need to add padding to give the field the correct
300bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    // alignment.
301bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)
302bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson      FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
303bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
304bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    // Padding members don't affect overall alignment
305bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    if (!D->getIdentifier())
306bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson      FieldAlign = 1;
307bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  } else {
308bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    if (D->getType()->isIncompleteArrayType()) {
309bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson      // This is a flexible array member; we can't directly
310bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson      // query getTypeInfo about these, so we figure it out here.
311bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson      // Flexible array members don't have any size, but they
312bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson      // have to be aligned appropriately for their element type.
313bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson      FieldSize = 0;
314bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson      const ArrayType* ATy = Ctx.getAsArrayType(D->getType());
315bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson      FieldAlign = Ctx.getTypeAlign(ATy->getElementType());
3166217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek    } else if (const ReferenceType *RT = D->getType()->getAs<ReferenceType>()) {
317bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson      unsigned AS = RT->getPointeeType().getAddressSpace();
318bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson      FieldSize = Ctx.Target.getPointerWidth(AS);
319bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson      FieldAlign = Ctx.Target.getPointerAlign(AS);
320bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    } else {
321bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson      std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType());
322bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson      FieldSize = FieldInfo.first;
323bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson      FieldAlign = FieldInfo.second;
324bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    }
325bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
326a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson    if (FieldPacked)
327a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson      FieldAlign = 8;
328bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
329bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson      FieldAlign = std::max(FieldAlign, AA->getAlignment());
330a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson    // The maximum field alignment overrides the aligned attribute.
331a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson    if (MaxFieldAlignment)
332a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson      FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
333bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
334bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    // Round up the current record size to the field's alignment boundary.
335bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
336bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  }
337bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
338bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  // Place this field at the current location.
339bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  FieldOffsets.push_back(FieldOffset);
340bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
341bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  // Reserve space for this field.
342bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  if (IsUnion)
343bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    Size = std::max(Size, FieldSize);
344bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  else
345bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    Size = FieldOffset + FieldSize;
346bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
347bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  // Remember the next available offset.
348bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  NextOffset = Size;
349bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
350bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  // Remember max struct/class alignment.
351bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  UpdateAlignment(FieldAlign);
352bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson}
353bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
354bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlssonvoid ASTRecordLayoutBuilder::FinishLayout() {
355bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  // In C++, records cannot be of size 0.
356bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  if (Ctx.getLangOptions().CPlusPlus && Size == 0)
357bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    Size = 8;
358bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  // Finally, round the size of the record up to the alignment of the
359bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  // record itself.
360bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  Size = (Size + (Alignment-1)) & ~(Alignment-1);
361bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson}
362bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
363bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlssonvoid ASTRecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) {
364bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  if (NewAlignment <= Alignment)
365bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson    return;
366bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
367bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  assert(llvm::isPowerOf2_32(NewAlignment && "Alignment not a power of 2"));
368bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
369bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  Alignment = NewAlignment;
370bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson}
371bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
372bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlssonconst ASTRecordLayout *
373bda4c1015e27ac82d31afb4519dd53586e61a51aAnders CarlssonASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
374bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson                                      const RecordDecl *D) {
375bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  ASTRecordLayoutBuilder Builder(Ctx);
376bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
377bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson  Builder.Layout(D);
378bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson
379b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson  if (!isa<CXXRecordDecl>(D))
380b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson    return new ASTRecordLayout(Builder.Size, Builder.Alignment, Builder.Size,
381b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson                               Builder.FieldOffsets.data(),
382b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson                               Builder.FieldOffsets.size());
383b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson
384b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson  // FIXME: This is not always correct. See the part about bitfields at
385b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson  // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
386b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson  // FIXME: IsPODForThePurposeOfLayout should be stored in the record layout.
387b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson  bool IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD();
38874cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson
389b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson  assert(Builder.Bases.size() == Builder.BaseOffsets.size() &&
390b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson         "Base offsets vector must be same size as bases vector!");
391b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson
392b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson  // FIXME: This should be done in FinalizeLayout.
39374cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson  uint64_t DataSize =
39474cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson    IsPODForThePurposeOfLayout ? Builder.Size : Builder.NextOffset;
395b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson  uint64_t NonVirtualSize =
396b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson    IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize;
39774cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson
39874cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson  return new ASTRecordLayout(Builder.Size, Builder.Alignment, DataSize,
39993fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson                             Builder.FieldOffsets.data(),
400b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson                             Builder.FieldOffsets.size(),
401b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson                             NonVirtualSize,
402b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson                             Builder.NonVirtualAlignment,
4036f376336138ea719e3c4757ae046a5768043b276Mike Stump                             Builder.PrimaryBase,
404928f1506eb38bb26a1284b876213a8f5244f6933Mike Stump                             Builder.PrimaryBaseWasVirtual,
405b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson                             Builder.Bases.data(),
406b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson                             Builder.BaseOffsets.data(),
407b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson                             Builder.Bases.size());
40893fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson}
40993fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson
41093fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlssonconst ASTRecordLayout *
41193fab9d67ca62e3e291803e5a1309473d6e00344Anders CarlssonASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
41293fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson                                      const ObjCInterfaceDecl *D,
41393fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson                                      const ObjCImplementationDecl *Impl) {
41493fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson  ASTRecordLayoutBuilder Builder(Ctx);
41593fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson
41693fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson  Builder.Layout(D, Impl);
41793fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson
41893fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson  return new ASTRecordLayout(Builder.Size, Builder.Alignment,
41993fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson                             Builder.NextOffset,
420bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson                             Builder.FieldOffsets.data(),
421bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson                             Builder.FieldOffsets.size());
422bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson}
423