zcov: / lib/CodeGen/CGRecordLayoutBuilder.cpp


Files: 1 Branches Taken: 83.3% 110 / 132
Generated: 2010-02-10 01:31 Branches Executed: 98.5% 130 / 132
Line Coverage: 96.8% 183 / 189


Programs: 1 Runs 2897


       1                 : //===--- CGRecordLayoutBuilder.cpp - Record builder helper ------*- C++ -*-===//
       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                 : // This is a helper class used to build CGRecordLayout objects and LLVM types.
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #include "CGRecordLayoutBuilder.h"
      15                 : 
      16                 : #include "clang/AST/ASTContext.h"
      17                 : #include "clang/AST/Attr.h"
      18                 : #include "clang/AST/DeclCXX.h"
      19                 : #include "clang/AST/Expr.h"
      20                 : #include "clang/AST/RecordLayout.h"
      21                 : #include "CodeGenTypes.h"
      22                 : #include "llvm/DerivedTypes.h"
      23                 : #include "llvm/Target/TargetData.h"
      24                 : 
      25                 : 
      26                 : using namespace clang;
      27                 : using namespace CodeGen;
      28                 : 
      29             1341: void CGRecordLayoutBuilder::Layout(const RecordDecl *D) {
      30             1341:   Alignment = Types.getContext().getASTRecordLayout(D).getAlignment() / 8;
      31             1341:   Packed = D->hasAttr<PackedAttr>();
      32                 : 
                       46: branch 1 taken
                     1295: branch 2 taken
      33             1341:   if (D->isUnion()) {
      34               46:     LayoutUnion(D);
      35               46:     return;
      36                 :   }
      37                 : 
                     1270: branch 1 taken
                       25: branch 2 taken
      38             1295:   if (LayoutFields(D))
      39             1270:     return;
      40                 : 
      41                 :   // We weren't able to layout the struct. Try again with a packed struct
      42               25:   Packed = true;
      43               25:   AlignmentAsLLVMStruct = 1;
      44               25:   NextFieldOffsetInBytes = 0;
      45               25:   FieldTypes.clear();
      46               25:   LLVMFields.clear();
      47               25:   LLVMBitFields.clear();
      48                 : 
      49               25:   LayoutFields(D);
      50                 : }
      51                 : 
      52                 : void CGRecordLayoutBuilder::LayoutBitField(const FieldDecl *D,
      53              116:                                            uint64_t FieldOffset) {
      54                 :   uint64_t FieldSize =
      55              116:     D->getBitWidth()->EvaluateAsInt(Types.getContext()).getZExtValue();
      56                 : 
                       21: branch 0 taken
                       95: branch 1 taken
      57              116:   if (FieldSize == 0)
      58               21:     return;
      59                 : 
      60               95:   uint64_t NextFieldOffset = NextFieldOffsetInBytes * 8;
      61                 :   unsigned NumBytesToAppend;
      62                 : 
                       35: branch 0 taken
                       60: branch 1 taken
      63               95:   if (FieldOffset < NextFieldOffset) {
                        0: branch 0 not taken
                       35: branch 1 taken
      64               35:     assert(BitsAvailableInLastField && "Bitfield size mismatch!");
                        0: branch 0 not taken
                       35: branch 1 taken
      65               35:     assert(NextFieldOffsetInBytes && "Must have laid out at least one byte!");
      66                 : 
      67                 :     // The bitfield begins in the previous bit-field.
      68                 :     NumBytesToAppend =
      69               35:       llvm::RoundUpToAlignment(FieldSize - BitsAvailableInLastField, 8) / 8;
      70                 :   } else {
                        0: branch 0 not taken
                       60: branch 1 taken
      71               60:     assert(FieldOffset % 8 == 0 && "Field offset not aligned correctly");
      72                 : 
      73                 :     // Append padding if necessary.
      74               60:     AppendBytes((FieldOffset - NextFieldOffset) / 8);
      75                 : 
      76                 :     NumBytesToAppend =
      77               60:       llvm::RoundUpToAlignment(FieldSize, 8) / 8;
      78                 : 
                        0: branch 0 not taken
                       60: branch 1 taken
      79               60:     assert(NumBytesToAppend && "No bytes to append!");
      80                 :   }
      81                 : 
      82               95:   const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(D->getType());
      83               95:   uint64_t TypeSizeInBits = getTypeSizeInBytes(Ty) * 8;
      84                 : 
      85                 :   LLVMBitFields.push_back(LLVMBitFieldInfo(D, FieldOffset / TypeSizeInBits,
      86                 :                                            FieldOffset % TypeSizeInBits,
      87               95:                                            FieldSize));
      88                 : 
      89               95:   AppendBytes(NumBytesToAppend);
      90                 : 
      91                 :   BitsAvailableInLastField =
      92               95:     NextFieldOffsetInBytes * 8 - (FieldOffset + FieldSize);
      93                 : }
      94                 : 
      95                 : bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D,
      96             1829:                                         uint64_t FieldOffset) {
      97                 :   // If the field is packed, then we need a packed struct.
                     1773: branch 0 taken
                       56: branch 1 taken
                        3: branch 3 taken
                     1770: branch 4 taken
                        3: branch 5 taken
                     1826: branch 6 taken
      98             1829:   if (!Packed && D->hasAttr<PackedAttr>())
      99                3:     return false;
     100                 : 
                      134: branch 1 taken
                     1692: branch 2 taken
     101             1826:   if (D->isBitField()) {
     102                 :     // We must use packed structs for unnamed bit fields since they
     103                 :     // don't affect the struct alignment.
                      107: branch 0 taken
                       27: branch 1 taken
                       18: branch 4 taken
                       89: branch 5 taken
                       18: branch 6 taken
                      116: branch 7 taken
     104              134:     if (!Packed && !D->getDeclName())
     105               18:       return false;
     106                 : 
     107              116:     LayoutBitField(D, FieldOffset);
     108              116:     return true;
     109                 :   }
     110                 : 
     111                 :   // Check if we have a pointer to data member in this field.
     112             1692:   CheckForPointerToDataMember(D->getType());
     113                 :   
                        0: branch 0 not taken
                     1692: branch 1 taken
     114             1692:   assert(FieldOffset % 8 == 0 && "FieldOffset is not on a byte boundary!");
     115             1692:   uint64_t FieldOffsetInBytes = FieldOffset / 8;
     116                 : 
     117             1692:   const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(D->getType());
     118             1692:   unsigned TypeAlignment = getTypeAlignment(Ty);
     119                 : 
     120                 :   // If the type alignment is larger then the struct alignment, we must use
     121                 :   // a packed struct.
                        3: branch 0 taken
                     1689: branch 1 taken
     122             1692:   if (TypeAlignment > Alignment) {
                        0: branch 0 not taken
                        3: branch 1 taken
     123                3:     assert(!Packed && "Alignment is wrong even with packed struct!");
     124                3:     return false;
     125                 :   }
     126                 : 
                      101: branch 3 taken
                     1588: branch 4 taken
     127             1689:   if (const RecordType *RT = D->getType()->getAs<RecordType>()) {
     128              101:     const RecordDecl *RD = cast<RecordDecl>(RT->getDecl());
                        3: branch 1 taken
                       98: branch 2 taken
     129              101:     if (const PragmaPackAttr *PPA = RD->getAttr<PragmaPackAttr>()) {
                        2: branch 1 taken
                        1: branch 2 taken
                        1: branch 3 taken
                        1: branch 4 taken
                        1: branch 5 taken
                        2: branch 6 taken
     130                3:       if (PPA->getAlignment() != TypeAlignment * 8 && !Packed)
     131                1:         return false;
     132                 :     }
     133                 :   }
     134                 : 
     135                 :   // Round up the field offset to the alignment of the field type.
     136                 :   uint64_t AlignedNextFieldOffsetInBytes =
     137             1688:     llvm::RoundUpToAlignment(NextFieldOffsetInBytes, TypeAlignment);
     138                 : 
                        0: branch 0 not taken
                     1688: branch 1 taken
     139             1688:   if (FieldOffsetInBytes < AlignedNextFieldOffsetInBytes) {
                        0: branch 0 not taken
                        0: branch 1 not taken
     140                0:     assert(!Packed && "Could not place field even with packed struct!");
     141                0:     return false;
     142                 :   }
     143                 : 
                       54: branch 0 taken
                     1634: branch 1 taken
     144             1688:   if (AlignedNextFieldOffsetInBytes < FieldOffsetInBytes) {
     145                 :     // Even with alignment, the field offset is not at the right place,
     146                 :     // insert padding.
     147               54:     uint64_t PaddingInBytes = FieldOffsetInBytes - NextFieldOffsetInBytes;
     148                 : 
     149               54:     AppendBytes(PaddingInBytes);
     150                 :   }
     151                 : 
     152                 :   // Now append the field.
     153             1688:   LLVMFields.push_back(LLVMFieldInfo(D, FieldTypes.size()));
     154             1688:   AppendField(FieldOffsetInBytes, Ty);
     155                 : 
     156             1688:   return true;
     157                 : }
     158                 : 
     159               46: void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) {
                       46: branch 1 taken
                        0: branch 2 not taken
     160               46:   assert(D->isUnion() && "Can't call LayoutUnion on a non-union record!");
     161                 : 
     162               46:   const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D);
     163                 : 
     164               46:   const llvm::Type *Ty = 0;
     165               46:   uint64_t Size = 0;
     166               46:   unsigned Align = 0;
     167                 : 
     168               46:   bool HasOnlyZeroSizedBitFields = true;
     169                 :   
     170               46:   unsigned FieldNo = 0;
                       80: branch 3 taken
                       46: branch 4 taken
     171              172:   for (RecordDecl::field_iterator Field = D->field_begin(),
     172               46:        FieldEnd = D->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
     173                 :     assert(Layout.getFieldOffset(FieldNo) == 0 &&
                       80: branch 1 taken
                        0: branch 2 not taken
     174               80:           "Union field offset did not start at the beginning of record!");
     175                 : 
                        2: branch 2 taken
                       78: branch 3 taken
     176               80:     if (Field->isBitField()) {
     177                 :       uint64_t FieldSize =
     178                2:         Field->getBitWidth()->EvaluateAsInt(Types.getContext()).getZExtValue();
     179                 : 
     180                 :       // Ignore zero sized bit fields.
                        1: branch 0 taken
                        1: branch 1 taken
     181                2:       if (FieldSize == 0)
     182                1:         continue;
     183                 : 
     184                 :       // Add the bit field info.
     185                1:       Types.addBitFieldInfo(*Field, 0, 0, FieldSize);
     186                 :     } else
     187               78:       Types.addFieldInfo(*Field, 0);
     188                 : 
     189               79:     HasOnlyZeroSizedBitFields = false;
     190                 :     
     191                 :     const llvm::Type *FieldTy =
     192               79:       Types.ConvertTypeForMemRecursive(Field->getType());
     193               79:     unsigned FieldAlign = Types.getTargetData().getABITypeAlignment(FieldTy);
     194               79:     uint64_t FieldSize = Types.getTargetData().getTypeAllocSize(FieldTy);
     195                 : 
                        6: branch 0 taken
                       73: branch 1 taken
     196               79:     if (FieldAlign < Align)
     197                6:       continue;
     198                 : 
                       27: branch 0 taken
                       46: branch 1 taken
                        3: branch 2 taken
                       24: branch 3 taken
     199               73:     if (FieldAlign > Align || FieldSize > Size) {
     200               49:       Ty = FieldTy;
     201               49:       Align = FieldAlign;
     202               49:       Size = FieldSize;
     203                 :     }
     204                 :   }
     205                 : 
     206                 :   // Now add our field.
                       41: branch 0 taken
                        5: branch 1 taken
     207               46:   if (Ty) {
     208               41:     AppendField(0, Ty);
     209                 : 
                        2: branch 2 taken
                       39: branch 3 taken
     210               41:     if (getTypeAlignment(Ty) > Layout.getAlignment() / 8) {
     211                 :       // We need a packed struct.
     212                2:       Packed = true;
     213                2:       Align = 1;
     214                 :     }
     215                 :   }
                        5: branch 0 taken
                       41: branch 1 taken
     216               46:   if (!Align) {
     217                 :     assert(HasOnlyZeroSizedBitFields &&
                        0: branch 0 not taken
                        5: branch 1 taken
     218                5:            "0-align record did not have all zero-sized bit-fields!");
     219                5:     Align = 1;
     220                 :   }
     221                 :   
     222                 :   // Append tail padding.
                        5: branch 1 taken
                       41: branch 2 taken
     223               46:   if (Layout.getSize() / 8 > Size)
     224                5:     AppendPadding(Layout.getSize() / 8, Align);
     225               46: }
     226                 : 
     227                 : void CGRecordLayoutBuilder::LayoutBases(const CXXRecordDecl *RD,
     228              750:                                         const ASTRecordLayout &Layout) {
     229                 :   // Check if we need to add a vtable pointer.
                      331: branch 1 taken
                      419: branch 2 taken
                      203: branch 4 taken
                      128: branch 5 taken
                      203: branch 6 taken
                      547: branch 7 taken
     230              750:   if (RD->isDynamicClass() && !Layout.getPrimaryBase()) {
     231                 :     const llvm::Type *Int8PtrTy = 
     232              203:       llvm::Type::getInt8PtrTy(Types.getLLVMContext());
     233                 :     
     234                 :     assert(NextFieldOffsetInBytes == 0 &&
                        0: branch 0 not taken
                      203: branch 1 taken
     235              203:            "Vtable pointer must come first!");
     236              203:     AppendField(NextFieldOffsetInBytes, Int8PtrTy->getPointerTo());
     237                 :   }
     238              750: }
     239                 : 
     240             1320: bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
                     1320: branch 1 taken
                        0: branch 2 not taken
     241             1320:   assert(!D->isUnion() && "Can't call LayoutFields on a union!");
                        0: branch 0 not taken
                     1320: branch 1 taken
     242             1320:   assert(Alignment && "Did not set alignment!");
     243                 : 
     244             1320:   const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D);
     245                 : 
                      750: branch 1 taken
                      570: branch 2 taken
     246             1320:   if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D))
     247              750:     LayoutBases(RD, Layout);
     248                 :   
     249             1320:   unsigned FieldNo = 0;
     250                 : 
                     1829: branch 3 taken
                     1295: branch 4 taken
     251             4444:   for (RecordDecl::field_iterator Field = D->field_begin(),
     252             1320:        FieldEnd = D->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
                       25: branch 3 taken
                     1804: branch 4 taken
     253             1829:     if (!LayoutField(*Field, Layout.getFieldOffset(FieldNo))) {
     254                 :       assert(!Packed &&
                        0: branch 0 not taken
                       25: branch 1 taken
     255               25:              "Could not layout fields even with a packed LLVM struct!");
     256               25:       return false;
     257                 :     }
     258                 :   }
     259                 : 
     260                 :   // Append tail padding if necessary.
     261             1295:   AppendTailPadding(Layout.getSize());
     262                 : 
     263             1295:   return true;
     264                 : }
     265                 : 
     266             1295: void CGRecordLayoutBuilder::AppendTailPadding(uint64_t RecordSize) {
                        0: branch 0 not taken
                     1295: branch 1 taken
     267             1295:   assert(RecordSize % 8 == 0 && "Invalid record size!");
     268                 : 
     269             1295:   uint64_t RecordSizeInBytes = RecordSize / 8;
                        0: branch 0 not taken
                     1295: branch 1 taken
     270             1295:   assert(NextFieldOffsetInBytes <= RecordSizeInBytes && "Size mismatch!");
     271                 : 
     272                 :   uint64_t AlignedNextFieldOffset = 
     273             1295:     llvm::RoundUpToAlignment(NextFieldOffsetInBytes, AlignmentAsLLVMStruct);
     274                 : 
                      888: branch 0 taken
                      407: branch 1 taken
     275             1295:   if (AlignedNextFieldOffset == RecordSizeInBytes) {
     276                 :     // We don't need any padding.
     277              888:     return;
     278                 :   }
     279                 :   
     280              407:   unsigned NumPadBytes = RecordSizeInBytes - NextFieldOffsetInBytes;
     281              407:   AppendBytes(NumPadBytes);
     282                 : }
     283                 : 
     284                 : void CGRecordLayoutBuilder::AppendField(uint64_t FieldOffsetInBytes,
     285             2461:                                         const llvm::Type *FieldTy) {
     286                 :   AlignmentAsLLVMStruct = std::max(AlignmentAsLLVMStruct,
     287             2461:                                    getTypeAlignment(FieldTy));
     288                 : 
     289             2461:   uint64_t FieldSizeInBytes = getTypeSizeInBytes(FieldTy);
     290                 : 
     291             2461:   FieldTypes.push_back(FieldTy);
     292                 : 
     293             2461:   NextFieldOffsetInBytes = FieldOffsetInBytes + FieldSizeInBytes;
     294             2461:   BitsAvailableInLastField = 0;
     295             2461: }
     296                 : 
     297                 : void
     298                 : CGRecordLayoutBuilder::AppendPadding(uint64_t FieldOffsetInBytes,
     299                0:                                      const llvm::Type *FieldTy) {
     300                0:   AppendPadding(FieldOffsetInBytes, getTypeAlignment(FieldTy));
     301                0: }
     302                 : 
     303                 : void CGRecordLayoutBuilder::AppendPadding(uint64_t FieldOffsetInBytes,
     304                5:                                           unsigned FieldAlignment) {
     305                 :   assert(NextFieldOffsetInBytes <= FieldOffsetInBytes &&
                        0: branch 0 not taken
                        5: branch 1 taken
     306                5:          "Incorrect field layout!");
     307                 : 
     308                 :   // Round up the field offset to the alignment of the field type.
     309                 :   uint64_t AlignedNextFieldOffsetInBytes =
     310                5:     llvm::RoundUpToAlignment(NextFieldOffsetInBytes, FieldAlignment);
     311                 : 
                        5: branch 0 taken
                        0: branch 1 not taken
     312                5:   if (AlignedNextFieldOffsetInBytes < FieldOffsetInBytes) {
     313                 :     // Even with alignment, the field offset is not at the right place,
     314                 :     // insert padding.
     315                5:     uint64_t PaddingInBytes = FieldOffsetInBytes - NextFieldOffsetInBytes;
     316                 : 
     317                5:     AppendBytes(PaddingInBytes);
     318                 :   }
     319                5: }
     320                 : 
     321              621: void CGRecordLayoutBuilder::AppendBytes(uint64_t NumBytes) {
                       92: branch 0 taken
                      529: branch 1 taken
     322              621:   if (NumBytes == 0)
     323               92:     return;
     324                 : 
     325              529:   const llvm::Type *Ty = llvm::Type::getInt8Ty(Types.getLLVMContext());
                      269: branch 0 taken
                      260: branch 1 taken
     326              529:   if (NumBytes > 1)
     327              269:     Ty = llvm::ArrayType::get(Ty, NumBytes);
     328                 : 
     329                 :   // Append the padding field
     330              529:   AppendField(NextFieldOffsetInBytes, Ty);
     331                 : }
     332                 : 
     333             4194: unsigned CGRecordLayoutBuilder::getTypeAlignment(const llvm::Type *Ty) const {
                       75: branch 0 taken
                     4119: branch 1 taken
     334             4194:   if (Packed)
     335               75:     return 1;
     336                 : 
     337             4119:   return Types.getTargetData().getABITypeAlignment(Ty);
     338                 : }
     339                 : 
     340             2556: uint64_t CGRecordLayoutBuilder::getTypeSizeInBytes(const llvm::Type *Ty) const {
     341             2556:   return Types.getTargetData().getTypeAllocSize(Ty);
     342                 : }
     343                 : 
     344             1692: void CGRecordLayoutBuilder::CheckForPointerToDataMember(QualType T) {
     345                 :   // This record already contains a member pointer.
                        0: branch 0 not taken
                     1692: branch 1 taken
     346             1692:   if (ContainsPointerToDataMember)
     347                0:     return;
     348                 : 
     349                 :   // Can only have member pointers if we're compiling C++.
                     1233: branch 2 taken
                      459: branch 3 taken
     350             1692:   if (!Types.getContext().getLangOptions().CPlusPlus)
     351             1233:     return;
     352                 : 
     353              459:   T = Types.getContext().getBaseElementType(T);
     354                 : 
                       10: branch 2 taken
                      449: branch 3 taken
     355              459:   if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) {
                        5: branch 3 taken
                        5: branch 4 taken
     356               10:     if (!MPT->getPointeeType()->isFunctionType()) {
     357                 :       // We have a pointer to data member.
     358                5:       ContainsPointerToDataMember = true;
     359                 :     }
                       82: branch 2 taken
                      367: branch 3 taken
     360              449:   } else if (const RecordType *RT = T->getAs<RecordType>()) {
     361               82:     const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
     362                 :     
     363                 :     // FIXME: It would be better if there was a way to explicitly compute the
     364                 :     // record layout instead of converting to a type.
     365               82:     Types.ConvertTagDeclType(RD);
     366                 :     
     367               82:     const CGRecordLayout &Layout = Types.getCGRecordLayout(RD);
     368                 :     
                        1: branch 1 taken
                       81: branch 2 taken
     369               82:     if (Layout.containsPointerToDataMember())
     370                1:       ContainsPointerToDataMember = true;
     371                 :   }    
     372                 : }
     373                 : 
     374                 : CGRecordLayout *
     375                 : CGRecordLayoutBuilder::ComputeLayout(CodeGenTypes &Types,
     376             1341:                                      const RecordDecl *D) {
     377             1341:   CGRecordLayoutBuilder Builder(Types);
     378                 : 
     379             1341:   Builder.Layout(D);
     380                 : 
     381                 :   const llvm::Type *Ty = llvm::StructType::get(Types.getLLVMContext(),
     382                 :                                                Builder.FieldTypes,
     383             1341:                                                Builder.Packed);
     384                 :   assert(Types.getContext().getASTRecordLayout(D).getSize() / 8 ==
     385                 :          Types.getTargetData().getTypeAllocSize(Ty) &&
                     1341: branch 5 taken
                        0: branch 6 not taken
     386             1341:          "Type size mismatch!");
     387                 : 
     388                 :   // Add all the field numbers.
                     1677: branch 1 taken
                     1341: branch 2 taken
     389             3018:   for (unsigned i = 0, e = Builder.LLVMFields.size(); i != e; ++i) {
     390             1677:     const FieldDecl *FD = Builder.LLVMFields[i].first;
     391             1677:     unsigned FieldNo = Builder.LLVMFields[i].second;
     392                 : 
     393             1677:     Types.addFieldInfo(FD, FieldNo);
     394                 :   }
     395                 : 
     396                 :   // Add bitfield info.
                       92: branch 1 taken
                     1341: branch 2 taken
     397             1433:   for (unsigned i = 0, e = Builder.LLVMBitFields.size(); i != e; ++i) {
     398               92:     const LLVMBitFieldInfo &Info = Builder.LLVMBitFields[i];
     399                 : 
     400               92:     Types.addBitFieldInfo(Info.FD, Info.FieldNo, Info.Start, Info.Size);
     401                 :   }
     402                 : 
     403             1341:   return new CGRecordLayout(Ty, Builder.ContainsPointerToDataMember);
     404                 : }

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