]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r304149, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / DebugInfo / CodeView / TypeDeserializer.h
1 //===- TypeDeserializer.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_TYPEDESERIALIZER_H
11 #define LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
12
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/DebugInfo/CodeView/CodeView.h"
16 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
17 #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
18 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
19 #include "llvm/Support/BinaryByteStream.h"
20 #include "llvm/Support/BinaryStreamReader.h"
21 #include "llvm/Support/Error.h"
22 #include <cassert>
23 #include <cstdint>
24 #include <memory>
25
26 namespace llvm {
27 namespace codeview {
28
29 class TypeDeserializer : public TypeVisitorCallbacks {
30   struct MappingInfo {
31     explicit MappingInfo(ArrayRef<uint8_t> RecordData)
32         : Stream(RecordData, llvm::support::little), Reader(Stream),
33           Mapping(Reader) {}
34
35     BinaryByteStream Stream;
36     BinaryStreamReader Reader;
37     TypeRecordMapping Mapping;
38   };
39
40 public:
41   TypeDeserializer() = default;
42
43   template <typename T> static Error deserializeAs(CVType &CVT, T &Record) {
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   Error visitTypeBegin(CVType &Record) override {
55     assert(!Mapping && "Already in a type mapping!");
56     Mapping = llvm::make_unique<MappingInfo>(Record.content());
57     return Mapping->Mapping.visitTypeBegin(Record);
58   }
59
60   Error visitTypeBegin(CVType &Record, TypeIndex Index) override {
61     return visitTypeBegin(Record);
62   }
63
64   Error visitTypeEnd(CVType &Record) override {
65     assert(Mapping && "Not in a type mapping!");
66     auto EC = Mapping->Mapping.visitTypeEnd(Record);
67     Mapping.reset();
68     return EC;
69   }
70
71 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
72   Error visitKnownRecord(CVType &CVR, Name##Record &Record) override {         \
73     return visitKnownRecordImpl<Name##Record>(CVR, Record);                    \
74   }
75 #define MEMBER_RECORD(EnumName, EnumVal, Name)
76 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
77 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
78 #include "TypeRecords.def"
79
80 private:
81   template <typename RecordType>
82   Error visitKnownRecordImpl(CVType &CVR, RecordType &Record) {
83     return Mapping->Mapping.visitKnownRecord(CVR, Record);
84   }
85
86   std::unique_ptr<MappingInfo> Mapping;
87 };
88
89 class FieldListDeserializer : public TypeVisitorCallbacks {
90   struct MappingInfo {
91     explicit MappingInfo(BinaryStreamReader &R)
92         : Reader(R), Mapping(Reader), StartOffset(0) {}
93
94     BinaryStreamReader &Reader;
95     TypeRecordMapping Mapping;
96     uint32_t StartOffset;
97   };
98
99 public:
100   explicit FieldListDeserializer(BinaryStreamReader &Reader) : Mapping(Reader) {
101     CVType FieldList;
102     FieldList.Type = TypeLeafKind::LF_FIELDLIST;
103     consumeError(Mapping.Mapping.visitTypeBegin(FieldList));
104   }
105
106   ~FieldListDeserializer() override {
107     CVType FieldList;
108     FieldList.Type = TypeLeafKind::LF_FIELDLIST;
109     consumeError(Mapping.Mapping.visitTypeEnd(FieldList));
110   }
111
112   Error visitMemberBegin(CVMemberRecord &Record) override {
113     Mapping.StartOffset = Mapping.Reader.getOffset();
114     return Mapping.Mapping.visitMemberBegin(Record);
115   }
116
117   Error visitMemberEnd(CVMemberRecord &Record) override {
118     if (auto EC = Mapping.Mapping.visitMemberEnd(Record))
119       return EC;
120     return Error::success();
121   }
122
123 #define TYPE_RECORD(EnumName, EnumVal, Name)
124 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
125   Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
126     return visitKnownMemberImpl<Name##Record>(CVR, Record);                    \
127   }
128 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
129 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
130 #include "TypeRecords.def"
131
132 private:
133   template <typename RecordType>
134   Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) {
135     if (auto EC = Mapping.Mapping.visitKnownMember(CVR, Record))
136       return EC;
137
138     uint32_t EndOffset = Mapping.Reader.getOffset();
139     uint32_t RecordLength = EndOffset - Mapping.StartOffset;
140     Mapping.Reader.setOffset(Mapping.StartOffset);
141     if (auto EC = Mapping.Reader.readBytes(CVR.Data, RecordLength))
142       return EC;
143     assert(Mapping.Reader.getOffset() == EndOffset);
144     return Error::success();
145   }
146   MappingInfo Mapping;
147 };
148
149 } // end namespace codeview
150 } // end namespace llvm
151
152 #endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H