1 //===- TypeDeserializer.h ---------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
11 #define LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
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"
29 class TypeDeserializer : public TypeVisitorCallbacks {
31 explicit MappingInfo(ArrayRef<uint8_t> RecordData)
32 : Stream(RecordData, llvm::support::little), Reader(Stream),
35 BinaryByteStream Stream;
36 BinaryStreamReader Reader;
37 TypeRecordMapping Mapping;
41 TypeDeserializer() = default;
43 template <typename T> static Error deserializeAs(CVType &CVT, T &Record) {
44 MappingInfo I(CVT.content());
45 if (auto EC = I.Mapping.visitTypeBegin(CVT))
47 if (auto EC = I.Mapping.visitKnownRecord(CVT, Record))
49 if (auto EC = I.Mapping.visitTypeEnd(CVT))
51 return Error::success();
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);
60 Error visitTypeBegin(CVType &Record, TypeIndex Index) override {
61 return visitTypeBegin(Record);
64 Error visitTypeEnd(CVType &Record) override {
65 assert(Mapping && "Not in a type mapping!");
66 auto EC = Mapping->Mapping.visitTypeEnd(Record);
71 #define TYPE_RECORD(EnumName, EnumVal, Name) \
72 Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \
73 return visitKnownRecordImpl<Name##Record>(CVR, Record); \
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"
81 template <typename RecordType>
82 Error visitKnownRecordImpl(CVType &CVR, RecordType &Record) {
83 return Mapping->Mapping.visitKnownRecord(CVR, Record);
86 std::unique_ptr<MappingInfo> Mapping;
89 class FieldListDeserializer : public TypeVisitorCallbacks {
91 explicit MappingInfo(BinaryStreamReader &R)
92 : Reader(R), Mapping(Reader), StartOffset(0) {}
94 BinaryStreamReader &Reader;
95 TypeRecordMapping Mapping;
100 explicit FieldListDeserializer(BinaryStreamReader &Reader) : Mapping(Reader) {
102 FieldList.Type = TypeLeafKind::LF_FIELDLIST;
103 consumeError(Mapping.Mapping.visitTypeBegin(FieldList));
106 ~FieldListDeserializer() override {
108 FieldList.Type = TypeLeafKind::LF_FIELDLIST;
109 consumeError(Mapping.Mapping.visitTypeEnd(FieldList));
112 Error visitMemberBegin(CVMemberRecord &Record) override {
113 Mapping.StartOffset = Mapping.Reader.getOffset();
114 return Mapping.Mapping.visitMemberBegin(Record);
117 Error visitMemberEnd(CVMemberRecord &Record) override {
118 if (auto EC = Mapping.Mapping.visitMemberEnd(Record))
120 return Error::success();
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); \
128 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
129 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
130 #include "TypeRecords.def"
133 template <typename RecordType>
134 Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) {
135 if (auto EC = Mapping.Mapping.visitKnownMember(CVR, Record))
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))
143 assert(Mapping.Reader.getOffset() == EndOffset);
144 return Error::success();
149 } // end namespace codeview
150 } // end namespace llvm
152 #endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H