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

Generated by: LCOV version 1.13