LCOV - code coverage report
Current view: top level - lib/DebugInfo/CodeView - TypeRecordMapping.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 248 249 99.6 %
Date: 2017-09-14 15:23:50 Functions: 39 39 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         341 :       : IsFromOverloadList(IsFromOverloadList) {}
      23             : 
      24         592 :   Error operator()(CodeViewRecordIO &IO, OneMethodRecord &Method) const {
      25        1776 :     error(IO.mapInteger(Method.Attrs.Attrs));
      26         592 :     if (IsFromOverloadList) {
      27         436 :       uint16_t Padding = 0;
      28        1308 :       error(IO.mapInteger(Padding));
      29             :     }
      30        1776 :     error(IO.mapInteger(Method.Type));
      31         553 :     if (Method.isIntroducingVirtual()) {
      32         117 :       error(IO.mapInteger(Method.VFTableOffset));
      33         553 :     } else if (!IO.isWriting())
      34         457 :       Method.VFTableOffset = -1;
      35             : 
      36         592 :     if (!IsFromOverloadList)
      37         468 :       error(IO.mapStringZ(Method.Name));
      38             : 
      39        1776 :     return Error::success();
      40             :   }
      41             : 
      42             : private:
      43             :   bool IsFromOverloadList;
      44             : };
      45             : }
      46             : 
      47        1270 : static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name,
      48             :                                   StringRef &UniqueName, bool HasUniqueName) {
      49        1270 :   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         238 :     size_t BytesLeft = IO.maxFieldLength();
      54         238 :     if (HasUniqueName) {
      55         364 :       size_t BytesNeeded = Name.size() + UniqueName.size() + 2;
      56         182 :       StringRef N = Name;
      57         182 :       StringRef U = UniqueName;
      58         182 :       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         546 :       error(IO.mapStringZ(N));
      68         546 :       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         112 :       auto N = StringRef(Name).take_front(BytesLeft - 1);
      73         168 :       error(IO.mapStringZ(N));
      74             :     }
      75             :   } else {
      76        3096 :     error(IO.mapStringZ(Name));
      77        1032 :     if (HasUniqueName)
      78        2826 :       error(IO.mapStringZ(UniqueName));
      79             :   }
      80             : 
      81        3810 :   return Error::success();
      82             : }
      83             : 
      84        7093 : 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       14186 :   Optional<uint32_t> MaxLen;
      92        7093 :   if (CVR.Type != TypeLeafKind::LF_FIELDLIST &&
      93             :       CVR.Type != TypeLeafKind::LF_METHODLIST)
      94             :     MaxLen = MaxRecordLength - sizeof(RecordPrefix);
      95       35465 :   error(IO.beginRecord(MaxLen));
      96       14186 :   TypeKind = CVR.Type;
      97       21279 :   return Error::success();
      98             : }
      99             : 
     100        7093 : 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       21279 :   error(IO.endRecord());
     105             : 
     106       14186 :   TypeKind.reset();
     107       21279 :   return Error::success();
     108             : }
     109             : 
     110       13627 : 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       13627 :   constexpr uint32_t ContinuationLength = 8;
     119       68135 :   error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix) -
     120             :                        ContinuationLength));
     121             : 
     122       27254 :   MemberKind = Record.Kind;
     123       40881 :   return Error::success();
     124             : }
     125             : 
     126       13627 : 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       27254 :   if (!IO.isWriting()) {
     131       22332 :     if (auto EC = IO.skipPadding())
     132           0 :       return EC;
     133             :   }
     134             : 
     135       27254 :   MemberKind.reset();
     136       40881 :   error(IO.endRecord());
     137       40881 :   return Error::success();
     138             : }
     139             : 
     140         148 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ModifierRecord &Record) {
     141         444 :   error(IO.mapInteger(Record.ModifiedType));
     142         444 :   error(IO.mapEnum(Record.Modifiers));
     143             : 
     144         444 :   return Error::success();
     145             : }
     146             : 
     147         464 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     148             :                                           ProcedureRecord &Record) {
     149        1392 :   error(IO.mapInteger(Record.ReturnType));
     150        1392 :   error(IO.mapEnum(Record.CallConv));
     151        1392 :   error(IO.mapEnum(Record.Options));
     152        1392 :   error(IO.mapInteger(Record.ParameterCount));
     153        1392 :   error(IO.mapInteger(Record.ArgumentList));
     154             : 
     155        1392 :   return Error::success();
     156             : }
     157             : 
     158         658 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     159             :                                           MemberFunctionRecord &Record) {
     160        1974 :   error(IO.mapInteger(Record.ReturnType));
     161        1974 :   error(IO.mapInteger(Record.ClassType));
     162        1974 :   error(IO.mapInteger(Record.ThisType));
     163        1974 :   error(IO.mapEnum(Record.CallConv));
     164        1974 :   error(IO.mapEnum(Record.Options));
     165        1974 :   error(IO.mapInteger(Record.ParameterCount));
     166        1974 :   error(IO.mapInteger(Record.ArgumentList));
     167        1974 :   error(IO.mapInteger(Record.ThisPointerAdjustment));
     168             : 
     169        1974 :   return Error::success();
     170             : }
     171             : 
     172         796 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArgListRecord &Record) {
     173        3238 :   error(IO.mapVectorN<uint32_t>(
     174             :       Record.ArgIndices,
     175             :       [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
     176             : 
     177        2388 :   return Error::success();
     178             : }
     179             : 
     180          67 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     181             :                                           StringListRecord &Record) {
     182         277 :   error(IO.mapVectorN<uint32_t>(
     183             :       Record.StringIndices,
     184             :       [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
     185             : 
     186         201 :   return Error::success();
     187             : }
     188             : 
     189         715 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, PointerRecord &Record) {
     190        2145 :   error(IO.mapInteger(Record.ReferentType));
     191        2145 :   error(IO.mapInteger(Record.Attrs));
     192             : 
     193             :   if (Record.isPointerToMember()) {
     194          76 :     if (!IO.isWriting())
     195          24 :       Record.MemberInfo.emplace();
     196             : 
     197          76 :     MemberPointerInfo &M = *Record.MemberInfo;
     198         114 :     error(IO.mapInteger(M.ContainingType));
     199         114 :     error(IO.mapEnum(M.Representation));
     200             :   }
     201             : 
     202        2145 :   return Error::success();
     203             : }
     204             : 
     205         147 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArrayRecord &Record) {
     206         441 :   error(IO.mapInteger(Record.ElementType));
     207         441 :   error(IO.mapInteger(Record.IndexType));
     208         441 :   error(IO.mapEncodedInteger(Record.Size));
     209         441 :   error(IO.mapStringZ(Record.Name));
     210             : 
     211         441 :   return Error::success();
     212             : }
     213             : 
     214         967 : 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        2901 :   error(IO.mapInteger(Record.MemberCount));
     220        2901 :   error(IO.mapEnum(Record.Options));
     221        2901 :   error(IO.mapInteger(Record.FieldList));
     222        2901 :   error(IO.mapInteger(Record.DerivationList));
     223        2901 :   error(IO.mapInteger(Record.VTableShape));
     224        1934 :   error(IO.mapEncodedInteger(Record.Size));
     225        3868 :   error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
     226             :                              Record.hasUniqueName()));
     227             : 
     228        2901 :   return Error::success();
     229             : }
     230             : 
     231          29 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, UnionRecord &Record) {
     232          58 :   error(IO.mapInteger(Record.MemberCount));
     233          87 :   error(IO.mapEnum(Record.Options));
     234          87 :   error(IO.mapInteger(Record.FieldList));
     235          87 :   error(IO.mapEncodedInteger(Record.Size));
     236         116 :   error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
     237             :                              Record.hasUniqueName()));
     238             : 
     239          87 :   return Error::success();
     240             : }
     241             : 
     242         274 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, EnumRecord &Record) {
     243         822 :   error(IO.mapInteger(Record.MemberCount));
     244         822 :   error(IO.mapEnum(Record.Options));
     245         822 :   error(IO.mapInteger(Record.UnderlyingType));
     246         822 :   error(IO.mapInteger(Record.FieldList));
     247        1096 :   error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
     248             :                              Record.hasUniqueName()));
     249             : 
     250         822 :   return Error::success();
     251             : }
     252             : 
     253          26 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, BitFieldRecord &Record) {
     254          78 :   error(IO.mapInteger(Record.Type));
     255          78 :   error(IO.mapInteger(Record.BitSize));
     256          78 :   error(IO.mapInteger(Record.BitOffset));
     257             : 
     258          78 :   return Error::success();
     259             : }
     260             : 
     261          42 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     262             :                                           VFTableShapeRecord &Record) {
     263             :   uint16_t Size;
     264          84 :   if (IO.isWriting()) {
     265           9 :     ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
     266           9 :     Size = Slots.size();
     267          27 :     error(IO.mapInteger(Size));
     268             : 
     269          16 :     for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
     270          14 :       uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
     271           7 :       if ((SlotIndex + 1) < Slots.size()) {
     272           2 :         Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
     273             :       }
     274          21 :       error(IO.mapInteger(Byte));
     275             :     }
     276             :   } else {
     277          99 :     error(IO.mapInteger(Size));
     278          68 :     for (uint16_t I = 0; I < Size; I += 2) {
     279             :       uint8_t Byte;
     280         105 :       error(IO.mapInteger(Byte));
     281          70 :       Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte & 0xF));
     282          35 :       if ((I + 1) < Size)
     283          20 :         Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte >> 4));
     284             :     }
     285             :   }
     286             : 
     287         126 :   return Error::success();
     288             : }
     289             : 
     290          13 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, VFTableRecord &Record) {
     291          39 :   error(IO.mapInteger(Record.CompleteClass));
     292          39 :   error(IO.mapInteger(Record.OverriddenVFTable));
     293          39 :   error(IO.mapInteger(Record.VFPtrOffset));
     294          13 :   uint32_t NamesLen = 0;
     295          26 :   if (IO.isWriting()) {
     296          10 :     for (auto Name : Record.MethodNames)
     297           2 :       NamesLen += Name.size() + 1;
     298             :   }
     299          39 :   error(IO.mapInteger(NamesLen));
     300          69 :   error(IO.mapVectorTail(
     301             :       Record.MethodNames,
     302             :       [](CodeViewRecordIO &IO, StringRef &S) { return IO.mapStringZ(S); }));
     303             : 
     304          39 :   return Error::success();
     305             : }
     306             : 
     307         595 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, StringIdRecord &Record) {
     308        1785 :   error(IO.mapInteger(Record.Id));
     309        1785 :   error(IO.mapStringZ(Record.String));
     310             : 
     311        1190 :   return Error::success();
     312             : }
     313             : 
     314         296 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     315             :                                           UdtSourceLineRecord &Record) {
     316         888 :   error(IO.mapInteger(Record.UDT));
     317         888 :   error(IO.mapInteger(Record.SourceFile));
     318         888 :   error(IO.mapInteger(Record.LineNumber));
     319             : 
     320         888 :   return Error::success();
     321             : }
     322             : 
     323          45 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     324             :                                           UdtModSourceLineRecord &Record) {
     325         135 :   error(IO.mapInteger(Record.UDT));
     326         135 :   error(IO.mapInteger(Record.SourceFile));
     327         135 :   error(IO.mapInteger(Record.LineNumber));
     328         135 :   error(IO.mapInteger(Record.Module));
     329             : 
     330         135 :   return Error::success();
     331             : }
     332             : 
     333         510 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, FuncIdRecord &Record) {
     334        1530 :   error(IO.mapInteger(Record.ParentScope));
     335        1530 :   error(IO.mapInteger(Record.FunctionType));
     336        1530 :   error(IO.mapStringZ(Record.Name));
     337             : 
     338        1530 :   return Error::success();
     339             : }
     340             : 
     341         100 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     342             :                                           MemberFuncIdRecord &Record) {
     343         300 :   error(IO.mapInteger(Record.ClassType));
     344         300 :   error(IO.mapInteger(Record.FunctionType));
     345         300 :   error(IO.mapStringZ(Record.Name));
     346             : 
     347         300 :   return Error::success();
     348             : }
     349             : 
     350          68 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     351             :                                           BuildInfoRecord &Record) {
     352         540 :   error(IO.mapVectorN<uint16_t>(
     353             :       Record.ArgIndices,
     354             :       [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
     355             : 
     356         204 :   return Error::success();
     357             : }
     358             : 
     359         185 : 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         740 :   error(IO.mapVectorTail(Record.Methods, MapOneMethodRecord(true)));
     364             : 
     365         555 :   return Error::success();
     366             : }
     367             : 
     368         458 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     369             :                                           FieldListRecord &Record) {
     370        1374 :   error(IO.mapByteVectorTail(Record.Data));
     371             : 
     372        1374 :   return Error::success();
     373             : }
     374             : 
     375           7 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     376             :                                           TypeServer2Record &Record) {
     377          21 :   error(IO.mapGuid(Record.Guid));
     378          21 :   error(IO.mapInteger(Record.Age));
     379          21 :   error(IO.mapStringZ(Record.Name));
     380          21 :   return Error::success();
     381             : }
     382             : 
     383           1 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, LabelRecord &Record) {
     384           3 :   error(IO.mapEnum(Record.Mode));
     385           3 :   return Error::success();
     386             : }
     387             : 
     388          42 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     389             :                                           BaseClassRecord &Record) {
     390         126 :   error(IO.mapInteger(Record.Attrs.Attrs));
     391         126 :   error(IO.mapInteger(Record.Type));
     392         126 :   error(IO.mapEncodedInteger(Record.Offset));
     393             : 
     394         126 :   return Error::success();
     395             : }
     396             : 
     397       12385 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     398             :                                           EnumeratorRecord &Record) {
     399       37155 :   error(IO.mapInteger(Record.Attrs.Attrs));
     400             : 
     401             :   // FIXME: Handle full APInt such as __int128.
     402       37155 :   error(IO.mapEncodedInteger(Record.Value));
     403       37155 :   error(IO.mapStringZ(Record.Name));
     404             : 
     405       37155 :   return Error::success();
     406             : }
     407             : 
     408         671 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     409             :                                           DataMemberRecord &Record) {
     410        2013 :   error(IO.mapInteger(Record.Attrs.Attrs));
     411        2013 :   error(IO.mapInteger(Record.Type));
     412        2013 :   error(IO.mapEncodedInteger(Record.FieldOffset));
     413        2013 :   error(IO.mapStringZ(Record.Name));
     414             : 
     415        2013 :   return Error::success();
     416             : }
     417             : 
     418         136 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     419             :                                           OverloadedMethodRecord &Record) {
     420         408 :   error(IO.mapInteger(Record.NumOverloads));
     421         408 :   error(IO.mapInteger(Record.MethodList));
     422         408 :   error(IO.mapStringZ(Record.Name));
     423             : 
     424         408 :   return Error::success();
     425             : }
     426             : 
     427         156 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     428             :                                           OneMethodRecord &Record) {
     429         156 :   MapOneMethodRecord Mapper(false);
     430         156 :   return Mapper(IO, Record);
     431             : }
     432             : 
     433         168 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     434             :                                           NestedTypeRecord &Record) {
     435         168 :   uint16_t Padding = 0;
     436         504 :   error(IO.mapInteger(Padding));
     437         504 :   error(IO.mapInteger(Record.Type));
     438         504 :   error(IO.mapStringZ(Record.Name));
     439             : 
     440         504 :   return Error::success();
     441             : }
     442             : 
     443          12 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     444             :                                           StaticDataMemberRecord &Record) {
     445             : 
     446          36 :   error(IO.mapInteger(Record.Attrs.Attrs));
     447          36 :   error(IO.mapInteger(Record.Type));
     448          36 :   error(IO.mapStringZ(Record.Name));
     449             : 
     450          36 :   return Error::success();
     451             : }
     452             : 
     453          26 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     454             :                                           VirtualBaseClassRecord &Record) {
     455             : 
     456          78 :   error(IO.mapInteger(Record.Attrs.Attrs));
     457          78 :   error(IO.mapInteger(Record.BaseType));
     458          78 :   error(IO.mapInteger(Record.VBPtrType));
     459          78 :   error(IO.mapEncodedInteger(Record.VBPtrOffset));
     460          78 :   error(IO.mapEncodedInteger(Record.VTableIndex));
     461             : 
     462          78 :   return Error::success();
     463             : }
     464             : 
     465          25 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     466             :                                           VFPtrRecord &Record) {
     467          25 :   uint16_t Padding = 0;
     468          75 :   error(IO.mapInteger(Padding));
     469          75 :   error(IO.mapInteger(Record.Type));
     470             : 
     471          75 :   return Error::success();
     472             : }
     473             : 
     474           6 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     475             :                                           ListContinuationRecord &Record) {
     476           6 :   uint16_t Padding = 0;
     477          18 :   error(IO.mapInteger(Padding));
     478          18 :   error(IO.mapInteger(Record.ContinuationIndex));
     479             : 
     480          18 :   return Error::success();
     481             : }

Generated by: LCOV version 1.13