LCOV - code coverage report
Current view: top level - include/llvm/DebugInfo/CodeView - TypeSerializer.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 17 19 89.5 %
Date: 2017-09-14 15:23:50 Functions: 11 12 91.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- TypeSerializer.h -----------------------------------------*- 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             : #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZER_H
      11             : #define LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZER_H
      12             : 
      13             : #include "llvm/ADT/ArrayRef.h"
      14             : #include "llvm/ADT/Optional.h"
      15             : #include "llvm/ADT/SmallVector.h"
      16             : #include "llvm/DebugInfo/CodeView/CodeView.h"
      17             : #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
      18             : #include "llvm/DebugInfo/CodeView/TypeIndex.h"
      19             : #include "llvm/DebugInfo/CodeView/TypeRecord.h"
      20             : #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
      21             : #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
      22             : #include "llvm/Support/Allocator.h"
      23             : #include "llvm/Support/BinaryByteStream.h"
      24             : #include "llvm/Support/BinaryStreamWriter.h"
      25             : #include "llvm/Support/Error.h"
      26             : #include <cassert>
      27             : #include <cstdint>
      28             : #include <memory>
      29             : #include <vector>
      30             : 
      31             : namespace llvm {
      32             : namespace codeview {
      33             : 
      34             : class TypeHasher;
      35             : 
      36       60300 : class TypeSerializer : public TypeVisitorCallbacks {
      37             :   struct SubRecord {
      38        6183 :     SubRecord(TypeLeafKind K, uint32_t S) : Kind(K), Size(S) {}
      39             : 
      40             :     TypeLeafKind Kind;
      41             :     uint32_t Size = 0;
      42             :   };
      43       20904 :   struct RecordSegment {
      44             :     SmallVector<SubRecord, 16> SubRecords;
      45             : 
      46             :     uint32_t length() const {
      47       12370 :       uint32_t L = sizeof(RecordPrefix);
      48     7508053 :       for (const auto &R : SubRecords) {
      49     7470947 :         L += R.Size;
      50             :       }
      51             :       return L;
      52             :     }
      53             :   };
      54             : 
      55             :   using MutableRecordList = SmallVector<MutableArrayRef<uint8_t>, 2>;
      56             : 
      57             :   static constexpr uint8_t ContinuationLength = 8;
      58             :   BumpPtrAllocator &RecordStorage;
      59             :   RecordSegment CurrentSegment;
      60             :   MutableRecordList FieldListSegments;
      61             : 
      62             :   Optional<TypeLeafKind> TypeKind;
      63             :   Optional<TypeLeafKind> MemberKind;
      64             :   std::vector<uint8_t> RecordBuffer;
      65             :   MutableBinaryByteStream Stream;
      66             :   BinaryStreamWriter Writer;
      67             :   TypeRecordMapping Mapping;
      68             : 
      69             :   /// Private type record hashing implementation details are handled here.
      70             :   std::unique_ptr<TypeHasher> Hasher;
      71             : 
      72             :   /// Contains a list of all records indexed by TypeIndex.toArrayIndex().
      73             :   SmallVector<ArrayRef<uint8_t>, 2> SeenRecords;
      74             : 
      75             :   /// Temporary storage that we use to copy a record's data while re-writing
      76             :   /// its type indices.
      77             :   SmallVector<uint8_t, 256> RemapStorage;
      78             : 
      79             :   TypeIndex nextTypeIndex() const;
      80             : 
      81             :   bool isInFieldList() const;
      82             :   MutableArrayRef<uint8_t> getCurrentSubRecordData();
      83             :   MutableArrayRef<uint8_t> getCurrentRecordData();
      84             :   Error writeRecordPrefix(TypeLeafKind Kind);
      85             : 
      86             :   Expected<MutableArrayRef<uint8_t>>
      87             :   addPadding(MutableArrayRef<uint8_t> Record);
      88             : 
      89             : public:
      90             :   explicit TypeSerializer(BumpPtrAllocator &Storage, bool Hash = true);
      91             :   ~TypeSerializer() override;
      92             : 
      93             :   void reset();
      94             : 
      95             :   BumpPtrAllocator &getAllocator() { return RecordStorage; }
      96             : 
      97             :   ArrayRef<ArrayRef<uint8_t>> records() const;
      98             :   TypeIndex insertRecordBytes(ArrayRef<uint8_t> &Record);
      99             :   TypeIndex insertRecord(const RemappedType &Record);
     100             :   Expected<TypeIndex> visitTypeEndGetIndex(CVType &Record);
     101             : 
     102             :   using TypeVisitorCallbacks::visitTypeBegin;
     103             :   Error visitTypeBegin(CVType &Record) override;
     104             :   Error visitTypeEnd(CVType &Record) override;
     105             :   Error visitMemberBegin(CVMemberRecord &Record) override;
     106             :   Error visitMemberEnd(CVMemberRecord &Record) override;
     107             : 
     108             : #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
     109             :   virtual Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \
     110             :     return visitKnownRecordImpl(CVR, Record);                                  \
     111             :   }
     112             : #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
     113             : #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
     114             :   Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
     115             :     return visitKnownMemberImpl<Name##Record>(CVR, Record);                    \
     116             :   }
     117             : #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
     118             : #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
     119             : 
     120             : private:
     121             :   template <typename RecordKind>
     122             :   Error visitKnownRecordImpl(CVType &CVR, RecordKind &Record) {
     123        1614 :     return Mapping.visitKnownRecord(CVR, Record);
     124             :   }
     125             : 
     126             :   template <typename RecordType>
     127        6183 :   Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) {
     128             :     assert(CVR.Kind == static_cast<TypeLeafKind>(Record.getKind()));
     129             : 
     130       24732 :     if (auto EC = Writer.writeEnum(CVR.Kind))
     131           0 :       return EC;
     132             : 
     133       18549 :     if (auto EC = Mapping.visitKnownMember(CVR, Record))
     134           0 :       return EC;
     135             : 
     136             :     // Get all the data that was just written and is yet to be committed to
     137             :     // the current segment.  Then pad it to 4 bytes.
     138        6183 :     MutableArrayRef<uint8_t> ThisRecord = getCurrentSubRecordData();
     139        6183 :     auto ExpectedRecord = addPadding(ThisRecord);
     140        6183 :     if (!ExpectedRecord)
     141             :       return ExpectedRecord.takeError();
     142        6183 :     ThisRecord = *ExpectedRecord;
     143             : 
     144        6183 :     CurrentSegment.SubRecords.emplace_back(CVR.Kind, ThisRecord.size());
     145        6183 :     CVR.Data = ThisRecord;
     146             : 
     147             :     // Both the last subrecord and the total length of this segment should be
     148             :     // multiples of 4.
     149             :     assert(ThisRecord.size() % 4 == 0);
     150             :     assert(CurrentSegment.length() % 4 == 0);
     151             : 
     152       18549 :     return Error::success();
     153             :   }
     154             : };
     155             : 
     156             : } // end namespace codeview
     157             : } // end namespace llvm
     158             : 
     159             : #endif // LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZER_H

Generated by: LCOV version 1.13