LCOV - code coverage report
Current view: top level - lib/DebugInfo/CodeView - TypeRecordMapping.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 208 208 100.0 %
Date: 2018-06-17 00:07:59 Functions: 41 41 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- TypeRecordMapping.cpp ------------------------------------*- 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             : #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
      11             : 
      12             : using namespace llvm;
      13             : using namespace llvm::codeview;
      14             : 
      15             : #define error(X)                                                               \
      16             :   if (auto EC = X)                                                             \
      17             :     return EC;
      18             : 
      19             : namespace {
      20             : struct MapOneMethodRecord {
      21             :   explicit MapOneMethodRecord(bool IsFromOverloadList)
      22         860 :       : IsFromOverloadList(IsFromOverloadList) {}
      23             : 
      24        1392 :   Error operator()(CodeViewRecordIO &IO, OneMethodRecord &Method) const {
      25        2784 :     error(IO.mapInteger(Method.Attrs.Attrs));
      26        1392 :     if (IsFromOverloadList) {
      27         895 :       uint16_t Padding = 0;
      28        1790 :       error(IO.mapInteger(Padding));
      29             :     }
      30        2784 :     error(IO.mapInteger(Method.Type));
      31             :     if (Method.isIntroducingVirtual()) {
      32         106 :       error(IO.mapInteger(Method.VFTableOffset));
      33        1339 :     } else if (!IO.isWriting())
      34        1153 :       Method.VFTableOffset = -1;
      35             : 
      36        1392 :     if (!IsFromOverloadList)
      37         994 :       error(IO.mapStringZ(Method.Name));
      38             : 
      39             :     return Error::success();
      40             :   }
      41             : 
      42             : private:
      43             :   bool IsFromOverloadList;
      44             : };
      45             : }
      46             : 
      47        2752 : static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name,
      48             :                                   StringRef &UniqueName, bool HasUniqueName) {
      49        2752 :   if (IO.isWriting()) {
      50             :     // Try to be smart about what we write here.  We can't write anything too
      51             :     // large, so if we're going to go over the limit, truncate both the name
      52             :     // and unique name by the same amount.
      53         383 :     size_t BytesLeft = IO.maxFieldLength();
      54         383 :     if (HasUniqueName) {
      55         323 :       size_t BytesNeeded = Name.size() + UniqueName.size() + 2;
      56         323 :       StringRef N = Name;
      57         323 :       StringRef U = UniqueName;
      58         323 :       if (BytesNeeded > BytesLeft) {
      59           3 :         size_t BytesToDrop = (BytesNeeded - BytesLeft);
      60           6 :         size_t DropN = std::min(N.size(), BytesToDrop / 2);
      61           6 :         size_t DropU = std::min(U.size(), BytesToDrop - DropN);
      62             : 
      63           3 :         N = N.drop_back(DropN);
      64           3 :         U = U.drop_back(DropU);
      65             :       }
      66             : 
      67         646 :       error(IO.mapStringZ(N));
      68         646 :       error(IO.mapStringZ(U));
      69             :     } else {
      70             :       // Cap the length of the string at however many bytes we have available,
      71             :       // plus one for the required null terminator.
      72         120 :       auto N = StringRef(Name).take_front(BytesLeft - 1);
      73         120 :       error(IO.mapStringZ(N));
      74             :     }
      75             :   } else {
      76        4738 :     error(IO.mapStringZ(Name));
      77        2369 :     if (HasUniqueName)
      78        4542 :       error(IO.mapStringZ(UniqueName));
      79             :   }
      80             : 
      81             :   return Error::success();
      82             : }
      83             : 
      84       13323 : Error TypeRecordMapping::visitTypeBegin(CVType &CVR) {
      85             :   assert(!TypeKind.hasValue() && "Already in a type mapping!");
      86             :   assert(!MemberKind.hasValue() && "Already in a member mapping!");
      87             : 
      88             :   // FieldList and MethodList records can be any length because they can be
      89             :   // split with continuation records.  All other record types cannot be
      90             :   // longer than the maximum record length.
      91             :   Optional<uint32_t> MaxLen;
      92       13323 :   if (CVR.Type != TypeLeafKind::LF_FIELDLIST &&
      93             :       CVR.Type != TypeLeafKind::LF_METHODLIST)
      94             :     MaxLen = MaxRecordLength - sizeof(RecordPrefix);
      95       39969 :   error(IO.beginRecord(MaxLen));
      96       13323 :   TypeKind = CVR.Type;
      97             :   return Error::success();
      98             : }
      99             : 
     100       13321 : Error TypeRecordMapping::visitTypeEnd(CVType &Record) {
     101             :   assert(TypeKind.hasValue() && "Not in a type mapping!");
     102             :   assert(!MemberKind.hasValue() && "Still in a member mapping!");
     103             : 
     104       26642 :   error(IO.endRecord());
     105             : 
     106             :   TypeKind.reset();
     107             :   return Error::success();
     108             : }
     109             : 
     110       15478 : Error TypeRecordMapping::visitMemberBegin(CVMemberRecord &Record) {
     111             :   assert(TypeKind.hasValue() && "Not in a type mapping!");
     112             :   assert(!MemberKind.hasValue() && "Already in a member mapping!");
     113             : 
     114             :   // The largest possible subrecord is one in which there is a record prefix,
     115             :   // followed by the subrecord, followed by a continuation, and that entire
     116             :   // sequence spaws `MaxRecordLength` bytes.  So the record's length is
     117             :   // calculated as follows.
     118             :   constexpr uint32_t ContinuationLength = 8;
     119       46434 :   error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix) -
     120             :                        ContinuationLength));
     121             : 
     122       15478 :   MemberKind = Record.Kind;
     123             :   return Error::success();
     124             : }
     125             : 
     126       15478 : Error TypeRecordMapping::visitMemberEnd(CVMemberRecord &Record) {
     127             :   assert(TypeKind.hasValue() && "Not in a type mapping!");
     128             :   assert(MemberKind.hasValue() && "Not in a member mapping!");
     129             : 
     130       15478 :   if (!IO.isWriting()) {
     131       17682 :     if (auto EC = IO.skipPadding())
     132             :       return EC;
     133             :   }
     134             : 
     135             :   MemberKind.reset();
     136       30956 :   error(IO.endRecord());
     137             :   return Error::success();
     138             : }
     139             : 
     140         253 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ModifierRecord &Record) {
     141         506 :   error(IO.mapInteger(Record.ModifiedType));
     142         506 :   error(IO.mapEnum(Record.Modifiers));
     143             : 
     144             :   return Error::success();
     145             : }
     146             : 
     147         619 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     148             :                                           ProcedureRecord &Record) {
     149        1238 :   error(IO.mapInteger(Record.ReturnType));
     150        1238 :   error(IO.mapEnum(Record.CallConv));
     151        1238 :   error(IO.mapEnum(Record.Options));
     152        1238 :   error(IO.mapInteger(Record.ParameterCount));
     153        1238 :   error(IO.mapInteger(Record.ArgumentList));
     154             : 
     155             :   return Error::success();
     156             : }
     157             : 
     158        1603 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     159             :                                           MemberFunctionRecord &Record) {
     160        3206 :   error(IO.mapInteger(Record.ReturnType));
     161        3206 :   error(IO.mapInteger(Record.ClassType));
     162        3206 :   error(IO.mapInteger(Record.ThisType));
     163        3206 :   error(IO.mapEnum(Record.CallConv));
     164        3206 :   error(IO.mapEnum(Record.Options));
     165        3206 :   error(IO.mapInteger(Record.ParameterCount));
     166        3206 :   error(IO.mapInteger(Record.ArgumentList));
     167        3206 :   error(IO.mapInteger(Record.ThisPointerAdjustment));
     168             : 
     169             :   return Error::success();
     170             : }
     171             : 
     172        1160 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArgListRecord &Record) {
     173        3894 :   error(IO.mapVectorN<uint32_t>(
     174             :       Record.ArgIndices,
     175             :       [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
     176             : 
     177             :   return Error::success();
     178             : }
     179             : 
     180          81 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     181             :                                           StringListRecord &Record) {
     182         261 :   error(IO.mapVectorN<uint32_t>(
     183             :       Record.StringIndices,
     184             :       [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
     185             : 
     186             :   return Error::success();
     187             : }
     188             : 
     189        1522 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, PointerRecord &Record) {
     190        3044 :   error(IO.mapInteger(Record.ReferentType));
     191        3044 :   error(IO.mapInteger(Record.Attrs));
     192             : 
     193             :   if (Record.isPointerToMember()) {
     194          49 :     if (!IO.isWriting())
     195             :       Record.MemberInfo.emplace();
     196             : 
     197             :     MemberPointerInfo &M = *Record.MemberInfo;
     198          98 :     error(IO.mapInteger(M.ContainingType));
     199          98 :     error(IO.mapEnum(M.Representation));
     200             :   }
     201             : 
     202             :   return Error::success();
     203             : }
     204             : 
     205         175 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArrayRecord &Record) {
     206         350 :   error(IO.mapInteger(Record.ElementType));
     207         350 :   error(IO.mapInteger(Record.IndexType));
     208         350 :   error(IO.mapEncodedInteger(Record.Size));
     209         350 :   error(IO.mapStringZ(Record.Name));
     210             : 
     211             :   return Error::success();
     212             : }
     213             : 
     214        2350 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ClassRecord &Record) {
     215             :   assert((CVR.Type == TypeLeafKind::LF_STRUCTURE) ||
     216             :          (CVR.Type == TypeLeafKind::LF_CLASS) ||
     217             :          (CVR.Type == TypeLeafKind::LF_INTERFACE));
     218             : 
     219        4700 :   error(IO.mapInteger(Record.MemberCount));
     220        4700 :   error(IO.mapEnum(Record.Options));
     221        4700 :   error(IO.mapInteger(Record.FieldList));
     222        4700 :   error(IO.mapInteger(Record.DerivationList));
     223        4700 :   error(IO.mapInteger(Record.VTableShape));
     224        4700 :   error(IO.mapEncodedInteger(Record.Size));
     225        7050 :   error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
     226             :                              Record.hasUniqueName()));
     227             : 
     228             :   return Error::success();
     229             : }
     230             : 
     231          37 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, UnionRecord &Record) {
     232          74 :   error(IO.mapInteger(Record.MemberCount));
     233          74 :   error(IO.mapEnum(Record.Options));
     234          74 :   error(IO.mapInteger(Record.FieldList));
     235          74 :   error(IO.mapEncodedInteger(Record.Size));
     236         111 :   error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
     237             :                              Record.hasUniqueName()));
     238             : 
     239             :   return Error::success();
     240             : }
     241             : 
     242         365 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, EnumRecord &Record) {
     243         730 :   error(IO.mapInteger(Record.MemberCount));
     244         730 :   error(IO.mapEnum(Record.Options));
     245         730 :   error(IO.mapInteger(Record.UnderlyingType));
     246         730 :   error(IO.mapInteger(Record.FieldList));
     247        1095 :   error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
     248             :                              Record.hasUniqueName()));
     249             : 
     250             :   return Error::success();
     251             : }
     252             : 
     253          32 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, BitFieldRecord &Record) {
     254          64 :   error(IO.mapInteger(Record.Type));
     255          64 :   error(IO.mapInteger(Record.BitSize));
     256          64 :   error(IO.mapInteger(Record.BitOffset));
     257             : 
     258             :   return Error::success();
     259             : }
     260             : 
     261          56 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     262             :                                           VFTableShapeRecord &Record) {
     263             :   uint16_t Size;
     264          56 :   if (IO.isWriting()) {
     265             :     ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
     266          17 :     Size = Slots.size();
     267          34 :     error(IO.mapInteger(Size));
     268             : 
     269          47 :     for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
     270          15 :       uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
     271          15 :       if ((SlotIndex + 1) < Slots.size()) {
     272           2 :         Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
     273             :       }
     274          30 :       error(IO.mapInteger(Byte));
     275             :     }
     276             :   } else {
     277          78 :     error(IO.mapInteger(Size));
     278         121 :     for (uint16_t I = 0; I < Size; I += 2) {
     279             :       uint8_t Byte;
     280          82 :       error(IO.mapInteger(Byte));
     281          82 :       Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte & 0xF));
     282          41 :       if ((I + 1) < Size)
     283          24 :         Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte >> 4));
     284             :     }
     285             :   }
     286             : 
     287             :   return Error::success();
     288             : }
     289             : 
     290          17 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, VFTableRecord &Record) {
     291          34 :   error(IO.mapInteger(Record.CompleteClass));
     292          34 :   error(IO.mapInteger(Record.OverriddenVFTable));
     293          34 :   error(IO.mapInteger(Record.VFPtrOffset));
     294          17 :   uint32_t NamesLen = 0;
     295          17 :   if (IO.isWriting()) {
     296          16 :     for (auto Name : Record.MethodNames)
     297          10 :       NamesLen += Name.size() + 1;
     298             :   }
     299          34 :   error(IO.mapInteger(NamesLen));
     300          72 :   error(IO.mapVectorTail(
     301             :       Record.MethodNames,
     302             :       [](CodeViewRecordIO &IO, StringRef &S) { return IO.mapStringZ(S); }));
     303             : 
     304             :   return Error::success();
     305             : }
     306             : 
     307         782 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, StringIdRecord &Record) {
     308        1564 :   error(IO.mapInteger(Record.Id));
     309        1564 :   error(IO.mapStringZ(Record.String));
     310             : 
     311             :   return Error::success();
     312             : }
     313             : 
     314         912 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     315             :                                           UdtSourceLineRecord &Record) {
     316        1824 :   error(IO.mapInteger(Record.UDT));
     317        1824 :   error(IO.mapInteger(Record.SourceFile));
     318        1824 :   error(IO.mapInteger(Record.LineNumber));
     319             : 
     320             :   return Error::success();
     321             : }
     322             : 
     323          45 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     324             :                                           UdtModSourceLineRecord &Record) {
     325          90 :   error(IO.mapInteger(Record.UDT));
     326          90 :   error(IO.mapInteger(Record.SourceFile));
     327          90 :   error(IO.mapInteger(Record.LineNumber));
     328          90 :   error(IO.mapInteger(Record.Module));
     329             : 
     330             :   return Error::success();
     331             : }
     332             : 
     333         664 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, FuncIdRecord &Record) {
     334        1328 :   error(IO.mapInteger(Record.ParentScope));
     335        1328 :   error(IO.mapInteger(Record.FunctionType));
     336        1328 :   error(IO.mapStringZ(Record.Name));
     337             : 
     338             :   return Error::success();
     339             : }
     340             : 
     341         171 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     342             :                                           MemberFuncIdRecord &Record) {
     343         342 :   error(IO.mapInteger(Record.ClassType));
     344         342 :   error(IO.mapInteger(Record.FunctionType));
     345         342 :   error(IO.mapStringZ(Record.Name));
     346             : 
     347             :   return Error::success();
     348             : }
     349             : 
     350          83 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     351             :                                           BuildInfoRecord &Record) {
     352         577 :   error(IO.mapVectorN<uint16_t>(
     353             :       Record.ArgIndices,
     354             :       [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
     355             : 
     356             :   return Error::success();
     357             : }
     358             : 
     359         363 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     360             :                                           MethodOverloadListRecord &Record) {
     361             :   // TODO: Split the list into multiple records if it's longer than 64KB, using
     362             :   // a subrecord of TypeRecordKind::Index to chain the records together.
     363        1089 :   error(IO.mapVectorTail(Record.Methods, MapOneMethodRecord(true)));
     364             : 
     365             :   return Error::success();
     366             : }
     367             : 
     368         959 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     369             :                                           FieldListRecord &Record) {
     370        1918 :   error(IO.mapByteVectorTail(Record.Data));
     371             : 
     372             :   return Error::success();
     373             : }
     374             : 
     375          12 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     376             :                                           TypeServer2Record &Record) {
     377          24 :   error(IO.mapGuid(Record.Guid));
     378          24 :   error(IO.mapInteger(Record.Age));
     379          24 :   error(IO.mapStringZ(Record.Name));
     380             :   return Error::success();
     381             : }
     382             : 
     383           1 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, LabelRecord &Record) {
     384           2 :   error(IO.mapEnum(Record.Mode));
     385             :   return Error::success();
     386             : }
     387             : 
     388          46 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     389             :                                           BaseClassRecord &Record) {
     390          92 :   error(IO.mapInteger(Record.Attrs.Attrs));
     391          92 :   error(IO.mapInteger(Record.Type));
     392          92 :   error(IO.mapEncodedInteger(Record.Offset));
     393             : 
     394             :   return Error::success();
     395             : }
     396             : 
     397       12786 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     398             :                                           EnumeratorRecord &Record) {
     399       25572 :   error(IO.mapInteger(Record.Attrs.Attrs));
     400             : 
     401             :   // FIXME: Handle full APInt such as __int128.
     402       25572 :   error(IO.mapEncodedInteger(Record.Value));
     403       25572 :   error(IO.mapStringZ(Record.Name));
     404             : 
     405             :   return Error::success();
     406             : }
     407             : 
     408        1440 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     409             :                                           DataMemberRecord &Record) {
     410        2880 :   error(IO.mapInteger(Record.Attrs.Attrs));
     411        2880 :   error(IO.mapInteger(Record.Type));
     412        2880 :   error(IO.mapEncodedInteger(Record.FieldOffset));
     413        2880 :   error(IO.mapStringZ(Record.Name));
     414             : 
     415             :   return Error::success();
     416             : }
     417             : 
     418         276 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     419             :                                           OverloadedMethodRecord &Record) {
     420         552 :   error(IO.mapInteger(Record.NumOverloads));
     421         552 :   error(IO.mapInteger(Record.MethodList));
     422         552 :   error(IO.mapStringZ(Record.Name));
     423             : 
     424             :   return Error::success();
     425             : }
     426             : 
     427         497 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     428             :                                           OneMethodRecord &Record) {
     429             :   const bool IsFromOverloadList = (TypeKind == LF_METHODLIST);
     430             :   MapOneMethodRecord Mapper(IsFromOverloadList);
     431         497 :   return Mapper(IO, Record);
     432             : }
     433             : 
     434         231 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     435             :                                           NestedTypeRecord &Record) {
     436         231 :   uint16_t Padding = 0;
     437         462 :   error(IO.mapInteger(Padding));
     438         462 :   error(IO.mapInteger(Record.Type));
     439         462 :   error(IO.mapStringZ(Record.Name));
     440             : 
     441             :   return Error::success();
     442             : }
     443             : 
     444         125 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     445             :                                           StaticDataMemberRecord &Record) {
     446             : 
     447         250 :   error(IO.mapInteger(Record.Attrs.Attrs));
     448         250 :   error(IO.mapInteger(Record.Type));
     449         250 :   error(IO.mapStringZ(Record.Name));
     450             : 
     451             :   return Error::success();
     452             : }
     453             : 
     454          34 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     455             :                                           VirtualBaseClassRecord &Record) {
     456             : 
     457          68 :   error(IO.mapInteger(Record.Attrs.Attrs));
     458          68 :   error(IO.mapInteger(Record.BaseType));
     459          68 :   error(IO.mapInteger(Record.VBPtrType));
     460          68 :   error(IO.mapEncodedInteger(Record.VBPtrOffset));
     461          68 :   error(IO.mapEncodedInteger(Record.VTableIndex));
     462             : 
     463             :   return Error::success();
     464             : }
     465             : 
     466          37 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     467             :                                           VFPtrRecord &Record) {
     468          37 :   uint16_t Padding = 0;
     469          74 :   error(IO.mapInteger(Padding));
     470          74 :   error(IO.mapInteger(Record.Type));
     471             : 
     472             :   return Error::success();
     473             : }
     474             : 
     475           6 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     476             :                                           ListContinuationRecord &Record) {
     477           6 :   uint16_t Padding = 0;
     478          12 :   error(IO.mapInteger(Padding));
     479          12 :   error(IO.mapInteger(Record.ContinuationIndex));
     480             : 
     481             :   return Error::success();
     482             : }
     483             : 
     484           4 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     485             :                                           PrecompRecord &Precomp) {
     486           8 :   error(IO.mapInteger(Precomp.StartTypeIndex));
     487           8 :   error(IO.mapInteger(Precomp.TypesCount));
     488           8 :   error(IO.mapInteger(Precomp.Signature));
     489           8 :   error(IO.mapStringZ(Precomp.PrecompFilePath));
     490             :   return Error::success();
     491             : }
     492             : 
     493           4 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     494             :                                           EndPrecompRecord &EndPrecomp) {
     495           8 :   error(IO.mapInteger(EndPrecomp.Signature));
     496             :   return Error::success();
     497             : }

Generated by: LCOV version 1.13