]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r303571, 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/StringMap.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/Support/Allocator.h"
23 #include "llvm/Support/Error.h"
24
25 namespace llvm {
26
27 namespace codeview {
28
29 class TypeSerializer : public TypeVisitorCallbacks {
30   struct SubRecord {
31     SubRecord(TypeLeafKind K, uint32_t S) : Kind(K), Size(S) {}
32
33     TypeLeafKind Kind;
34     uint32_t Size = 0;
35   };
36   struct RecordSegment {
37     SmallVector<SubRecord, 16> SubRecords;
38
39     uint32_t length() const {
40       uint32_t L = sizeof(RecordPrefix);
41       for (const auto &R : SubRecords) {
42         L += R.Size;
43       }
44       return L;
45     }
46   };
47
48   typedef SmallVector<MutableArrayRef<uint8_t>, 2> RecordList;
49
50   static constexpr uint8_t ContinuationLength = 8;
51   BumpPtrAllocator &RecordStorage;
52   RecordSegment CurrentSegment;
53   RecordList FieldListSegments;
54
55   TypeIndex LastTypeIndex;
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   RecordList SeenRecords;
64   StringMap<TypeIndex> HashedRecords;
65
66   bool isInFieldList() const;
67   TypeIndex calcNextTypeIndex() const;
68   TypeIndex incrementTypeIndex();
69   MutableArrayRef<uint8_t> getCurrentSubRecordData();
70   MutableArrayRef<uint8_t> getCurrentRecordData();
71   Error writeRecordPrefix(TypeLeafKind Kind);
72   TypeIndex insertRecordBytesPrivate(MutableArrayRef<uint8_t> Record);
73   TypeIndex insertRecordBytesWithCopy(CVType &Record,
74                                       MutableArrayRef<uint8_t> Data);
75
76   Expected<MutableArrayRef<uint8_t>>
77   addPadding(MutableArrayRef<uint8_t> Record);
78
79 public:
80   explicit TypeSerializer(BumpPtrAllocator &Storage);
81
82   ArrayRef<MutableArrayRef<uint8_t>> records() const;
83   TypeIndex getLastTypeIndex() const;
84   TypeIndex insertRecordBytes(MutableArrayRef<uint8_t> Record);
85   Expected<TypeIndex> visitTypeEndGetIndex(CVType &Record);
86
87   Error visitTypeBegin(CVType &Record) override;
88   Error visitTypeEnd(CVType &Record) override;
89   Error visitMemberBegin(CVMemberRecord &Record) override;
90   Error visitMemberEnd(CVMemberRecord &Record) override;
91
92 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
93   virtual Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \
94     return visitKnownRecordImpl(CVR, Record);                                  \
95   }
96 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
97 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
98   Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
99     return visitKnownMemberImpl<Name##Record>(CVR, Record);                    \
100   }
101 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
102 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
103
104 private:
105   template <typename RecordKind>
106   Error visitKnownRecordImpl(CVType &CVR, RecordKind &Record) {
107     return Mapping.visitKnownRecord(CVR, Record);
108   }
109
110   template <typename RecordType>
111   Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) {
112     assert(CVR.Kind == static_cast<TypeLeafKind>(Record.getKind()));
113
114     if (auto EC = Writer.writeEnum(CVR.Kind))
115       return EC;
116
117     if (auto EC = Mapping.visitKnownMember(CVR, Record))
118       return EC;
119
120     // Get all the data that was just written and is yet to be committed to
121     // the current segment.  Then pad it to 4 bytes.
122     MutableArrayRef<uint8_t> ThisRecord = getCurrentSubRecordData();
123     auto ExpectedRecord = addPadding(ThisRecord);
124     if (!ExpectedRecord)
125       return ExpectedRecord.takeError();
126     ThisRecord = *ExpectedRecord;
127
128     CurrentSegment.SubRecords.emplace_back(CVR.Kind, ThisRecord.size());
129     CVR.Data = ThisRecord;
130
131     // Both the last subrecord and the total length of this segment should be
132     // multiples of 4.
133     assert(ThisRecord.size() % 4 == 0);
134     assert(CurrentSegment.length() % 4 == 0);
135
136     return Error::success();
137   }
138 };
139 }
140 }
141
142 #endif