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

Generated by: LCOV version 1.13