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