]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
Move all sources from the llvm project into contrib/llvm-project.
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / include / llvm / DebugInfo / CodeView / TypeDeserializer.h
1 //===- TypeDeserializer.h ---------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
10 #define LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
11
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/DebugInfo/CodeView/CodeView.h"
15 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
16 #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
17 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
18 #include "llvm/Support/BinaryByteStream.h"
19 #include "llvm/Support/BinaryStreamReader.h"
20 #include "llvm/Support/Error.h"
21 #include <cassert>
22 #include <cstdint>
23 #include <memory>
24
25 namespace llvm {
26 namespace codeview {
27
28 class TypeDeserializer : public TypeVisitorCallbacks {
29   struct MappingInfo {
30     explicit MappingInfo(ArrayRef<uint8_t> RecordData)
31         : Stream(RecordData, llvm::support::little), Reader(Stream),
32           Mapping(Reader) {}
33
34     BinaryByteStream Stream;
35     BinaryStreamReader Reader;
36     TypeRecordMapping Mapping;
37   };
38
39 public:
40   TypeDeserializer() = default;
41
42   template <typename T> static Error deserializeAs(CVType &CVT, T &Record) {
43     Record.Kind = static_cast<TypeRecordKind>(CVT.kind());
44     MappingInfo I(CVT.content());
45     if (auto EC = I.Mapping.visitTypeBegin(CVT))
46       return EC;
47     if (auto EC = I.Mapping.visitKnownRecord(CVT, Record))
48       return EC;
49     if (auto EC = I.Mapping.visitTypeEnd(CVT))
50       return EC;
51     return Error::success();
52   }
53
54   template <typename T>
55   static Expected<T> deserializeAs(ArrayRef<uint8_t> Data) {
56     const RecordPrefix *Prefix =
57         reinterpret_cast<const RecordPrefix *>(Data.data());
58     TypeRecordKind K =
59         static_cast<TypeRecordKind>(uint16_t(Prefix->RecordKind));
60     T Record(K);
61     CVType CVT(Data);
62     if (auto EC = deserializeAs<T>(CVT, Record))
63       return std::move(EC);
64     return Record;
65   }
66
67   Error visitTypeBegin(CVType &Record) override {
68     assert(!Mapping && "Already in a type mapping!");
69     Mapping = llvm::make_unique<MappingInfo>(Record.content());
70     return Mapping->Mapping.visitTypeBegin(Record);
71   }
72
73   Error visitTypeBegin(CVType &Record, TypeIndex Index) override {
74     return visitTypeBegin(Record);
75   }
76
77   Error visitTypeEnd(CVType &Record) override {
78     assert(Mapping && "Not in a type mapping!");
79     auto EC = Mapping->Mapping.visitTypeEnd(Record);
80     Mapping.reset();
81     return EC;
82   }
83
84 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
85   Error visitKnownRecord(CVType &CVR, Name##Record &Record) override {         \
86     return visitKnownRecordImpl<Name##Record>(CVR, Record);                    \
87   }
88 #define MEMBER_RECORD(EnumName, EnumVal, Name)
89 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
90 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
91 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
92
93 private:
94   template <typename RecordType>
95   Error visitKnownRecordImpl(CVType &CVR, RecordType &Record) {
96     return Mapping->Mapping.visitKnownRecord(CVR, Record);
97   }
98
99   std::unique_ptr<MappingInfo> Mapping;
100 };
101
102 class FieldListDeserializer : public TypeVisitorCallbacks {
103   struct MappingInfo {
104     explicit MappingInfo(BinaryStreamReader &R)
105         : Reader(R), Mapping(Reader), StartOffset(0) {}
106
107     BinaryStreamReader &Reader;
108     TypeRecordMapping Mapping;
109     uint32_t StartOffset;
110   };
111
112 public:
113   explicit FieldListDeserializer(BinaryStreamReader &Reader) : Mapping(Reader) {
114     RecordPrefix Pre(static_cast<uint16_t>(TypeLeafKind::LF_FIELDLIST));
115     CVType FieldList(&Pre, sizeof(Pre));
116     consumeError(Mapping.Mapping.visitTypeBegin(FieldList));
117   }
118
119   ~FieldListDeserializer() override {
120     RecordPrefix Pre(static_cast<uint16_t>(TypeLeafKind::LF_FIELDLIST));
121     CVType FieldList(&Pre, sizeof(Pre));
122     consumeError(Mapping.Mapping.visitTypeEnd(FieldList));
123   }
124
125   Error visitMemberBegin(CVMemberRecord &Record) override {
126     Mapping.StartOffset = Mapping.Reader.getOffset();
127     return Mapping.Mapping.visitMemberBegin(Record);
128   }
129
130   Error visitMemberEnd(CVMemberRecord &Record) override {
131     if (auto EC = Mapping.Mapping.visitMemberEnd(Record))
132       return EC;
133     return Error::success();
134   }
135
136 #define TYPE_RECORD(EnumName, EnumVal, Name)
137 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
138   Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
139     return visitKnownMemberImpl<Name##Record>(CVR, Record);                    \
140   }
141 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
142 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
143 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
144
145 private:
146   template <typename RecordType>
147   Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) {
148     if (auto EC = Mapping.Mapping.visitKnownMember(CVR, Record))
149       return EC;
150
151     uint32_t EndOffset = Mapping.Reader.getOffset();
152     uint32_t RecordLength = EndOffset - Mapping.StartOffset;
153     Mapping.Reader.setOffset(Mapping.StartOffset);
154     if (auto EC = Mapping.Reader.readBytes(CVR.Data, RecordLength))
155       return EC;
156     assert(Mapping.Reader.getOffset() == EndOffset);
157     return Error::success();
158   }
159   MappingInfo Mapping;
160 };
161
162 } // end namespace codeview
163 } // end namespace llvm
164
165 #endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H