RecordLayoutBuilder.cpp revision 9dc82d2193971ed57dc657dbd21249a2c57da376
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/Basic/TargetInfo.h" 186f376336138ea719e3c4757ae046a5768043b276Mike Stump#include <llvm/ADT/SmallSet.h> 19bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson#include <llvm/Support/MathExtras.h> 20bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 21bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlssonusing namespace clang; 22bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 231eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx) 24e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson : Ctx(Ctx), Size(0), Alignment(8), Packed(false), UnfilledBitsInLastByte(0), 25e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson MaxFieldAlignment(0), DataSize(0), IsUnion(false), NonVirtualSize(0), 26200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson NonVirtualAlignment(8), FirstNearlyEmptyVBase(0) { } 273dee6efcad9ad56d14f7edd1c29924f0b876a7f9Mike Stump 286f376336138ea719e3c4757ae046a5768043b276Mike Stump/// IsNearlyEmpty - Indicates when a class has a vtable pointer, but 296f376336138ea719e3c4757ae046a5768043b276Mike Stump/// no other data. 303f066522342538509cf0aa4f381503b43fbdb68bAnders Carlssonbool ASTRecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) const { 316f376336138ea719e3c4757ae046a5768043b276Mike Stump // FIXME: Audit the corners 326f376336138ea719e3c4757ae046a5768043b276Mike Stump if (!RD->isDynamicClass()) 336f376336138ea719e3c4757ae046a5768043b276Mike Stump return false; 346f376336138ea719e3c4757ae046a5768043b276Mike Stump const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD); 356f376336138ea719e3c4757ae046a5768043b276Mike Stump if (BaseInfo.getNonVirtualSize() == Ctx.Target.getPointerWidth(0)) 366f376336138ea719e3c4757ae046a5768043b276Mike Stump return true; 376f376336138ea719e3c4757ae046a5768043b276Mike Stump return false; 386f376336138ea719e3c4757ae046a5768043b276Mike Stump} 396f376336138ea719e3c4757ae046a5768043b276Mike Stump 403f066522342538509cf0aa4f381503b43fbdb68bAnders Carlssonvoid ASTRecordLayoutBuilder::IdentifyPrimaryBases(const CXXRecordDecl *RD) { 41ce2009ab2f59894dbcc847e25e05abe78c296e95Anders Carlsson const ASTRecordLayout::PrimaryBaseInfo &BaseInfo = 42ce2009ab2f59894dbcc847e25e05abe78c296e95Anders Carlsson Ctx.getASTRecordLayout(RD).getPrimaryBaseInfo(); 433f066522342538509cf0aa4f381503b43fbdb68bAnders Carlsson 443f066522342538509cf0aa4f381503b43fbdb68bAnders Carlsson // If the record has a primary base class that is virtual, add it to the set 453f066522342538509cf0aa4f381503b43fbdb68bAnders Carlsson // of primary bases. 46261fba6cf57a09a1f1d0c4a4c4856aaa62753242Anders Carlsson if (BaseInfo.isVirtual()) 47261fba6cf57a09a1f1d0c4a4c4856aaa62753242Anders Carlsson IndirectPrimaryBases.insert(BaseInfo.getBase()); 483f066522342538509cf0aa4f381503b43fbdb68bAnders Carlsson 493f066522342538509cf0aa4f381503b43fbdb68bAnders Carlsson // Now traverse all bases and find primary bases for them. 506f376336138ea719e3c4757ae046a5768043b276Mike Stump for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), 516f376336138ea719e3c4757ae046a5768043b276Mike Stump e = RD->bases_end(); i != e; ++i) { 529994a34f6cf842721ba7723edc0b9036229fe387Sebastian Redl assert(!i->getType()->isDependentType() && 539994a34f6cf842721ba7723edc0b9036229fe387Sebastian Redl "Cannot layout class with dependent bases."); 541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *Base = 5549520944c688a9d5fc78d0c2af544b825873477bMike Stump cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); 563f066522342538509cf0aa4f381503b43fbdb68bAnders Carlsson 5749520944c688a9d5fc78d0c2af544b825873477bMike Stump // Only bases with virtual bases participate in computing the 5849520944c688a9d5fc78d0c2af544b825873477bMike Stump // indirect primary virtual base classes. 594ef980984fd0e131fca3f9e6ba15e8a79cabf88cMike Stump if (Base->getNumVBases()) 603f066522342538509cf0aa4f381503b43fbdb68bAnders Carlsson IdentifyPrimaryBases(Base); 616f376336138ea719e3c4757ae046a5768043b276Mike Stump } 626f376336138ea719e3c4757ae046a5768043b276Mike Stump} 636f376336138ea719e3c4757ae046a5768043b276Mike Stump 643f066522342538509cf0aa4f381503b43fbdb68bAnders Carlssonvoid 65200c5c2d9488165626925235ff918e3d744d785aAnders CarlssonASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) { 66200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson 67d76264e0b20470267249660ab947197cf6d6e31fMike Stump for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), 68d76264e0b20470267249660ab947197cf6d6e31fMike Stump e = RD->bases_end(); i != e; ++i) { 699994a34f6cf842721ba7723edc0b9036229fe387Sebastian Redl assert(!i->getType()->isDependentType() && 709994a34f6cf842721ba7723edc0b9036229fe387Sebastian Redl "Cannot layout class with dependent bases."); 711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *Base = 72d76264e0b20470267249660ab947197cf6d6e31fMike Stump cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); 73d76264e0b20470267249660ab947197cf6d6e31fMike Stump if (!i->isVirtual()) { 74200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson SelectPrimaryVBase(Base); 75261fba6cf57a09a1f1d0c4a4c4856aaa62753242Anders Carlsson if (PrimaryBase.getBase()) 76d76264e0b20470267249660ab947197cf6d6e31fMike Stump return; 77d76264e0b20470267249660ab947197cf6d6e31fMike Stump continue; 78d76264e0b20470267249660ab947197cf6d6e31fMike Stump } 79d76264e0b20470267249660ab947197cf6d6e31fMike Stump if (IsNearlyEmpty(Base)) { 80200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson // Is this the first nearly empty primary virtual base? 81200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson if (!FirstNearlyEmptyVBase) 82200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson FirstNearlyEmptyVBase = Base; 83200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson 843f066522342538509cf0aa4f381503b43fbdb68bAnders Carlsson if (!IndirectPrimaryBases.count(Base)) { 85200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson PrimaryBase = ASTRecordLayout::PrimaryBaseInfo(Base, 86200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson /*IsVirtual=*/true); 87d76264e0b20470267249660ab947197cf6d6e31fMike Stump return; 88d76264e0b20470267249660ab947197cf6d6e31fMike Stump } 89d76264e0b20470267249660ab947197cf6d6e31fMike Stump } 90200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson 9194ba380b820cde3fb9d97d5f07ac709ebbb6ac1eZhongxing Xu assert(i->isVirtual()); 92200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson SelectPrimaryVBase(Base); 9394ba380b820cde3fb9d97d5f07ac709ebbb6ac1eZhongxing Xu if (PrimaryBase.getBase()) 9494ba380b820cde3fb9d97d5f07ac709ebbb6ac1eZhongxing Xu return; 95d76264e0b20470267249660ab947197cf6d6e31fMike Stump } 96d76264e0b20470267249660ab947197cf6d6e31fMike Stump} 97d76264e0b20470267249660ab947197cf6d6e31fMike Stump 98200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson/// DeterminePrimaryBase - Determine the primary base of the given class. 99200c5c2d9488165626925235ff918e3d744d785aAnders Carlssonvoid ASTRecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) { 100200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson // If the class isn't dynamic, it won't have a primary base. 101200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson if (!RD->isDynamicClass()) 102200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson return; 103200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson 1043f066522342538509cf0aa4f381503b43fbdb68bAnders Carlsson // Compute all the primary virtual bases for all of our direct and 1050880e75541899bc1cdd73c50eb549110b5916c59Mike Stump // indirect bases, and record all their primary virtual base classes. 1060880e75541899bc1cdd73c50eb549110b5916c59Mike Stump for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), 1070880e75541899bc1cdd73c50eb549110b5916c59Mike Stump e = RD->bases_end(); i != e; ++i) { 1089994a34f6cf842721ba7723edc0b9036229fe387Sebastian Redl assert(!i->getType()->isDependentType() && 109200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson "Cannot lay out class with dependent bases."); 1101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *Base = 1110880e75541899bc1cdd73c50eb549110b5916c59Mike Stump cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); 1123f066522342538509cf0aa4f381503b43fbdb68bAnders Carlsson IdentifyPrimaryBases(Base); 1130880e75541899bc1cdd73c50eb549110b5916c59Mike Stump } 1140880e75541899bc1cdd73c50eb549110b5916c59Mike Stump 1153f066522342538509cf0aa4f381503b43fbdb68bAnders Carlsson // If the record has a dynamic base class, attempt to choose a primary base 1163f066522342538509cf0aa4f381503b43fbdb68bAnders Carlsson // class. It is the first (in direct base class order) non-virtual dynamic 1173f066522342538509cf0aa4f381503b43fbdb68bAnders Carlsson // base class, if one exists. 1186f376336138ea719e3c4757ae046a5768043b276Mike Stump for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), 1196f376336138ea719e3c4757ae046a5768043b276Mike Stump e = RD->bases_end(); i != e; ++i) { 120ce2009ab2f59894dbcc847e25e05abe78c296e95Anders Carlsson // Ignore virtual bases. 121ce2009ab2f59894dbcc847e25e05abe78c296e95Anders Carlsson if (i->isVirtual()) 122ce2009ab2f59894dbcc847e25e05abe78c296e95Anders Carlsson continue; 123ce2009ab2f59894dbcc847e25e05abe78c296e95Anders Carlsson 124ce2009ab2f59894dbcc847e25e05abe78c296e95Anders Carlsson const CXXRecordDecl *Base = 125ce2009ab2f59894dbcc847e25e05abe78c296e95Anders Carlsson cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); 126ce2009ab2f59894dbcc847e25e05abe78c296e95Anders Carlsson 127ce2009ab2f59894dbcc847e25e05abe78c296e95Anders Carlsson if (Base->isDynamicClass()) { 128ce2009ab2f59894dbcc847e25e05abe78c296e95Anders Carlsson // We found it. 129ce2009ab2f59894dbcc847e25e05abe78c296e95Anders Carlsson PrimaryBase = ASTRecordLayout::PrimaryBaseInfo(Base, /*IsVirtual=*/false); 130ce2009ab2f59894dbcc847e25e05abe78c296e95Anders Carlsson return; 1316f376336138ea719e3c4757ae046a5768043b276Mike Stump } 1326f376336138ea719e3c4757ae046a5768043b276Mike Stump } 1336f376336138ea719e3c4757ae046a5768043b276Mike Stump 1346f376336138ea719e3c4757ae046a5768043b276Mike Stump // Otherwise, it is the first nearly empty virtual base that is not an 13549520944c688a9d5fc78d0c2af544b825873477bMike Stump // indirect primary virtual base class, if one exists. 136200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson if (RD->getNumVBases() != 0) { 137200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson SelectPrimaryVBase(RD); 138200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson if (PrimaryBase.getBase()) 139200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson return; 140200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson } 1416f376336138ea719e3c4757ae046a5768043b276Mike Stump 142200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson // Otherwise, it is the first nearly empty virtual base that is not an 143200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson // indirect primary virtual base class, if one exists. 144200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson if (FirstNearlyEmptyVBase) { 145200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson PrimaryBase = 146200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson ASTRecordLayout::PrimaryBaseInfo(FirstNearlyEmptyVBase, /*IsVirtual=*/true); 1476f376336138ea719e3c4757ae046a5768043b276Mike Stump return; 148200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson } 1493f066522342538509cf0aa4f381503b43fbdb68bAnders Carlsson 150200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson // Otherwise there is no primary base class. 151200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson assert(!PrimaryBase.getBase() && "Should not get here with a primary base!"); 152200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson 153200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson // Allocate the virtual table pointer at offset zero. 154200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson assert(DataSize == 0 && "Vtable pointer must be at offset zero!"); 155200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson 156200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson // Update the size. 157200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson Size += Ctx.Target.getPointerWidth(0); 158200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson DataSize = Size; 159200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson 160200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson // Update the alignment. 161200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson UpdateAlignment(Ctx.Target.getPointerAlign(0)); 1626f376336138ea719e3c4757ae046a5768043b276Mike Stump} 1636f376336138ea719e3c4757ae046a5768043b276Mike Stump 164968db3364611a475909b5e76969d2f5472e65597Mike Stumpuint64_t ASTRecordLayoutBuilder::getBaseOffset(const CXXRecordDecl *Base) { 165968db3364611a475909b5e76969d2f5472e65597Mike Stump for (size_t i = 0; i < Bases.size(); ++i) { 166968db3364611a475909b5e76969d2f5472e65597Mike Stump if (Bases[i].first == Base) 167968db3364611a475909b5e76969d2f5472e65597Mike Stump return Bases[i].second; 168968db3364611a475909b5e76969d2f5472e65597Mike Stump } 169968db3364611a475909b5e76969d2f5472e65597Mike Stump for (size_t i = 0; i < VBases.size(); ++i) { 170968db3364611a475909b5e76969d2f5472e65597Mike Stump if (VBases[i].first == Base) 171968db3364611a475909b5e76969d2f5472e65597Mike Stump return VBases[i].second; 172968db3364611a475909b5e76969d2f5472e65597Mike Stump } 173968db3364611a475909b5e76969d2f5472e65597Mike Stump assert(0 && "missing base"); 174968db3364611a475909b5e76969d2f5472e65597Mike Stump return 0; 175968db3364611a475909b5e76969d2f5472e65597Mike Stump} 176968db3364611a475909b5e76969d2f5472e65597Mike Stump 177e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlssonvoid 178e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders CarlssonASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { 179200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson // First, determine the primary base class. 180200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson DeterminePrimaryBase(RD); 181200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson 182200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson // If we have a primary base class, lay it out. 183200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson if (const CXXRecordDecl *Base = PrimaryBase.getBase()) { 184200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson if (PrimaryBase.isVirtual()) { 185200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson // We have a virtual primary base, insert it as an indirect primary base. 186200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson IndirectPrimaryBases.insert(Base); 187200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson 188200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson LayoutVirtualBase(Base); 189200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson } else 190200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson LayoutNonVirtualBase(Base); 191200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson } 192200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson 193200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson // Now lay out the non-virtual bases. 194200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), 195200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson E = RD->bases_end(); I != E; ++I) { 196200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson 197200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson // Ignore virtual bases. 198200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson if (I->isVirtual()) 199200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson continue; 200200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson 201200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson const CXXRecordDecl *Base = 202200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); 203200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson 204200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson // Skip the primary base. 205200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson if (Base == PrimaryBase.getBase() && !PrimaryBase.isVirtual()) 206200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson continue; 207200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson 208200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson // Lay out the base. 209200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson LayoutNonVirtualBase(Base); 210e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson } 211e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson} 212e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson 213e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlssonvoid ASTRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *RD) { 214e3bdbee47059839d5e24acab5ee7b925285f573eAnders Carlsson // Layout the base. 215e3bdbee47059839d5e24acab5ee7b925285f573eAnders Carlsson uint64_t Offset = LayoutBase(RD); 216e3bdbee47059839d5e24acab5ee7b925285f573eAnders Carlsson 217e3bdbee47059839d5e24acab5ee7b925285f573eAnders Carlsson // Add its base class offset. 218e3bdbee47059839d5e24acab5ee7b925285f573eAnders Carlsson Bases.push_back(std::make_pair(RD, Offset)); 219e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson} 220968db3364611a475909b5e76969d2f5472e65597Mike Stump 221968db3364611a475909b5e76969d2f5472e65597Mike Stumpvoid ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *Class, 222968db3364611a475909b5e76969d2f5472e65597Mike Stump const CXXRecordDecl *RD, 223fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump const CXXRecordDecl *PB, 224968db3364611a475909b5e76969d2f5472e65597Mike Stump uint64_t Offset, 2259dc82d2193971ed57dc657dbd21249a2c57da376Anders Carlsson llvm::SmallSet<const CXXRecordDecl*, 32> &mark) { 2264ef980984fd0e131fca3f9e6ba15e8a79cabf88cMike Stump for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), 2274ef980984fd0e131fca3f9e6ba15e8a79cabf88cMike Stump e = RD->bases_end(); i != e; ++i) { 2289994a34f6cf842721ba7723edc0b9036229fe387Sebastian Redl assert(!i->getType()->isDependentType() && 2299994a34f6cf842721ba7723edc0b9036229fe387Sebastian Redl "Cannot layout class with dependent bases."); 2301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *Base = 231eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); 232968db3364611a475909b5e76969d2f5472e65597Mike Stump uint64_t BaseOffset = Offset; 233276b9f1d814f4f6551cc3000590759a34185d6daMike Stump if (i->isVirtual()) { 234fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump if (Base == PB) { 235fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump // Only lay things out once. 236fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump if (mark.count(Base)) 237fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump continue; 238fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump // Mark it so we don't lay it out twice. 239fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump mark.insert(Base); 2409dc82d2193971ed57dc657dbd21249a2c57da376Anders Carlsson assert (IndirectPrimaryBases.count(Base) && "IndirectPrimary was wrong"); 241e4feb834fb1a6b03291ed78fd32d13729b5a3c4aAnders Carlsson VBases.push_back(std::make_pair(Base, Offset)); 2429dc82d2193971ed57dc657dbd21249a2c57da376Anders Carlsson } else if (IndirectPrimaryBases.count(Base)) { 243fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump // Someone else will eventually lay this out. 244fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump ; 245fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump } else { 246fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump // Only lay things out once. 247fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump if (mark.count(Base)) 248fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump continue; 249fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump // Mark it so we don't lay it out twice. 250fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump mark.insert(Base); 251276b9f1d814f4f6551cc3000590759a34185d6daMike Stump LayoutVirtualBase(Base); 252e4feb834fb1a6b03291ed78fd32d13729b5a3c4aAnders Carlsson BaseOffset = VBases.back().second; 253fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump } 254968db3364611a475909b5e76969d2f5472e65597Mike Stump } else { 255968db3364611a475909b5e76969d2f5472e65597Mike Stump if (RD == Class) 256968db3364611a475909b5e76969d2f5472e65597Mike Stump BaseOffset = getBaseOffset(Base); 257968db3364611a475909b5e76969d2f5472e65597Mike Stump else { 25837acf5a57f87abdbb4ac6115c5f3f09295ec2dc3Mike Stump const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); 259968db3364611a475909b5e76969d2f5472e65597Mike Stump BaseOffset = Offset + Layout.getBaseClassOffset(Base); 260968db3364611a475909b5e76969d2f5472e65597Mike Stump } 261fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump } 262968db3364611a475909b5e76969d2f5472e65597Mike Stump 263fe3010d09cec5cd06e31a3d57fe188a04d9bfa17Mike Stump if (Base->getNumVBases()) { 264ce2009ab2f59894dbcc847e25e05abe78c296e95Anders Carlsson const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Base); 265261fba6cf57a09a1f1d0c4a4c4856aaa62753242Anders Carlsson const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBaseInfo().getBase(); 2669dc82d2193971ed57dc657dbd21249a2c57da376Anders Carlsson LayoutVirtualBases(Class, Base, PrimaryBase, BaseOffset, mark); 2674ef980984fd0e131fca3f9e6ba15e8a79cabf88cMike Stump } 268eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump } 269eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump} 270eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump 271e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlssonvoid ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) { 272e3bdbee47059839d5e24acab5ee7b925285f573eAnders Carlsson // Layout the base. 273e3bdbee47059839d5e24acab5ee7b925285f573eAnders Carlsson uint64_t Offset = LayoutBase(RD); 274e3bdbee47059839d5e24acab5ee7b925285f573eAnders Carlsson 275e3bdbee47059839d5e24acab5ee7b925285f573eAnders Carlsson // Add its base class offset. 276e3bdbee47059839d5e24acab5ee7b925285f573eAnders Carlsson VBases.push_back(std::make_pair(RD, Offset)); 277e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson} 278e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson 279e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlssonuint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) { 280e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD); 281e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson 282e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson // If we have an empty base class, try to place it at offset 0. 283e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson if (RD->isEmpty() && canPlaceRecordAtOffset(RD, 0)) { 284e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson // We were able to place the class at offset 0. 285e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson UpdateEmptyClassOffsets(RD, 0); 286e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson 287e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson Size = std::max(Size, BaseInfo.getSize()); 288e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson 289e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson return 0; 290e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson } 291e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson 292e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson unsigned BaseAlign = BaseInfo.getNonVirtualAlign(); 293e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson 294e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson // Round up the current record size to the base's alignment boundary. 295e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson uint64_t Offset = llvm::RoundUpToAlignment(DataSize, BaseAlign); 296e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson 297e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson // Try to place the base. 298e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson while (true) { 299e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson if (canPlaceRecordAtOffset(RD, Offset)) 300e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson break; 301e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson 302e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson Offset += BaseAlign; 303e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson } 304e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson 305e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson if (!RD->isEmpty()) { 306e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson // Update the data size. 307e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson DataSize = Offset + BaseInfo.getNonVirtualSize(); 308e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson 309e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson Size = std::max(Size, DataSize); 310e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson } else 311e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson Size = std::max(Size, Offset + BaseInfo.getSize()); 312e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson 313e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson // Remember max struct/class alignment. 314e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson UpdateAlignment(BaseAlign); 315e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson 316e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson UpdateEmptyClassOffsets(RD, Offset); 317e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson return Offset; 318e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson} 319e239b9d5da3bdc722d29c276b261c136ca9f4eaaAnders Carlsson 3209606149722bedfc48fc56cafc58de1139aef481dAnders Carlssonbool ASTRecordLayoutBuilder::canPlaceRecordAtOffset(const CXXRecordDecl *RD, 3219606149722bedfc48fc56cafc58de1139aef481dAnders Carlsson uint64_t Offset) const { 3221345bd2b093e78620c32f5148b1279ed290188e8Anders Carlsson // Look for an empty class with the same type at the same offset. 3231345bd2b093e78620c32f5148b1279ed290188e8Anders Carlsson for (EmptyClassOffsetsTy::const_iterator I = 3241345bd2b093e78620c32f5148b1279ed290188e8Anders Carlsson EmptyClassOffsets.lower_bound(Offset), 3251345bd2b093e78620c32f5148b1279ed290188e8Anders Carlsson E = EmptyClassOffsets.upper_bound(Offset); I != E; ++I) { 3261345bd2b093e78620c32f5148b1279ed290188e8Anders Carlsson 3271345bd2b093e78620c32f5148b1279ed290188e8Anders Carlsson if (I->second == RD) 3281345bd2b093e78620c32f5148b1279ed290188e8Anders Carlsson return false; 3291345bd2b093e78620c32f5148b1279ed290188e8Anders Carlsson } 3301345bd2b093e78620c32f5148b1279ed290188e8Anders Carlsson 331ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson const ASTRecordLayout &Info = Ctx.getASTRecordLayout(RD); 332ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson 333ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson // Check bases. 334ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), 335ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson E = RD->bases_end(); I != E; ++I) { 3369994a34f6cf842721ba7723edc0b9036229fe387Sebastian Redl assert(!I->getType()->isDependentType() && 3379994a34f6cf842721ba7723edc0b9036229fe387Sebastian Redl "Cannot layout class with dependent bases."); 338ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson if (I->isVirtual()) 339ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson continue; 340ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson 341ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson const CXXRecordDecl *Base = 342ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); 343ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson 344ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson uint64_t BaseClassOffset = Info.getBaseClassOffset(Base); 345ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson 346ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson if (!canPlaceRecordAtOffset(Base, Offset + BaseClassOffset)) 347ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson return false; 348ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson } 349ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson 3501eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson // Check fields. 3511eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson unsigned FieldNo = 0; 3521eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); 3531eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson I != E; ++I, ++FieldNo) { 3541eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson const FieldDecl *FD = *I; 3551eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson 3561eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson uint64_t FieldOffset = Info.getFieldOffset(FieldNo); 3571eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson 3581eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson if (!canPlaceFieldAtOffset(FD, Offset + FieldOffset)) 3591eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson return false; 3601eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson } 3611eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson 362ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson // FIXME: virtual bases. 3639606149722bedfc48fc56cafc58de1139aef481dAnders Carlsson return true; 3649606149722bedfc48fc56cafc58de1139aef481dAnders Carlsson} 3659606149722bedfc48fc56cafc58de1139aef481dAnders Carlsson 3666026504302763f74102592602b392cecd5ced3aeAnders Carlssonbool ASTRecordLayoutBuilder::canPlaceFieldAtOffset(const FieldDecl *FD, 3676026504302763f74102592602b392cecd5ced3aeAnders Carlsson uint64_t Offset) const { 368fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson QualType T = FD->getType(); 369fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson if (const RecordType *RT = T->getAs<RecordType>()) { 3706026504302763f74102592602b392cecd5ced3aeAnders Carlsson if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) 3716026504302763f74102592602b392cecd5ced3aeAnders Carlsson return canPlaceRecordAtOffset(RD, Offset); 3726026504302763f74102592602b392cecd5ced3aeAnders Carlsson } 3736026504302763f74102592602b392cecd5ced3aeAnders Carlsson 374fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson if (const ConstantArrayType *AT = Ctx.getAsConstantArrayType(T)) { 375fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson QualType ElemTy = Ctx.getBaseElementType(AT); 376fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson const RecordType *RT = ElemTy->getAs<RecordType>(); 377fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson if (!RT) 378fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson return true; 379fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); 380fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson if (!RD) 381fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson return true; 382fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson 383fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson const ASTRecordLayout &Info = Ctx.getASTRecordLayout(RD); 384fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson 385fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson uint64_t NumElements = Ctx.getConstantArrayElementCount(AT); 386968db3364611a475909b5e76969d2f5472e65597Mike Stump uint64_t ElementOffset = Offset; 387fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson for (uint64_t I = 0; I != NumElements; ++I) { 388fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson if (!canPlaceRecordAtOffset(RD, ElementOffset)) 389fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson return false; 390fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson 391fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson ElementOffset += Info.getSize(); 392fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson } 393fbbce49c116aa8c8c7c0707cb6048b55f70461a9Anders Carlsson } 3946026504302763f74102592602b392cecd5ced3aeAnders Carlsson 3956026504302763f74102592602b392cecd5ced3aeAnders Carlsson return true; 3966026504302763f74102592602b392cecd5ced3aeAnders Carlsson} 3976026504302763f74102592602b392cecd5ced3aeAnders Carlsson 3989606149722bedfc48fc56cafc58de1139aef481dAnders Carlssonvoid ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD, 3999606149722bedfc48fc56cafc58de1139aef481dAnders Carlsson uint64_t Offset) { 4001345bd2b093e78620c32f5148b1279ed290188e8Anders Carlsson if (RD->isEmpty()) 4011345bd2b093e78620c32f5148b1279ed290188e8Anders Carlsson EmptyClassOffsets.insert(std::make_pair(Offset, RD)); 402ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson 403ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson const ASTRecordLayout &Info = Ctx.getASTRecordLayout(RD); 404ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson 405ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson // Update bases. 406ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), 407ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson E = RD->bases_end(); I != E; ++I) { 4089994a34f6cf842721ba7723edc0b9036229fe387Sebastian Redl assert(!I->getType()->isDependentType() && 4099994a34f6cf842721ba7723edc0b9036229fe387Sebastian Redl "Cannot layout class with dependent bases."); 410ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson if (I->isVirtual()) 411ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson continue; 412ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson 413ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson const CXXRecordDecl *Base = 414ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); 4151345bd2b093e78620c32f5148b1279ed290188e8Anders Carlsson 416ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson uint64_t BaseClassOffset = Info.getBaseClassOffset(Base); 417ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson UpdateEmptyClassOffsets(Base, Offset + BaseClassOffset); 418ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson } 419ffbdefc7a24c01a0f77425423278774796a3aa53Anders Carlsson 4201eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson // Update fields. 4211eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson unsigned FieldNo = 0; 4221eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); 4231eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson I != E; ++I, ++FieldNo) { 4241eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson const FieldDecl *FD = *I; 4251eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson 4261eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson uint64_t FieldOffset = Info.getFieldOffset(FieldNo); 4271eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson UpdateEmptyClassOffsets(FD, Offset + FieldOffset); 4281eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson } 4291eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson 4301eca99b815e531eba63233c0558af0dc971387aaAnders Carlsson // FIXME: Update virtual bases. 4319606149722bedfc48fc56cafc58de1139aef481dAnders Carlsson} 4329606149722bedfc48fc56cafc58de1139aef481dAnders Carlsson 433a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlssonvoid 434a4c6081abd5582515b110bdcb576b4b85536467bAnders CarlssonASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const FieldDecl *FD, 435a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson uint64_t Offset) { 436a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson QualType T = FD->getType(); 437a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson 438a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson if (const RecordType *RT = T->getAs<RecordType>()) { 439a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { 440a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson UpdateEmptyClassOffsets(RD, Offset); 441a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson return; 442a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson } 443a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson } 444a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson 445a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson if (const ConstantArrayType *AT = Ctx.getAsConstantArrayType(T)) { 446a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson QualType ElemTy = Ctx.getBaseElementType(AT); 447a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson const RecordType *RT = ElemTy->getAs<RecordType>(); 448a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson if (!RT) 449a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson return; 450a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); 451a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson if (!RD) 452a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson return; 453a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson 454a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson const ASTRecordLayout &Info = Ctx.getASTRecordLayout(RD); 455a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson 456a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson uint64_t NumElements = Ctx.getConstantArrayElementCount(AT); 457968db3364611a475909b5e76969d2f5472e65597Mike Stump uint64_t ElementOffset = Offset; 458a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson 459a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson for (uint64_t I = 0; I != NumElements; ++I) { 460a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson UpdateEmptyClassOffsets(RD, ElementOffset); 461a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson ElementOffset += Info.getSize(); 462a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson } 463a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson } 464a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson} 465a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson 466bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlssonvoid ASTRecordLayoutBuilder::Layout(const RecordDecl *D) { 467bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson IsUnion = D->isUnion(); 468a860e755f1f9f071b6a6a2f96128a6a258f5c331Anders Carlsson 469a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson Packed = D->hasAttr<PackedAttr>(); 470a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson 471a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson // The #pragma pack attribute specifies the maximum field alignment. 472a860e755f1f9f071b6a6a2f96128a6a258f5c331Anders Carlsson if (const PragmaPackAttr *PPA = D->getAttr<PragmaPackAttr>()) 473a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson MaxFieldAlignment = PPA->getAlignment(); 4741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 475bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) 476bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt UpdateAlignment(AA->getMaxAlignment()); 47774cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson 478276b9f1d814f4f6551cc3000590759a34185d6daMike Stump // If this is a C++ class, lay out the vtable and the non-virtual bases. 479eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D); 480200c5c2d9488165626925235ff918e3d744d785aAnders Carlsson if (RD) 4813dee6efcad9ad56d14f7edd1c29924f0b876a7f9Mike Stump LayoutNonVirtualBases(RD); 48274cbe226207fd101623638dadfa7fbada04ff2a6Anders Carlsson 483a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson LayoutFields(D); 4841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 485b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson NonVirtualSize = Size; 486b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson NonVirtualAlignment = Alignment; 4873dee6efcad9ad56d14f7edd1c29924f0b876a7f9Mike Stump 488276b9f1d814f4f6551cc3000590759a34185d6daMike Stump if (RD) { 489276b9f1d814f4f6551cc3000590759a34185d6daMike Stump llvm::SmallSet<const CXXRecordDecl*, 32> mark; 4909dc82d2193971ed57dc657dbd21249a2c57da376Anders Carlsson LayoutVirtualBases(RD, RD, PrimaryBase.getBase(), 0, mark); 491276b9f1d814f4f6551cc3000590759a34185d6daMike Stump } 492eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump 493bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // Finally, round the size of the total struct up to the alignment of the 494bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // struct itself. 495bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FinishLayout(); 496bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson} 497bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 49811062e11236b7bc689dad150e8b490fd6b063ec3Fariborz Jahanian// FIXME. Impl is no longer needed. 49993fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlssonvoid ASTRecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D, 50093fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson const ObjCImplementationDecl *Impl) { 50193fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson if (ObjCInterfaceDecl *SD = D->getSuperClass()) { 50293fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson const ASTRecordLayout &SL = Ctx.getASTObjCInterfaceLayout(SD); 50393fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson 50493fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson UpdateAlignment(SL.getAlignment()); 5051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 50693fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson // We start laying out ivars not at the end of the superclass 50793fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson // structure, but at the next byte following the last field. 508243a68551ac9ec71bf341e062418e33eb4f286ffAnders Carlsson Size = llvm::RoundUpToAlignment(SL.getDataSize(), 8); 509a223935e5cf82e939e1ca1da4111d63025a04e39Anders Carlsson DataSize = Size; 51093fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson } 5111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 512a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson Packed = D->hasAttr<PackedAttr>(); 5131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 514a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson // The #pragma pack attribute specifies the maximum field alignment. 515a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson if (const PragmaPackAttr *PPA = D->getAttr<PragmaPackAttr>()) 516a5dd722bdf2f74a1a249fe6661d96a7236aee0f0Anders Carlsson MaxFieldAlignment = PPA->getAlignment(); 5171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 51893fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) 519bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt UpdateAlignment(AA->getMaxAlignment()); 52093fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson // Layout each ivar sequentially. 52193fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; 52211062e11236b7bc689dad150e8b490fd6b063ec3Fariborz Jahanian Ctx.ShallowCollectObjCIvars(D, Ivars); 52393fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson for (unsigned i = 0, e = Ivars.size(); i != e; ++i) 52493fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson LayoutField(Ivars[i]); 5251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 52693fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson // Finally, round the size of the total struct up to the alignment of the 52793fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson // struct itself. 52893fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson FinishLayout(); 52993fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson} 53093fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson 531a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlssonvoid ASTRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { 532a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson // Layout each field, for now, just sequentially, respecting alignment. In 533a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson // the future, this will need to be tweakable by targets. 5341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (RecordDecl::field_iterator Field = D->field_begin(), 535a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson FieldEnd = D->field_end(); Field != FieldEnd; ++Field) 536a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson LayoutField(*Field); 537a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson} 538a2df41c107d3c5f5bff2d090fab77734e0da735dAnders Carlsson 53942dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlssonvoid ASTRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { 54042dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson bool FieldPacked = Packed || D->hasAttr<PackedAttr>(); 541e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson uint64_t FieldOffset = IsUnion ? 0 : (DataSize - UnfilledBitsInLastByte); 54242dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson uint64_t FieldSize = D->getBitWidth()->EvaluateAsInt(Ctx).getZExtValue(); 54342dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson 54442dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType()); 54542dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson uint64_t TypeSize = FieldInfo.first; 54642dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson unsigned FieldAlign = FieldInfo.second; 54742dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson 54842dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson if (FieldPacked) 54942dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson FieldAlign = 1; 55042dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) 55142dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson FieldAlign = std::max(FieldAlign, AA->getMaxAlignment()); 5521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 55342dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson // The maximum field alignment overrides the aligned attribute. 55442dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson if (MaxFieldAlignment) 55542dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson FieldAlign = std::min(FieldAlign, MaxFieldAlignment); 55642dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson 55742dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson // Check if we need to add padding to give the field the correct 55842dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson // alignment. 55942dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize) 56042dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1); 56142dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson 56242dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson // Padding members don't affect overall alignment 56342dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson if (!D->getIdentifier()) 56442dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson FieldAlign = 1; 56542dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson 56642dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson // Place this field at the current location. 56742dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson FieldOffsets.push_back(FieldOffset); 56842dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson 569e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson // Update DataSize to include the last byte containing (part of) the bitfield. 570e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson if (IsUnion) { 571e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson // FIXME: I think FieldSize should be TypeSize here. 572e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson DataSize = std::max(DataSize, FieldSize); 573e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson } else { 574e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson uint64_t NewSizeInBits = FieldOffset + FieldSize; 575e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson 576e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson DataSize = llvm::RoundUpToAlignment(NewSizeInBits, 8); 577e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson UnfilledBitsInLastByte = DataSize - NewSizeInBits; 578e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson } 57942dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson 580e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson // Update the size. 581e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson Size = std::max(Size, DataSize); 58242dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson 58342dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson // Remember max struct/class alignment. 58442dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson UpdateAlignment(FieldAlign); 58542dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson} 5861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 58742dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlssonvoid ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) { 58842dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson if (D->isBitField()) { 58942dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson LayoutBitField(D); 59042dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson return; 59142dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson } 5921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 593e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson // Reset the unfilled bits. 594e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson UnfilledBitsInLastByte = 0; 595e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9Anders Carlsson 59642dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson bool FieldPacked = Packed || D->hasAttr<PackedAttr>(); 59742dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson uint64_t FieldOffset = IsUnion ? 0 : DataSize; 59842dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson uint64_t FieldSize; 59942dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson unsigned FieldAlign; 60042dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson 60142dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson if (D->getType()->isIncompleteArrayType()) { 60242dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson // This is a flexible array member; we can't directly 60342dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson // query getTypeInfo about these, so we figure it out here. 60442dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson // Flexible array members don't have any size, but they 60542dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson // have to be aligned appropriately for their element type. 60642dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson FieldSize = 0; 60742dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson const ArrayType* ATy = Ctx.getAsArrayType(D->getType()); 60842dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson FieldAlign = Ctx.getTypeAlign(ATy->getElementType()); 60942dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson } else if (const ReferenceType *RT = D->getType()->getAs<ReferenceType>()) { 61042dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson unsigned AS = RT->getPointeeType().getAddressSpace(); 61142dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson FieldSize = Ctx.Target.getPointerWidth(AS); 61242dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson FieldAlign = Ctx.Target.getPointerAlign(AS); 61342dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson } else { 614bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType()); 61542dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson FieldSize = FieldInfo.first; 616bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldAlign = FieldInfo.second; 61742dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson } 6181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 61942dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson if (FieldPacked) 62042dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson FieldAlign = 8; 62142dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) 62242dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson FieldAlign = std::max(FieldAlign, AA->getMaxAlignment()); 6231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 62442dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson // The maximum field alignment overrides the aligned attribute. 62542dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson if (MaxFieldAlignment) 62642dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson FieldAlign = std::min(FieldAlign, MaxFieldAlignment); 6271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 62842dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson // Round up the current record size to the field's alignment boundary. 62942dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); 63042dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson 63142dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson if (!IsUnion) { 63242dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson while (true) { 63342dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson // Check if we can place the field at this offset. 63442dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson if (canPlaceFieldAtOffset(D, FieldOffset)) 63542dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson break; 636a4c6081abd5582515b110bdcb576b4b85536467bAnders Carlsson 63742dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson // We couldn't place the field at the offset. Try again at a new offset. 63842dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson FieldOffset += FieldAlign; 6396026504302763f74102592602b392cecd5ced3aeAnders Carlsson } 64042dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson 64142dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson UpdateEmptyClassOffsets(D, FieldOffset); 642bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson } 64342dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson 644bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // Place this field at the current location. 645bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson FieldOffsets.push_back(FieldOffset); 6461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 647bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // Reserve space for this field. 648bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (IsUnion) 649bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson Size = std::max(Size, FieldSize); 650bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson else 651bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson Size = FieldOffset + FieldSize; 6521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 653a223935e5cf82e939e1ca1da4111d63025a04e39Anders Carlsson // Update the data size. 654a223935e5cf82e939e1ca1da4111d63025a04e39Anders Carlsson DataSize = Size; 6551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 656bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // Remember max struct/class alignment. 657bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson UpdateAlignment(FieldAlign); 658bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson} 659bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 660bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlssonvoid ASTRecordLayoutBuilder::FinishLayout() { 661bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // In C++, records cannot be of size 0. 662bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (Ctx.getLangOptions().CPlusPlus && Size == 0) 663bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson Size = 8; 664bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // Finally, round the size of the record up to the alignment of the 665bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson // record itself. 66642dbcc4d8f0c483693befc76f37ca6dc4e0844e1Anders Carlsson Size = llvm::RoundUpToAlignment(Size, Alignment); 667bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson} 668bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 669bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlssonvoid ASTRecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) { 670bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson if (NewAlignment <= Alignment) 671bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson return; 6721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 673bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson assert(llvm::isPowerOf2_32(NewAlignment && "Alignment not a power of 2")); 6741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 675bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson Alignment = NewAlignment; 676bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson} 6771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 678bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlssonconst ASTRecordLayout * 6791eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, 680bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson const RecordDecl *D) { 681bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson ASTRecordLayoutBuilder Builder(Ctx); 682bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 683bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson Builder.Layout(D); 684bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson 685b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson if (!isa<CXXRecordDecl>(D)) 686503524acc73f2f8280080ca0d200377406001b65Ted Kremenek return new (Ctx) ASTRecordLayout(Ctx, Builder.Size, Builder.Alignment, 687503524acc73f2f8280080ca0d200377406001b65Ted Kremenek Builder.Size, 688503524acc73f2f8280080ca0d200377406001b65Ted Kremenek Builder.FieldOffsets.data(), 689503524acc73f2f8280080ca0d200377406001b65Ted Kremenek Builder.FieldOffsets.size()); 6901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 691b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson // FIXME: This is not always correct. See the part about bitfields at 692b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info. 693b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson // FIXME: IsPODForThePurposeOfLayout should be stored in the record layout. 694b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson bool IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD(); 6951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 696b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson // FIXME: This should be done in FinalizeLayout. 6971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump uint64_t DataSize = 698a223935e5cf82e939e1ca1da4111d63025a04e39Anders Carlsson IsPODForThePurposeOfLayout ? Builder.Size : Builder.DataSize; 6991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump uint64_t NonVirtualSize = 700b2fafd4978166114c54748a73738d8b2c3a37e2bAnders Carlsson IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize; 7011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 702503524acc73f2f8280080ca0d200377406001b65Ted Kremenek return new (Ctx) ASTRecordLayout(Ctx, Builder.Size, Builder.Alignment, 703503524acc73f2f8280080ca0d200377406001b65Ted Kremenek DataSize, Builder.FieldOffsets.data(), 704503524acc73f2f8280080ca0d200377406001b65Ted Kremenek Builder.FieldOffsets.size(), 705503524acc73f2f8280080ca0d200377406001b65Ted Kremenek NonVirtualSize, 706503524acc73f2f8280080ca0d200377406001b65Ted Kremenek Builder.NonVirtualAlignment, 707503524acc73f2f8280080ca0d200377406001b65Ted Kremenek Builder.PrimaryBase, 708503524acc73f2f8280080ca0d200377406001b65Ted Kremenek Builder.Bases.data(), 709503524acc73f2f8280080ca0d200377406001b65Ted Kremenek Builder.Bases.size(), 710503524acc73f2f8280080ca0d200377406001b65Ted Kremenek Builder.VBases.data(), 711503524acc73f2f8280080ca0d200377406001b65Ted Kremenek Builder.VBases.size()); 71293fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson} 71393fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson 71493fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlssonconst ASTRecordLayout * 71593fab9d67ca62e3e291803e5a1309473d6e00344Anders CarlssonASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, 71693fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson const ObjCInterfaceDecl *D, 71793fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson const ObjCImplementationDecl *Impl) { 71893fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson ASTRecordLayoutBuilder Builder(Ctx); 7191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 72093fab9d67ca62e3e291803e5a1309473d6e00344Anders Carlsson Builder.Layout(D, Impl); 7211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 722503524acc73f2f8280080ca0d200377406001b65Ted Kremenek return new (Ctx) ASTRecordLayout(Ctx, Builder.Size, Builder.Alignment, 723503524acc73f2f8280080ca0d200377406001b65Ted Kremenek Builder.DataSize, 724503524acc73f2f8280080ca0d200377406001b65Ted Kremenek Builder.FieldOffsets.data(), 725503524acc73f2f8280080ca0d200377406001b65Ted Kremenek Builder.FieldOffsets.size()); 726bda4c1015e27ac82d31afb4519dd53586e61a51aAnders Carlsson} 727f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson 728f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlssonconst CXXMethodDecl * 729f53df2398e07d13be9962b95aebc19b31706fa33Anders CarlssonASTRecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) { 730f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson assert(RD->isDynamicClass() && "Class does not have any virtual methods!"); 731f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson 732f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson // If a class isnt' polymorphic it doesn't have a key function. 733f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson if (!RD->isPolymorphic()) 734f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson return 0; 73561eab8872168af6eb1e0047a82901096cf145e27Eli Friedman 73661eab8872168af6eb1e0047a82901096cf145e27Eli Friedman // A class inside an anonymous namespace doesn't have a key function. (Or 73761eab8872168af6eb1e0047a82901096cf145e27Eli Friedman // at least, there's no point to assigning a key function to such a class; 73861eab8872168af6eb1e0047a82901096cf145e27Eli Friedman // this doesn't affect the ABI.) 73961eab8872168af6eb1e0047a82901096cf145e27Eli Friedman if (RD->isInAnonymousNamespace()) 74061eab8872168af6eb1e0047a82901096cf145e27Eli Friedman return 0; 74161eab8872168af6eb1e0047a82901096cf145e27Eli Friedman 742f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson for (CXXRecordDecl::method_iterator I = RD->method_begin(), 743f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson E = RD->method_end(); I != E; ++I) { 744f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson const CXXMethodDecl *MD = *I; 745f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson 746f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson if (!MD->isVirtual()) 747f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson continue; 748f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson 749f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson if (MD->isPure()) 750f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson continue; 75161eab8872168af6eb1e0047a82901096cf145e27Eli Friedman 752f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson // Ignore implicit member functions, they are always marked as inline, but 753f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson // they don't have a body until they're defined. 754f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson if (MD->isImplicit()) 755f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson continue; 756bd6d6197fcfc98356ea60e816365eb0648b69556Douglas Gregor 757bd6d6197fcfc98356ea60e816365eb0648b69556Douglas Gregor if (MD->isInlineSpecified()) 758bd6d6197fcfc98356ea60e816365eb0648b69556Douglas Gregor continue; 759f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson 760f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson if (MD->hasInlineBody()) 761f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson continue; 762f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson 763f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson // We found it. 764f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson return MD; 765f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson } 766f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson 767f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson return 0; 768f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson} 769f53df2398e07d13be9962b95aebc19b31706fa33Anders Carlsson 770