]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
Merge ^/head r318560 through r318657.
[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   Error visitTypeBegin(CVType &Record) override {
44     assert(!Mapping && "Already in a type mapping!");
45     Mapping = llvm::make_unique<MappingInfo>(Record.content());
46     return Mapping->Mapping.visitTypeBegin(Record);
47   }
48
49   Error visitTypeBegin(CVType &Record, TypeIndex Index) override {
50     return visitTypeBegin(Record);
51   }
52
53   Error visitTypeEnd(CVType &Record) override {
54     assert(Mapping && "Not in a type mapping!");
55     auto EC = Mapping->Mapping.visitTypeEnd(Record);
56     Mapping.reset();
57     return EC;
58   }
59
60 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
61   Error visitKnownRecord(CVType &CVR, Name##Record &Record) override {         \
62     return visitKnownRecordImpl<Name##Record>(CVR, Record);                    \
63   }
64 #define MEMBER_RECORD(EnumName, EnumVal, Name)
65 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
66 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
67 #include "TypeRecords.def"
68
69 private:
70   template <typename RecordType>
71   Error visitKnownRecordImpl(CVType &CVR, RecordType &Record) {
72     return Mapping->Mapping.visitKnownRecord(CVR, Record);
73   }
74
75   std::unique_ptr<MappingInfo> Mapping;
76 };
77
78 class FieldListDeserializer : public TypeVisitorCallbacks {
79   struct MappingInfo {
80     explicit MappingInfo(BinaryStreamReader &R)
81         : Reader(R), Mapping(Reader), StartOffset(0) {}
82
83     BinaryStreamReader &Reader;
84     TypeRecordMapping Mapping;
85     uint32_t StartOffset;
86   };
87
88 public:
89   explicit FieldListDeserializer(BinaryStreamReader &Reader) : Mapping(Reader) {
90     CVType FieldList;
91     FieldList.Type = TypeLeafKind::LF_FIELDLIST;
92     consumeError(Mapping.Mapping.visitTypeBegin(FieldList));
93   }
94
95   ~FieldListDeserializer() override {
96     CVType FieldList;
97     FieldList.Type = TypeLeafKind::LF_FIELDLIST;
98     consumeError(Mapping.Mapping.visitTypeEnd(FieldList));
99   }
100
101   Error visitMemberBegin(CVMemberRecord &Record) override {
102     Mapping.StartOffset = Mapping.Reader.getOffset();
103     return Mapping.Mapping.visitMemberBegin(Record);
104   }
105
106   Error visitMemberEnd(CVMemberRecord &Record) override {
107     if (auto EC = Mapping.Mapping.visitMemberEnd(Record))
108       return EC;
109     return Error::success();
110   }
111
112 #define TYPE_RECORD(EnumName, EnumVal, Name)
113 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
114   Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
115     return visitKnownMemberImpl<Name##Record>(CVR, Record);                    \
116   }
117 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
118 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
119 #include "TypeRecords.def"
120
121 private:
122   template <typename RecordType>
123   Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) {
124     if (auto EC = Mapping.Mapping.visitKnownMember(CVR, Record))
125       return EC;
126
127     uint32_t EndOffset = Mapping.Reader.getOffset();
128     uint32_t RecordLength = EndOffset - Mapping.StartOffset;
129     Mapping.Reader.setOffset(Mapping.StartOffset);
130     if (auto EC = Mapping.Reader.readBytes(CVR.Data, RecordLength))
131       return EC;
132     assert(Mapping.Reader.getOffset() == EndOffset);
133     return Error::success();
134   }
135   MappingInfo Mapping;
136 };
137
138 } // end namespace codeview
139 } // end namespace llvm
140
141 #endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H