LLVM  10.0.0svn
TypeDeserializer.h
Go to the documentation of this file.
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"
20 #include "llvm/Support/Error.h"
21 #include <cassert>
22 #include <cstdint>
23 #include <memory>
24 
25 namespace llvm {
26 namespace codeview {
27 
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>
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 
68  assert(!Mapping && "Already in a type mapping!");
69  Mapping = std::make_unique<MappingInfo>(Record.content());
70  return Mapping->Mapping.visitTypeBegin(Record);
71  }
72 
74  return visitTypeBegin(Record);
75  }
76 
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 
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 
120  RecordPrefix Pre(static_cast<uint16_t>(TypeLeafKind::LF_FIELDLIST));
121  CVType FieldList(&Pre, sizeof(Pre));
122  consumeError(Mapping.Mapping.visitTypeEnd(FieldList));
123  }
124 
126  Mapping.StartOffset = Mapping.Reader.getOffset();
127  return Mapping.Mapping.visitMemberBegin(Record);
128  }
129 
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
Kind kind() const
Definition: CVRecord.h:43
An implementation of BinaryStream which holds its entire data set in a single contiguous buffer...
This class represents lattice values for constants.
Definition: AllocatorList.h:23
ArrayRef< uint8_t > content() const
Definition: CVRecord.h:57
Tagged union holding either a T or a Error.
Definition: yaml2obj.h:21
Error visitTypeBegin(CVType &Record) override
Paired begin/end actions for all types.
A 32-bit type reference.
Definition: TypeIndex.h:95
TypeRecordKind
Distinguishes individual records in .debug$T or .debug$P section or PDB type stream.
Definition: CodeView.h:26
Error visitMemberBegin(CVMemberRecord &Record) override
Error visitTypeEnd(CVType &Record) override
static Error deserializeAs(CVType &CVT, T &Record)
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1001
const T * data() const
Definition: ArrayRef.h:145
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
Error visitTypeBegin(CVType &Record, TypeIndex Index) override
#define I(x, y, z)
Definition: MD5.cpp:58
Error visitMemberEnd(CVMemberRecord &Record) override
static Expected< T > deserializeAs(ArrayRef< uint8_t > Data)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
Provides read only access to a subclass of BinaryStream.
FieldListDeserializer(BinaryStreamReader &Reader)