]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h
Merge ^/head r312720 through r312893.
[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/DebugInfo/MSF/ByteStream.h"
16 #include "llvm/DebugInfo/MSF/StreamWriter.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   msf::MutableByteStream Stream;
60   msf::StreamWriter 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
74   Expected<MutableArrayRef<uint8_t>>
75   addPadding(MutableArrayRef<uint8_t> Record);
76
77 public:
78   explicit TypeSerializer(BumpPtrAllocator &Storage);
79
80   ArrayRef<MutableArrayRef<uint8_t>> records() const;
81   TypeIndex getLastTypeIndex() const;
82   TypeIndex insertRecordBytes(MutableArrayRef<uint8_t> Record);
83   Expected<TypeIndex> visitTypeEndGetIndex(CVType &Record);
84
85   Error visitTypeBegin(CVType &Record) override;
86   Error visitTypeEnd(CVType &Record) override;
87   Error visitMemberBegin(CVMemberRecord &Record) override;
88   Error visitMemberEnd(CVMemberRecord &Record) override;
89
90 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
91   virtual Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \
92     return visitKnownRecordImpl(CVR, Record);                                  \
93   }
94 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
95 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
96   Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
97     return visitKnownMemberImpl<Name##Record>(CVR, Record);                    \
98   }
99 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
100 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
101
102 private:
103   template <typename RecordKind>
104   Error visitKnownRecordImpl(CVType &CVR, RecordKind &Record) {
105     return Mapping.visitKnownRecord(CVR, Record);
106   }
107
108   template <typename RecordType>
109   Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) {
110     assert(CVR.Kind == static_cast<TypeLeafKind>(Record.getKind()));
111
112     if (auto EC = Writer.writeEnum(CVR.Kind))
113       return EC;
114
115     if (auto EC = Mapping.visitKnownMember(CVR, Record))
116       return EC;
117
118     // Get all the data that was just written and is yet to be committed to
119     // the current segment.  Then pad it to 4 bytes.
120     MutableArrayRef<uint8_t> ThisRecord = getCurrentSubRecordData();
121     auto ExpectedRecord = addPadding(ThisRecord);
122     if (!ExpectedRecord)
123       return ExpectedRecord.takeError();
124     ThisRecord = *ExpectedRecord;
125
126     CurrentSegment.SubRecords.emplace_back(CVR.Kind, ThisRecord.size());
127     CVR.Data = ThisRecord;
128
129     // Both the last subrecord and the total length of this segment should be
130     // multiples of 4.
131     assert(ThisRecord.size() % 4 == 0);
132     assert(CurrentSegment.length() % 4 == 0);
133
134     return Error::success();
135   }
136 };
137 }
138 }
139
140 #endif