zcov: / lib/AST/RecordLayoutBuilder.cpp


Files: 1 Branches Taken: 91.3% 230 / 252
Generated: 2010-02-10 01:31 Branches Executed: 98.4% 248 / 252
Line Coverage: 97.6% 367 / 376


Programs: 2 Runs 3018


       1                 : //=== ASTRecordLayoutBuilder.cpp - Helper class for building record layouts ==//
       2                 : //
       3                 : //                     The LLVM Compiler Infrastructure
       4                 : //
       5                 : // This file is distributed under the University of Illinois Open Source
       6                 : // License. See LICENSE.TXT for details.
       7                 : //
       8                 : //===----------------------------------------------------------------------===//
       9                 : 
      10                 : #include "RecordLayoutBuilder.h"
      11                 : 
      12                 : #include "clang/AST/Attr.h"
      13                 : #include "clang/AST/Decl.h"
      14                 : #include "clang/AST/DeclCXX.h"
      15                 : #include "clang/AST/DeclObjC.h"
      16                 : #include "clang/AST/Expr.h"
      17                 : #include "clang/Basic/TargetInfo.h"
      18                 : #include <llvm/ADT/SmallSet.h>
      19                 : #include <llvm/Support/MathExtras.h>
      20                 : 
      21                 : using namespace clang;
      22                 : 
      23             1800: ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx)
      24                 :   : Ctx(Ctx), Size(0), Alignment(8), Packed(false), UnfilledBitsInLastByte(0),
      25                 :   MaxFieldAlignment(0), DataSize(0), IsUnion(false), NonVirtualSize(0), 
      26             1800:   NonVirtualAlignment(8) { }
      27                 : 
      28                 : /// LayoutVtable - Lay out the vtable and set PrimaryBase.
      29              862: void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) {
                      509: branch 1 taken
                      353: branch 2 taken
      30              862:   if (!RD->isDynamicClass()) {
      31                 :     // There is no primary base in this case.
      32              509:     return;
      33                 :   }
      34                 : 
      35              353:   SelectPrimaryBase(RD);
                      216: branch 1 taken
                      137: branch 2 taken
      36              353:   if (!PrimaryBase.getBase()) {
      37              216:     int AS = 0;
      38              216:     UpdateAlignment(Ctx.Target.getPointerAlign(AS));
      39              216:     Size += Ctx.Target.getPointerWidth(AS);
      40              216:     DataSize = Size;
      41                 :   }
      42                 : }
      43                 : 
      44                 : void
      45              862: ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
                      412: branch 1 taken
                      862: branch 2 taken
      46             2136:   for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
      47              862:        e = RD->bases_end(); i != e; ++i) {
                      257: branch 1 taken
                      155: branch 2 taken
      48              412:     if (!i->isVirtual()) {
      49                 :       assert(!i->getType()->isDependentType() &&
                      257: branch 3 taken
                        0: branch 4 not taken
      50              257:              "Cannot layout class with dependent bases.");
      51                 :       const CXXRecordDecl *Base =
      52              257:         cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
      53                 :       // Skip the PrimaryBase here, as it is laid down first.
                       91: branch 1 taken
                      166: branch 2 taken
                        0: branch 4 not taken
                       91: branch 5 taken
                      166: branch 6 taken
                       91: branch 7 taken
      54              348:       if (Base != PrimaryBase.getBase() || PrimaryBase.isVirtual())
      55              166:         LayoutBaseNonVirtually(Base, false);
      56                 :     }
      57                 :   }
      58              862: }
      59                 : 
      60                 : // Helper routines related to the abi definition from:
      61                 : //   http://www.codesourcery.com/public/cxx-abi/abi.html
      62                 : //
      63                 : /// IsNearlyEmpty - Indicates when a class has a vtable pointer, but
      64                 : /// no other data.
      65              151: bool ASTRecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) const {
      66                 :   // FIXME: Audit the corners
                       27: branch 1 taken
                      124: branch 2 taken
      67              151:   if (!RD->isDynamicClass())
      68               27:     return false;
      69              124:   const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD);
                       47: branch 2 taken
                       77: branch 3 taken
      70              124:   if (BaseInfo.getNonVirtualSize() == Ctx.Target.getPointerWidth(0))
      71               47:     return true;
      72               77:   return false;
      73                 : }
      74                 : 
      75              341: void ASTRecordLayoutBuilder::IdentifyPrimaryBases(const CXXRecordDecl *RD) {
      76                 :   const ASTRecordLayout::PrimaryBaseInfo &BaseInfo = 
      77              341:     Ctx.getASTRecordLayout(RD).getPrimaryBaseInfo();
      78                 :   
      79                 :   // If the record has a primary base class that is virtual, add it to the set
      80                 :   // of primary bases.
                       42: branch 1 taken
                      299: branch 2 taken
      81              341:   if (BaseInfo.isVirtual())
      82               42:     IndirectPrimaryBases.insert(BaseInfo.getBase());
      83                 :   
      84                 :   // Now traverse all bases and find primary bases for them.
                      240: branch 1 taken
                      341: branch 2 taken
      85              922:   for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
      86              341:        e = RD->bases_end(); i != e; ++i) {
      87                 :     assert(!i->getType()->isDependentType() &&
                      240: branch 3 taken
                        0: branch 4 not taken
      88              240:            "Cannot layout class with dependent bases.");
      89                 :     const CXXRecordDecl *Base =
      90              240:       cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
      91                 :     
      92                 :     // Only bases with virtual bases participate in computing the
      93                 :     // indirect primary virtual base classes.
                       46: branch 1 taken
                      194: branch 2 taken
      94              240:     if (Base->getNumVBases())
      95               46:       IdentifyPrimaryBases(Base);
      96                 :   }
      97              341: }
      98                 : 
      99                 : void
     100                 : ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD,
     101              257:                                            const CXXRecordDecl *&FirstPrimary) {
                      207: branch 1 taken
                      209: branch 2 taken
     102              673:   for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
     103              257:          e = RD->bases_end(); i != e; ++i) {
     104                 :     assert(!i->getType()->isDependentType() &&
                      207: branch 3 taken
                        0: branch 4 not taken
     105              207:            "Cannot layout class with dependent bases.");
     106                 :     const CXXRecordDecl *Base =
     107              207:       cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
                       56: branch 1 taken
                      151: branch 2 taken
     108              207:     if (!i->isVirtual()) {
     109               56:       SelectPrimaryVBase(Base, FirstPrimary);
                        0: branch 1 not taken
                       56: branch 2 taken
     110               56:       if (PrimaryBase.getBase())
     111                0:         return;
     112               56:       continue;
     113                 :     }
                       47: branch 1 taken
                      104: branch 2 taken
     114              151:     if (IsNearlyEmpty(Base)) {
                       46: branch 0 taken
                        1: branch 1 taken
     115               47:       if (FirstPrimary==0)
     116               46:         FirstPrimary = Base;
                       46: branch 1 taken
                        1: branch 2 taken
     117               47:       if (!IndirectPrimaryBases.count(Base)) {
     118               46:         setPrimaryBase(Base, /*IsVirtual=*/true);
     119               46:         return;
     120                 :       }
     121                 :     }
                      105: branch 1 taken
                        0: branch 2 not taken
     122              105:     if (i->isVirtual()) {
     123              105:       SelectPrimaryVBase(Base, FirstPrimary);
                        2: branch 1 taken
                      103: branch 2 taken
     124              105:       if (PrimaryBase.getBase())
     125                2:         return;
     126                 :     }
     127                 :   }
     128                 : }
     129                 : 
     130                 : /// SelectPrimaryBase - Selects the primary base for the given class and
     131                 : /// record that with setPrimaryBase.  We also calculate the IndirectPrimaries.
     132              353: void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) {
     133                 :   // Compute all the primary virtual bases for all of our direct and
     134                 :   // indirect bases, and record all their primary virtual base classes.
                      295: branch 1 taken
                      353: branch 2 taken
     135             1649:   for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
     136              353:        e = RD->bases_end(); i != e; ++i) {
     137                 :     assert(!i->getType()->isDependentType() &&
                      295: branch 3 taken
                        0: branch 4 not taken
     138              295:            "Cannot layout class with dependent bases.");
     139                 :     const CXXRecordDecl *Base =
     140              295:       cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
     141              295:     IdentifyPrimaryBases(Base);
     142                 :   }
     143                 : 
     144                 :   // If the record has a dynamic base class, attempt to choose a primary base 
     145                 :   // class. It is the first (in direct base class order) non-virtual dynamic 
     146                 :   // base class, if one exists.
                      241: branch 1 taken
                      262: branch 2 taken
     147              856:   for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
     148              353:        e = RD->bases_end(); i != e; ++i) {
     149                 :     // Ignore virtual bases.
                      108: branch 1 taken
                      133: branch 2 taken
     150              241:     if (i->isVirtual())
     151              133:       continue;
     152                 :     
     153                 :     const CXXRecordDecl *Base =
     154              108:       cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
     155                 : 
                       91: branch 1 taken
                       17: branch 2 taken
     156              108:     if (Base->isDynamicClass()) {
     157                 :       // We found it.
     158               91:       PrimaryBase = ASTRecordLayout::PrimaryBaseInfo(Base, /*IsVirtual=*/false);
     159               91:       return;
     160                 :     }
     161                 :   }
     162                 : 
     163                 :   // Otherwise, it is the first nearly empty virtual base that is not an
     164                 :   // indirect primary virtual base class, if one exists.
     165                 : 
     166                 :   // If we have no virtual bases at this point, bail out as the searching below
     167                 :   // is expensive.
                      166: branch 1 taken
                       96: branch 2 taken
     168              262:   if (RD->getNumVBases() == 0)
     169              166:     return;
     170                 :   
     171                 :   // Then we can search for the first nearly empty virtual base itself.
     172               96:   const CXXRecordDecl *FirstPrimary = 0;
     173               96:   SelectPrimaryVBase(RD, FirstPrimary);
     174                 : 
     175                 :   // Otherwise if is the first nearly empty virtual base, if one exists,
     176                 :   // otherwise there is no primary base class.
                       50: branch 1 taken
                       46: branch 2 taken
     177               96:   if (!PrimaryBase.getBase())
     178               50:     setPrimaryBase(FirstPrimary, /*IsVirtual=*/true);
     179                 : }
     180                 : 
     181              207: void ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) {
     182              207:   LayoutBaseNonVirtually(RD, true);
     183              207: }
     184                 : 
     185              257: uint64_t ASTRecordLayoutBuilder::getBaseOffset(const CXXRecordDecl *Base) {
                      338: branch 1 taken
                        0: branch 2 not taken
     186              338:   for (size_t i = 0; i < Bases.size(); ++i) {
                      257: branch 1 taken
                       81: branch 2 taken
     187              338:     if (Bases[i].first == Base)
     188              257:       return Bases[i].second;
     189                 :   }
                        0: branch 1 not taken
                        0: branch 2 not taken
     190                0:   for (size_t i = 0; i < VBases.size(); ++i) {
                        0: branch 1 not taken
                        0: branch 2 not taken
     191                0:     if (VBases[i].first == Base)
     192                0:       return VBases[i].second;
     193                 :   }
     194                0:   assert(0 && "missing base");
     195                 :   return 0;
     196                 : }
     197                 : 
     198                 : 
     199                 : void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *Class,
     200                 :                                                 const CXXRecordDecl *RD,
     201                 :                                                 const CXXRecordDecl *PB,
     202                 :                                                 uint64_t Offset,
     203                 :                                  llvm::SmallSet<const CXXRecordDecl*, 32> &mark,
     204              998:                     llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary) {
                      616: branch 1 taken
                      998: branch 2 taken
     205             2612:   for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
     206              998:          e = RD->bases_end(); i != e; ++i) {
     207                 :     assert(!i->getType()->isDependentType() &&
                      616: branch 3 taken
                        0: branch 4 not taken
     208              616:            "Cannot layout class with dependent bases.");
     209                 :     const CXXRecordDecl *Base =
     210              616:       cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
     211              616:     uint64_t BaseOffset = Offset;
                      316: branch 1 taken
                      300: branch 2 taken
     212              616:     if (i->isVirtual()) {
                       86: branch 0 taken
                      230: branch 1 taken
     213              316:       if (Base == PB) {
     214                 :         // Only lay things out once.
                        0: branch 1 not taken
                       86: branch 2 taken
     215               86:         if (mark.count(Base))
     216                0:           continue;
     217                 :         // Mark it so we don't lay it out twice.
     218               86:         mark.insert(Base);
                       86: branch 1 taken
                        0: branch 2 not taken
     219               86:         assert (IndirectPrimary.count(Base) && "IndirectPrimary was wrong");
     220               86:         VBases.push_back(std::make_pair(Base, Offset));
                      227: branch 1 taken
                        3: branch 2 taken
     221              230:       } else if (IndirectPrimary.count(Base)) {
     222                 :         // Someone else will eventually lay this out.
     223                 :         ;
     224                 :       } else {
     225                 :         // Only lay things out once.
                       20: branch 1 taken
                      207: branch 2 taken
     226              227:         if (mark.count(Base))
     227               20:           continue;
     228                 :         // Mark it so we don't lay it out twice.
     229              207:         mark.insert(Base);
     230              207:         LayoutVirtualBase(Base);
     231              207:         BaseOffset = VBases.back().second;
     232                 :       }
     233                 :     } else {
                      257: branch 0 taken
                       43: branch 1 taken
     234              300:       if (RD == Class)
     235              257:         BaseOffset = getBaseOffset(Base);
     236                 :       else {
     237               43:         const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
     238               43:         BaseOffset = Offset + Layout.getBaseClassOffset(Base);
     239                 :       }
     240                 :     }
     241                 :     
                      136: branch 1 taken
                      460: branch 2 taken
     242              596:     if (Base->getNumVBases()) {
     243              136:       const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Base);
     244              136:       const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBaseInfo().getBase();
     245                 :       LayoutVirtualBases(Class, Base, PrimaryBase, BaseOffset, mark, 
     246              136:                          IndirectPrimary);
     247                 :     }
     248                 :   }
     249              998: }
     250                 : 
     251                 : bool ASTRecordLayoutBuilder::canPlaceRecordAtOffset(const CXXRecordDecl *RD, 
     252             1165:                                                     uint64_t Offset) const {
     253                 :   // Look for an empty class with the same type at the same offset.
                       92: branch 2 taken
                     1137: branch 3 taken
     254             1229:   for (EmptyClassOffsetsTy::const_iterator I = 
     255             1165:         EmptyClassOffsets.lower_bound(Offset), 
     256             1165:        E = EmptyClassOffsets.upper_bound(Offset); I != E; ++I) {
     257                 :     
                       28: branch 1 taken
                       64: branch 2 taken
     258               92:     if (I->second == RD)
     259               28:       return false;
     260                 :   }
     261                 :   
     262             1137:   const ASTRecordLayout &Info = Ctx.getASTRecordLayout(RD);
     263                 : 
     264                 :   // Check bases.
                      456: branch 1 taken
                     1097: branch 2 taken
     265             2690:   for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
     266             1137:        E = RD->bases_end(); I != E; ++I) {
     267                 :     assert(!I->getType()->isDependentType() &&
                      456: branch 3 taken
                        0: branch 4 not taken
     268              456:            "Cannot layout class with dependent bases.");
                      313: branch 1 taken
                      143: branch 2 taken
     269              456:     if (I->isVirtual())
     270              143:       continue;
     271                 :     
     272                 :     const CXXRecordDecl *Base =
     273              313:       cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
     274                 : 
     275              313:     uint64_t BaseClassOffset = Info.getBaseClassOffset(Base);
     276                 :     
                       40: branch 1 taken
                      273: branch 2 taken
     277              313:     if (!canPlaceRecordAtOffset(Base, Offset + BaseClassOffset))
     278               40:       return false;
     279                 :   }
     280                 :   
     281                 :   // Check fields.
     282             1097:   unsigned FieldNo = 0;
                      805: branch 4 taken
                     1096: branch 5 taken
     283             1901:   for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); 
     284                 :        I != E; ++I, ++FieldNo) {
     285              805:     const FieldDecl *FD = *I;
     286                 :     
     287              805:     uint64_t FieldOffset = Info.getFieldOffset(FieldNo);
     288                 :     
                        1: branch 1 taken
                      804: branch 2 taken
     289              805:     if (!canPlaceFieldAtOffset(FD, Offset + FieldOffset))
     290                1:       return false;
     291                 :   }
     292                 : 
     293                 :   // FIXME: virtual bases.
     294             1096:   return true;
     295                 : }
     296                 : 
     297                 : bool ASTRecordLayoutBuilder::canPlaceFieldAtOffset(const FieldDecl *FD, 
     298             2948:                                                    uint64_t Offset) const {
     299             2948:   QualType T = FD->getType();
                      175: branch 2 taken
                     2773: branch 3 taken
     300             2948:   if (const RecordType *RT = T->getAs<RecordType>()) {
                      112: branch 2 taken
                       63: branch 3 taken
     301              175:     if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
     302              112:       return canPlaceRecordAtOffset(RD, Offset);
     303                 :   }
     304                 :   
                      162: branch 1 taken
                     2674: branch 2 taken
     305             2836:   if (const ConstantArrayType *AT = Ctx.getAsConstantArrayType(T)) {
     306              162:     QualType ElemTy = Ctx.getBaseElementType(AT);
     307              162:     const RecordType *RT = ElemTy->getAs<RecordType>();
                      127: branch 0 taken
                       35: branch 1 taken
     308              162:     if (!RT)
     309              127:       return true;
     310               35:     const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
                        9: branch 0 taken
                       26: branch 1 taken
     311               35:     if (!RD)
     312                9:       return true;
     313                 :     
     314               26:     const ASTRecordLayout &Info = Ctx.getASTRecordLayout(RD);
     315                 : 
     316               26:     uint64_t NumElements = Ctx.getConstantArrayElementCount(AT);
     317               26:     uint64_t ElementOffset = Offset;
                      204: branch 0 taken
                       25: branch 1 taken
     318              229:     for (uint64_t I = 0; I != NumElements; ++I) {
                        1: branch 1 taken
                      203: branch 2 taken
     319              204:       if (!canPlaceRecordAtOffset(RD, ElementOffset))
     320                1:         return false;
     321                 :       
     322              203:       ElementOffset += Info.getSize();
     323                 :     }
     324                 :   }
     325                 :   
     326             2699:   return true;
     327                 : }
     328                 : 
     329                 : void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD,
     330             1080:                                                      uint64_t Offset) {
                      303: branch 1 taken
                      777: branch 2 taken
     331             1080:   if (RD->isEmpty())
     332              303:     EmptyClassOffsets.insert(std::make_pair(Offset, RD));
     333                 :   
     334             1080:   const ASTRecordLayout &Info = Ctx.getASTRecordLayout(RD);
     335                 : 
     336                 :   // Update bases.
                      400: branch 1 taken
                     1080: branch 2 taken
     337             2560:   for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
     338             1080:        E = RD->bases_end(); I != E; ++I) {
     339                 :     assert(!I->getType()->isDependentType() &&
                      400: branch 3 taken
                        0: branch 4 not taken
     340              400:            "Cannot layout class with dependent bases.");
                      143: branch 1 taken
                      257: branch 2 taken
     341              400:     if (I->isVirtual())
     342              143:       continue;
     343                 :     
     344                 :     const CXXRecordDecl *Base =
     345              257:       cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
     346                 :     
     347              257:     uint64_t BaseClassOffset = Info.getBaseClassOffset(Base);
     348              257:     UpdateEmptyClassOffsets(Base, Offset + BaseClassOffset);
     349                 :   }
     350                 :   
     351                 :   // Update fields.
     352             1080:   unsigned FieldNo = 0;
                      804: branch 4 taken
                     1080: branch 5 taken
     353             1884:   for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); 
     354                 :        I != E; ++I, ++FieldNo) {
     355              804:     const FieldDecl *FD = *I;
     356                 :     
     357              804:     uint64_t FieldOffset = Info.getFieldOffset(FieldNo);
     358              804:     UpdateEmptyClassOffsets(FD, Offset + FieldOffset);
     359                 :   }
     360                 :   
     361                 :   // FIXME: Update virtual bases.
     362             1080: }
     363                 : 
     364                 : void
     365                 : ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const FieldDecl *FD, 
     366             2945:                                                 uint64_t Offset) {
     367             2945:   QualType T = FD->getType();
     368                 : 
                      173: branch 2 taken
                     2772: branch 3 taken
     369             2945:   if (const RecordType *RT = T->getAs<RecordType>()) {
                      110: branch 2 taken
                       63: branch 3 taken
     370              173:     if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
     371              110:       UpdateEmptyClassOffsets(RD, Offset);
     372              110:       return;
     373                 :     }
     374                 :   }
     375                 :   
                      161: branch 1 taken
                     2674: branch 2 taken
     376             2835:   if (const ConstantArrayType *AT = Ctx.getAsConstantArrayType(T)) {
     377              161:     QualType ElemTy = Ctx.getBaseElementType(AT);
     378              161:     const RecordType *RT = ElemTy->getAs<RecordType>();
                      127: branch 0 taken
                       34: branch 1 taken
     379              161:     if (!RT)
     380              127:       return;
     381               34:     const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
                        9: branch 0 taken
                       25: branch 1 taken
     382               34:     if (!RD)
     383                9:       return;
     384                 :     
     385               25:     const ASTRecordLayout &Info = Ctx.getASTRecordLayout(RD);
     386                 : 
     387               25:     uint64_t NumElements = Ctx.getConstantArrayElementCount(AT);
     388               25:     uint64_t ElementOffset = Offset;
     389                 : 
                      203: branch 0 taken
                       25: branch 1 taken
     390              228:     for (uint64_t I = 0; I != NumElements; ++I) {
     391              203:       UpdateEmptyClassOffsets(RD, ElementOffset);
     392              203:       ElementOffset += Info.getSize();
     393                 :     }
     394                 :   }
     395                 : }
     396                 : 
     397              510: uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) {
     398              510:   const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD);
     399                 : 
     400                 :   // If we have an empty base class, try to place it at offset 0.
                       95: branch 1 taken
                      415: branch 2 taken
                       81: branch 4 taken
                       14: branch 5 taken
                       81: branch 6 taken
                      429: branch 7 taken
     401              510:   if (RD->isEmpty() && canPlaceRecordAtOffset(RD, 0)) {
     402                 :     // We were able to place the class at offset 0.
     403               81:     UpdateEmptyClassOffsets(RD, 0);
     404                 : 
     405               81:     Size = std::max(Size, BaseInfo.getSize());
     406                 : 
     407               81:     return 0;
     408                 :   }
     409                 :   
     410              429:   unsigned BaseAlign = BaseInfo.getNonVirtualAlign();
     411                 :   
     412                 :   // Round up the current record size to the base's alignment boundary.
     413              429:   uint64_t Offset = llvm::RoundUpToAlignment(DataSize, BaseAlign);
     414                 :   
     415                 :   // Try to place the base.
     416               12:   while (true) {
                       12: branch 1 taken
                      429: branch 2 taken
     417              441:     if (canPlaceRecordAtOffset(RD, Offset))
     418              429:       break;
     419                 :     
     420               12:     Offset += BaseAlign;
     421                 :   }
     422                 : 
                      415: branch 1 taken
                       14: branch 2 taken
     423              429:   if (!RD->isEmpty()) {
     424                 :     // Update the data size.
     425              415:     DataSize = Offset + BaseInfo.getNonVirtualSize();
     426                 : 
     427              415:     Size = std::max(Size, DataSize);
     428                 :   } else
     429               14:     Size = std::max(Size, Offset + BaseInfo.getSize());
     430                 : 
     431                 :   // Remember max struct/class alignment.
     432              429:   UpdateAlignment(BaseAlign);
     433                 : 
     434              429:   UpdateEmptyClassOffsets(RD, Offset);
     435              429:   return Offset;
     436                 : }
     437                 : 
     438                 : void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD,
     439              510:   bool IsVirtualBase) {
     440                 :   // Layout the base.
     441              510:   uint64_t Offset = LayoutBase(RD);
     442                 : 
     443                 :   // Add base class offsets.
                      253: branch 0 taken
                      257: branch 1 taken
     444              510:   if (IsVirtualBase) 
     445              253:     VBases.push_back(std::make_pair(RD, Offset));
     446                 :   else
     447              257:     Bases.push_back(std::make_pair(RD, Offset));
     448              510: }
     449                 : 
     450             1598: void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
     451             1598:   IsUnion = D->isUnion();
     452                 : 
     453             1598:   Packed = D->hasAttr<PackedAttr>();
     454                 : 
     455                 :   // The #pragma pack attribute specifies the maximum field alignment.
                       24: branch 1 taken
                     1574: branch 2 taken
     456             1598:   if (const PragmaPackAttr *PPA = D->getAttr<PragmaPackAttr>())
     457               24:     MaxFieldAlignment = PPA->getAlignment();
     458                 : 
                        5: branch 1 taken
                     1593: branch 2 taken
     459             1598:   if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
     460                5:     UpdateAlignment(AA->getMaxAlignment());
     461                 : 
     462                 :   // If this is a C++ class, lay out the vtable and the non-virtual bases.
     463             1598:   const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D);
                      862: branch 0 taken
                      736: branch 1 taken
     464             1598:   if (RD) {
     465              862:     LayoutVtable(RD);
     466                 :     // PrimaryBase goes first.
                      137: branch 1 taken
                      725: branch 2 taken
     467              862:     if (PrimaryBase.getBase()) {
                       46: branch 1 taken
                       91: branch 2 taken
     468              137:       if (PrimaryBase.isVirtual())
     469               46:         IndirectPrimaryBases.insert(PrimaryBase.getBase());
     470              137:       LayoutBaseNonVirtually(PrimaryBase.getBase(), PrimaryBase.isVirtual());
     471                 :     }
     472              862:     LayoutNonVirtualBases(RD);
     473                 :   }
     474                 : 
     475             1598:   LayoutFields(D);
     476                 : 
     477             1598:   NonVirtualSize = Size;
     478             1598:   NonVirtualAlignment = Alignment;
     479                 : 
                      862: branch 0 taken
                      736: branch 1 taken
     480             1598:   if (RD) {
     481              862:     llvm::SmallSet<const CXXRecordDecl*, 32> mark;
     482                 :     LayoutVirtualBases(RD, RD, PrimaryBase.getBase(), 
     483              862:                        0, mark, IndirectPrimaryBases);
     484                 :   }
     485                 : 
     486                 :   // Finally, round the size of the total struct up to the alignment of the
     487                 :   // struct itself.
     488             1598:   FinishLayout();
     489             1598: }
     490                 : 
     491                 : void ASTRecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D,
     492              202:                                     const ObjCImplementationDecl *Impl) {
                       73: branch 1 taken
                      129: branch 2 taken
     493              202:   if (ObjCInterfaceDecl *SD = D->getSuperClass()) {
     494               73:     const ASTRecordLayout &SL = Ctx.getASTObjCInterfaceLayout(SD);
     495                 : 
     496               73:     UpdateAlignment(SL.getAlignment());
     497                 : 
     498                 :     // We start laying out ivars not at the end of the superclass
     499                 :     // structure, but at the next byte following the last field.
     500               73:     Size = llvm::RoundUpToAlignment(SL.getDataSize(), 8);
     501               73:     DataSize = Size;
     502                 :   }
     503                 : 
     504              202:   Packed = D->hasAttr<PackedAttr>();
     505                 : 
     506                 :   // The #pragma pack attribute specifies the maximum field alignment.
                        0: branch 1 not taken
                      202: branch 2 taken
     507              202:   if (const PragmaPackAttr *PPA = D->getAttr<PragmaPackAttr>())
     508                0:     MaxFieldAlignment = PPA->getAlignment();
     509                 : 
                        0: branch 1 not taken
                      202: branch 2 taken
     510              202:   if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
     511                0:     UpdateAlignment(AA->getMaxAlignment());
     512                 : 
     513                 :   // Layout each ivar sequentially.
     514              202:   llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
     515              202:   Ctx.ShallowCollectObjCIvars(D, Ivars, Impl);
                      261: branch 1 taken
                      202: branch 2 taken
     516              463:   for (unsigned i = 0, e = Ivars.size(); i != e; ++i)
     517              261:     LayoutField(Ivars[i]);
     518                 : 
     519                 :   // Finally, round the size of the total struct up to the alignment of the
     520                 :   // struct itself.
     521              202:   FinishLayout();
     522              202: }
     523                 : 
     524             1598: void ASTRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
     525                 :   // Layout each field, for now, just sequentially, respecting alignment.  In
     526                 :   // the future, this will need to be tweakable by targets.
                     2181: branch 3 taken
                     1598: branch 4 taken
     527             5377:   for (RecordDecl::field_iterator Field = D->field_begin(),
     528             1598:        FieldEnd = D->field_end(); Field != FieldEnd; ++Field)
     529             2181:     LayoutField(*Field);
     530             1598: }
     531                 : 
     532              206: void ASTRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
                      202: branch 0 taken
                        4: branch 1 taken
                        3: branch 3 taken
                      199: branch 4 taken
     533              206:   bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
                        5: branch 0 taken
                      201: branch 1 taken
     534              206:   uint64_t FieldOffset = IsUnion ? 0 : (DataSize - UnfilledBitsInLastByte);
     535              206:   uint64_t FieldSize = D->getBitWidth()->EvaluateAsInt(Ctx).getZExtValue();
     536                 :   
     537              206:   std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType());
     538              206:   uint64_t TypeSize = FieldInfo.first;
     539              206:   unsigned FieldAlign = FieldInfo.second;
     540                 :   
                        7: branch 0 taken
                      199: branch 1 taken
     541              206:   if (FieldPacked)
     542                7:     FieldAlign = 1;
                        3: branch 1 taken
                      203: branch 2 taken
     543              206:   if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
     544                3:     FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
     545                 : 
     546                 :   // The maximum field alignment overrides the aligned attribute.
                        0: branch 0 not taken
                      206: branch 1 taken
     547              206:   if (MaxFieldAlignment)
     548                0:     FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
     549                 :   
     550                 :   // Check if we need to add padding to give the field the correct
     551                 :   // alignment.
                      179: branch 0 taken
                       27: branch 1 taken
                        7: branch 2 taken
                      172: branch 3 taken
     552              206:   if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)
     553               34:     FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
     554                 :   
     555                 :   // Padding members don't affect overall alignment
                       32: branch 1 taken
                      174: branch 2 taken
     556              206:   if (!D->getIdentifier())
     557               32:     FieldAlign = 1;
     558                 :   
     559                 :   // Place this field at the current location.
     560              206:   FieldOffsets.push_back(FieldOffset);
     561                 :   
     562                 :   // Update DataSize to include the last byte containing (part of) the bitfield.
                        5: branch 0 taken
                      201: branch 1 taken
     563              206:   if (IsUnion) {
     564                 :     // FIXME: I think FieldSize should be TypeSize here.
     565                5:     DataSize = std::max(DataSize, FieldSize);
     566                 :   } else {
     567              201:     uint64_t NewSizeInBits = FieldOffset + FieldSize;
     568                 :     
     569              201:     DataSize = llvm::RoundUpToAlignment(NewSizeInBits, 8);
     570              201:     UnfilledBitsInLastByte = DataSize - NewSizeInBits;
     571                 :   }
     572                 :   
     573                 :   // Update the size.
     574              206:   Size = std::max(Size, DataSize);
     575                 :   
     576                 :   // Remember max struct/class alignment.
     577              206:   UpdateAlignment(FieldAlign);
     578              206: }
     579                 : 
     580             2442: void ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) {
                      206: branch 1 taken
                     2236: branch 2 taken
     581             2442:   if (D->isBitField()) {
     582              206:     LayoutBitField(D);
     583              206:     return;
     584                 :   }
     585                 : 
     586                 :   // Reset the unfilled bits.
     587             2236:   UnfilledBitsInLastByte = 0;
     588                 : 
                     2206: branch 0 taken
                       30: branch 1 taken
                        3: branch 3 taken
                     2203: branch 4 taken
     589             2236:   bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
                       95: branch 0 taken
                     2141: branch 1 taken
     590             2236:   uint64_t FieldOffset = IsUnion ? 0 : DataSize;
     591                 :   uint64_t FieldSize;
     592                 :   unsigned FieldAlign;
     593                 :   
                        9: branch 3 taken
                     2227: branch 4 taken
     594             2236:   if (D->getType()->isIncompleteArrayType()) {
     595                 :     // This is a flexible array member; we can't directly
     596                 :     // query getTypeInfo about these, so we figure it out here.
     597                 :     // Flexible array members don't have any size, but they
     598                 :     // have to be aligned appropriately for their element type.
     599                9:     FieldSize = 0;
     600                9:     const ArrayType* ATy = Ctx.getAsArrayType(D->getType());
     601                9:     FieldAlign = Ctx.getTypeAlign(ATy->getElementType());
                       12: branch 3 taken
                     2215: branch 4 taken
     602             2227:   } else if (const ReferenceType *RT = D->getType()->getAs<ReferenceType>()) {
     603               12:     unsigned AS = RT->getPointeeType().getAddressSpace();
     604               12:     FieldSize = Ctx.Target.getPointerWidth(AS);
     605               12:     FieldAlign = Ctx.Target.getPointerAlign(AS);
     606                 :   } else {
     607             2215:     std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType());
     608             2215:     FieldSize = FieldInfo.first;
     609             2215:     FieldAlign = FieldInfo.second;
     610                 :   }
     611                 : 
                       33: branch 0 taken
                     2203: branch 1 taken
     612             2236:   if (FieldPacked)
     613               33:     FieldAlign = 8;
                       22: branch 1 taken
                     2214: branch 2 taken
     614             2236:   if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
     615               22:     FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
     616                 : 
     617                 :   // The maximum field alignment overrides the aligned attribute.
                       54: branch 0 taken
                     2182: branch 1 taken
     618             2236:   if (MaxFieldAlignment)
     619               54:     FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
     620                 : 
     621                 :   // Round up the current record size to the field's alignment boundary.
     622             2236:   FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
     623                 :   
                     2141: branch 0 taken
                       95: branch 1 taken
     624             2236:   if (!IsUnion) {
     625                2:     while (true) {
     626                 :       // Check if we can place the field at this offset.
                        2: branch 1 taken
                     2141: branch 2 taken
     627             2143:       if (canPlaceFieldAtOffset(D, FieldOffset))
     628             2141:         break;
     629                 :       
     630                 :       // We couldn't place the field at the offset. Try again at a new offset.
     631                2:       FieldOffset += FieldAlign;
     632                 :     }
     633                 :     
     634             2141:     UpdateEmptyClassOffsets(D, FieldOffset);
     635                 :   }
     636                 :   
     637                 :   // Place this field at the current location.
     638             2236:   FieldOffsets.push_back(FieldOffset);
     639                 : 
     640                 :   // Reserve space for this field.
                       95: branch 0 taken
                     2141: branch 1 taken
     641             2236:   if (IsUnion)
     642               95:     Size = std::max(Size, FieldSize);
     643                 :   else
     644             2141:     Size = FieldOffset + FieldSize;
     645                 : 
     646                 :   // Update the data size.
     647             2236:   DataSize = Size;
     648                 : 
     649                 :   // Remember max struct/class alignment.
     650             2236:   UpdateAlignment(FieldAlign);
     651                 : }
     652                 : 
     653             1800: void ASTRecordLayoutBuilder::FinishLayout() {
     654                 :   // In C++, records cannot be of size 0.
                      865: branch 1 taken
                      935: branch 2 taken
                      221: branch 3 taken
                      644: branch 4 taken
                      221: branch 5 taken
                     1579: branch 6 taken
     655             1800:   if (Ctx.getLangOptions().CPlusPlus && Size == 0)
     656              221:     Size = 8;
     657                 :   // Finally, round the size of the record up to the alignment of the
     658                 :   // record itself.
     659             1800:   Size = llvm::RoundUpToAlignment(Size, Alignment);
     660             1800: }
     661                 : 
     662             3165: void ASTRecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) {
                     1831: branch 0 taken
                     1334: branch 1 taken
     663             3165:   if (NewAlignment <= Alignment)
     664             1831:     return;
     665                 : 
                        0: branch 1 not taken
                     1334: branch 2 taken
     666             1334:   assert(llvm::isPowerOf2_32(NewAlignment && "Alignment not a power of 2"));
     667                 : 
     668             1334:   Alignment = NewAlignment;
     669                 : }
     670                 : 
     671                 : const ASTRecordLayout *
     672                 : ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
     673             1598:                                       const RecordDecl *D) {
     674             1598:   ASTRecordLayoutBuilder Builder(Ctx);
     675                 : 
     676             1598:   Builder.Layout(D);
     677                 : 
                      736: branch 1 taken
                      862: branch 2 taken
     678             1598:   if (!isa<CXXRecordDecl>(D))
     679                 :     return new ASTRecordLayout(Builder.Size, Builder.Alignment, Builder.Size,
     680                 :                                Builder.FieldOffsets.data(),
     681              736:                                Builder.FieldOffsets.size());
     682                 : 
     683                 :   // FIXME: This is not always correct. See the part about bitfields at
     684                 :   // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
     685                 :   // FIXME: IsPODForThePurposeOfLayout should be stored in the record layout.
     686              862:   bool IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD();
     687                 : 
     688                 :   // FIXME: This should be done in FinalizeLayout.
     689                 :   uint64_t DataSize =
                      218: branch 0 taken
                      644: branch 1 taken
     690              862:     IsPODForThePurposeOfLayout ? Builder.Size : Builder.DataSize;
     691                 :   uint64_t NonVirtualSize =
                      218: branch 0 taken
                      644: branch 1 taken
     692              862:     IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize;
     693                 : 
     694                 :   return new ASTRecordLayout(Builder.Size, Builder.Alignment, DataSize,
     695                 :                              Builder.FieldOffsets.data(),
     696                 :                              Builder.FieldOffsets.size(),
     697                 :                              NonVirtualSize,
     698                 :                              Builder.NonVirtualAlignment,
     699                 :                              Builder.PrimaryBase,
     700                 :                              Builder.Bases.data(),
     701                 :                              Builder.Bases.size(),
     702                 :                              Builder.VBases.data(),
     703              862:                              Builder.VBases.size());
     704                 : }
     705                 : 
     706                 : const ASTRecordLayout *
     707                 : ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
     708                 :                                       const ObjCInterfaceDecl *D,
     709              202:                                       const ObjCImplementationDecl *Impl) {
     710              202:   ASTRecordLayoutBuilder Builder(Ctx);
     711                 : 
     712              202:   Builder.Layout(D, Impl);
     713                 : 
     714                 :   return new ASTRecordLayout(Builder.Size, Builder.Alignment,
     715                 :                              Builder.DataSize,
     716                 :                              Builder.FieldOffsets.data(),
     717              202:                              Builder.FieldOffsets.size());
     718                 : }
     719                 : 
     720                 : const CXXMethodDecl *
     721             2359: ASTRecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) {
                     2359: branch 1 taken
                        0: branch 2 not taken
     722             2359:   assert(RD->isDynamicClass() && "Class does not have any virtual methods!");
     723                 : 
     724                 :   // If a class isnt' polymorphic it doesn't have a key function.
                      137: branch 1 taken
                     2222: branch 2 taken
     725             2359:   if (!RD->isPolymorphic())
     726              137:     return 0;
     727                 : 
     728                 :   // A class inside an anonymous namespace doesn't have a key function.  (Or
     729                 :   // at least, there's no point to assigning a key function to such a class;
     730                 :   // this doesn't affect the ABI.)
                       11: branch 1 taken
                     2211: branch 2 taken
     731             2222:   if (RD->isInAnonymousNamespace())
     732               11:     return 0;
     733                 : 
                     9477: branch 3 taken
                     1414: branch 4 taken
     734            13102:   for (CXXRecordDecl::method_iterator I = RD->method_begin(), 
     735             2211:        E = RD->method_end(); I != E; ++I) {
     736             9477:     const CXXMethodDecl *MD = *I;
     737                 :     
                     3330: branch 1 taken
                     6147: branch 2 taken
     738             9477:     if (!MD->isVirtual())
     739             6147:       continue;
     740                 :     
                       53: branch 1 taken
                     3277: branch 2 taken
     741             3330:     if (MD->isPure())
     742               53:       continue;
     743                 : 
     744                 :     // Ignore implicit member functions, they are always marked as inline, but
     745                 :     // they don't have a body until they're defined.
                       47: branch 1 taken
                     3230: branch 2 taken
     746             3277:     if (MD->isImplicit())
     747               47:       continue;
     748                 :     
                        8: branch 1 taken
                     3222: branch 2 taken
     749             3230:     if (MD->isInlineSpecified())
     750                8:       continue;
     751                 : 
                     2425: branch 1 taken
                      797: branch 2 taken
     752             3222:     if (MD->hasInlineBody())
     753             2425:       continue;
     754                 :     
     755                 :     // We found it.
     756              797:     return MD;
     757                 :   }
     758                 :   
     759             1414:   return 0;
     760                 : }
     761                 : 

Generated: 2010-02-10 01:31 by zcov