LCOV - code coverage report
Current view: top level - lib/DebugInfo/CodeView - CVTypeVisitor.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 68 109 62.4 %
Date: 2017-09-14 15:23:50 Functions: 46 53 86.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- CVTypeVisitor.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/CVTypeVisitor.h"
      11             : 
      12             : #include "llvm/ADT/TinyPtrVector.h"
      13             : #include "llvm/DebugInfo/CodeView/CodeViewError.h"
      14             : #include "llvm/DebugInfo/CodeView/TypeCollection.h"
      15             : #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
      16             : #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
      17             : #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
      18             : #include "llvm/Support/BinaryByteStream.h"
      19             : #include "llvm/Support/BinaryStreamReader.h"
      20             : 
      21             : using namespace llvm;
      22             : using namespace llvm::codeview;
      23             : 
      24             : 
      25             : template <typename T>
      26        4396 : static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) {
      27        4396 :   TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type);
      28        5621 :   T KnownRecord(RK);
      29       13188 :   if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
      30           0 :     return EC;
      31       13188 :   return Error::success();
      32             : }
      33             : 
      34             : template <typename T>
      35        7444 : static Error visitKnownMember(CVMemberRecord &Record,
      36             :                               TypeVisitorCallbacks &Callbacks) {
      37        7444 :   TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
      38       13966 :   T KnownRecord(RK);
      39       22332 :   if (auto EC = Callbacks.visitKnownMember(Record, KnownRecord))
      40           0 :     return EC;
      41       22332 :   return Error::success();
      42             : }
      43             : 
      44        7444 : static Error visitMemberRecord(CVMemberRecord &Record,
      45             :                                TypeVisitorCallbacks &Callbacks) {
      46       22332 :   if (auto EC = Callbacks.visitMemberBegin(Record))
      47           0 :     return EC;
      48             : 
      49        7444 :   switch (Record.Kind) {
      50           0 :   default:
      51           0 :     if (auto EC = Callbacks.visitUnknownMember(Record))
      52           0 :       return EC;
      53             :     break;
      54             : #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
      55             :   case EnumName: {                                                             \
      56             :     if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks))           \
      57             :       return EC;                                                               \
      58             :     break;                                                                     \
      59             :   }
      60             : #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
      61             :   MEMBER_RECORD(EnumVal, EnumVal, AliasName)
      62             : #define TYPE_RECORD(EnumName, EnumVal, Name)
      63             : #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
      64             : #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
      65             :   }
      66             : 
      67       22332 :   if (auto EC = Callbacks.visitMemberEnd(Record))
      68           0 :     return EC;
      69             : 
      70       22332 :   return Error::success();
      71             : }
      72             : 
      73             : namespace {
      74             : 
      75             : class CVTypeVisitor {
      76             : public:
      77             :   explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
      78             : 
      79             :   Error visitTypeRecord(CVType &Record, TypeIndex Index);
      80             :   Error visitTypeRecord(CVType &Record);
      81             : 
      82             :   /// Visits the type records in Data. Sets the error flag on parse failures.
      83             :   Error visitTypeStream(const CVTypeArray &Types);
      84             :   Error visitTypeStream(CVTypeRange Types);
      85             :   Error visitTypeStream(TypeCollection &Types);
      86             : 
      87             :   Error visitMemberRecord(CVMemberRecord Record);
      88             :   Error visitFieldListMemberStream(BinaryStreamReader &Stream);
      89             : 
      90             : private:
      91             :   Error finishVisitation(CVType &Record);
      92             : 
      93             :   /// The interface to the class that gets notified of each visitation.
      94             :   TypeVisitorCallbacks &Callbacks;
      95             : };
      96             : 
      97        2658 : CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
      98        2658 :     : Callbacks(Callbacks) {}
      99             : 
     100        4396 : Error CVTypeVisitor::finishVisitation(CVType &Record) {
     101        4396 :   switch (Record.Type) {
     102           0 :   default:
     103           0 :     if (auto EC = Callbacks.visitUnknownType(Record))
     104           0 :       return EC;
     105             :     break;
     106             : #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
     107             :   case EnumName: {                                                             \
     108             :     if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks))           \
     109             :       return EC;                                                               \
     110             :     break;                                                                     \
     111             :   }
     112             : #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                  \
     113             :   TYPE_RECORD(EnumVal, EnumVal, AliasName)
     114             : #define MEMBER_RECORD(EnumName, EnumVal, Name)
     115             : #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
     116             : #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
     117             :   }
     118             : 
     119       13188 :   if (auto EC = Callbacks.visitTypeEnd(Record))
     120           0 :     return EC;
     121             : 
     122       13188 :   return Error::success();
     123             : }
     124             : 
     125        4378 : Error CVTypeVisitor::visitTypeRecord(CVType &Record, TypeIndex Index) {
     126       13134 :   if (auto EC = Callbacks.visitTypeBegin(Record, Index))
     127           0 :     return EC;
     128             : 
     129        4378 :   return finishVisitation(Record);
     130             : }
     131             : 
     132          18 : Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
     133          54 :   if (auto EC = Callbacks.visitTypeBegin(Record))
     134           0 :     return EC;
     135             : 
     136          18 :   return finishVisitation(Record);
     137             : }
     138             : 
     139             : Error CVTypeVisitor::visitMemberRecord(CVMemberRecord Record) {
     140           0 :   return ::visitMemberRecord(Record, Callbacks);
     141             : }
     142             : 
     143             : /// Visits the type records in Data. Sets the error flag on parse failures.
     144           0 : Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
     145           0 :   for (auto I : Types) {
     146           0 :     if (auto EC = visitTypeRecord(I))
     147           0 :       return EC;
     148             :   }
     149           0 :   return Error::success();
     150             : }
     151             : 
     152           0 : Error CVTypeVisitor::visitTypeStream(CVTypeRange Types) {
     153           0 :   for (auto I : Types) {
     154           0 :     if (auto EC = visitTypeRecord(I))
     155           0 :       return EC;
     156             :   }
     157           0 :   return Error::success();
     158             : }
     159             : 
     160          99 : Error CVTypeVisitor::visitTypeStream(TypeCollection &Types) {
     161         198 :   Optional<TypeIndex> I = Types.getFirst();
     162        2284 :   while (I) {
     163        6555 :     CVType Type = Types.getType(*I);
     164        6555 :     if (auto EC = visitTypeRecord(Type, *I))
     165           0 :       return EC;
     166        8740 :     I = Types.getNext(*I);
     167             :   }
     168         297 :   return Error::success();
     169             : }
     170             : 
     171         348 : Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader &Reader) {
     172             :   TypeLeafKind Leaf;
     173        7792 :   while (!Reader.empty()) {
     174       22332 :     if (auto EC = Reader.readEnum(Leaf))
     175           0 :       return EC;
     176             : 
     177        7444 :     CVMemberRecord Record;
     178        7444 :     Record.Kind = Leaf;
     179       22332 :     if (auto EC = ::visitMemberRecord(Record, Callbacks))
     180           0 :       return EC;
     181             :   }
     182             : 
     183        1044 :   return Error::success();
     184             : }
     185             : 
     186        1392 : struct FieldListVisitHelper {
     187         348 :   FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef<uint8_t> Data,
     188             :                        VisitorDataSource Source)
     189         348 :       : Stream(Data, llvm::support::little), Reader(Stream),
     190             :         Deserializer(Reader),
     191        1392 :         Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
     192         348 :     if (Source == VDS_BytesPresent) {
     193         696 :       Pipeline.addCallbackToPipeline(Deserializer);
     194         348 :       Pipeline.addCallbackToPipeline(Callbacks);
     195             :     }
     196         348 :   }
     197             : 
     198             :   BinaryByteStream Stream;
     199             :   BinaryStreamReader Reader;
     200             :   FieldListDeserializer Deserializer;
     201             :   TypeVisitorCallbackPipeline Pipeline;
     202             :   CVTypeVisitor Visitor;
     203             : };
     204             : 
     205        6930 : struct VisitHelper {
     206        2310 :   VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source)
     207        9240 :       : Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
     208        2310 :     if (Source == VDS_BytesPresent) {
     209        4620 :       Pipeline.addCallbackToPipeline(Deserializer);
     210        2310 :       Pipeline.addCallbackToPipeline(Callbacks);
     211             :     }
     212        2310 :   }
     213             : 
     214             :   TypeDeserializer Deserializer;
     215             :   TypeVisitorCallbackPipeline Pipeline;
     216             :   CVTypeVisitor Visitor;
     217             : };
     218             : }
     219             : 
     220        2193 : Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index,
     221             :                                       TypeVisitorCallbacks &Callbacks,
     222             :                                       VisitorDataSource Source) {
     223        4386 :   VisitHelper V(Callbacks, Source);
     224        4386 :   return V.Visitor.visitTypeRecord(Record, Index);
     225             : }
     226             : 
     227          18 : Error llvm::codeview::visitTypeRecord(CVType &Record,
     228             :                                       TypeVisitorCallbacks &Callbacks,
     229             :                                       VisitorDataSource Source) {
     230          36 :   VisitHelper V(Callbacks, Source);
     231          36 :   return V.Visitor.visitTypeRecord(Record);
     232             : }
     233             : 
     234           0 : Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
     235             :                                       TypeVisitorCallbacks &Callbacks,
     236             :                                       VisitorDataSource Source) {
     237           0 :   VisitHelper V(Callbacks, Source);
     238           0 :   return V.Visitor.visitTypeStream(Types);
     239             : }
     240             : 
     241           0 : Error llvm::codeview::visitTypeStream(CVTypeRange Types,
     242             :                                       TypeVisitorCallbacks &Callbacks) {
     243           0 :   VisitHelper V(Callbacks, VDS_BytesPresent);
     244           0 :   return V.Visitor.visitTypeStream(Types);
     245             : }
     246             : 
     247          99 : Error llvm::codeview::visitTypeStream(TypeCollection &Types,
     248             :                                       TypeVisitorCallbacks &Callbacks) {
     249             :   // When the internal visitor calls Types.getType(Index) the interface is
     250             :   // required to return a CVType with the bytes filled out.  So we can assume
     251             :   // that the bytes will be present when individual records are visited.
     252         198 :   VisitHelper V(Callbacks, VDS_BytesPresent);
     253         198 :   return V.Visitor.visitTypeStream(Types);
     254             : }
     255             : 
     256           0 : Error llvm::codeview::visitMemberRecord(CVMemberRecord Record,
     257             :                                         TypeVisitorCallbacks &Callbacks,
     258             :                                         VisitorDataSource Source) {
     259           0 :   FieldListVisitHelper V(Callbacks, Record.Data, Source);
     260           0 :   return V.Visitor.visitMemberRecord(Record);
     261             : }
     262             : 
     263           0 : Error llvm::codeview::visitMemberRecord(TypeLeafKind Kind,
     264             :                                         ArrayRef<uint8_t> Record,
     265             :                                         TypeVisitorCallbacks &Callbacks) {
     266           0 :   CVMemberRecord R;
     267           0 :   R.Data = Record;
     268           0 :   R.Kind = Kind;
     269           0 :   return visitMemberRecord(R, Callbacks, VDS_BytesPresent);
     270             : }
     271             : 
     272         348 : Error llvm::codeview::visitMemberRecordStream(ArrayRef<uint8_t> FieldList,
     273             :                                               TypeVisitorCallbacks &Callbacks) {
     274         696 :   FieldListVisitHelper V(Callbacks, FieldList, VDS_BytesPresent);
     275         696 :   return V.Visitor.visitFieldListMemberStream(V.Reader);
     276             : }

Generated by: LCOV version 1.13