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