LLVM  14.0.0git
CVTypeVisitor.cpp
Go to the documentation of this file.
1 //===- CVTypeVisitor.cpp ----------------------------------------*- 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 
10 
18 
19 using namespace llvm;
20 using namespace llvm::codeview;
21 
22 
23 template <typename T>
25  TypeRecordKind RK = static_cast<TypeRecordKind>(Record.kind());
26  T KnownRecord(RK);
27  if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
28  return EC;
29  return Error::success();
30 }
31 
32 template <typename T>
34  TypeVisitorCallbacks &Callbacks) {
35  TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
36  T KnownRecord(RK);
37  if (auto EC = Callbacks.visitKnownMember(Record, KnownRecord))
38  return EC;
39  return Error::success();
40 }
41 
43  TypeVisitorCallbacks &Callbacks) {
44  if (auto EC = Callbacks.visitMemberBegin(Record))
45  return EC;
46 
47  switch (Record.Kind) {
48  default:
49  if (auto EC = Callbacks.visitUnknownMember(Record))
50  return EC;
51  break;
52 #define MEMBER_RECORD(EnumName, EnumVal, Name) \
53  case EnumName: { \
54  if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks)) \
55  return EC; \
56  break; \
57  }
58 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
59  MEMBER_RECORD(EnumVal, EnumVal, AliasName)
60 #define TYPE_RECORD(EnumName, EnumVal, Name)
61 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
62 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
63  }
64 
65  if (auto EC = Callbacks.visitMemberEnd(Record))
66  return EC;
67 
68  return Error::success();
69 }
70 
71 namespace {
72 
73 class CVTypeVisitor {
74 public:
75  explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
76 
79 
80  /// Visits the type records in Data. Sets the error flag on parse failures.
81  Error visitTypeStream(const CVTypeArray &Types);
84 
86  Error visitFieldListMemberStream(BinaryStreamReader &Stream);
87 
88 private:
90 
91  /// The interface to the class that gets notified of each visitation.
92  TypeVisitorCallbacks &Callbacks;
93 };
94 
95 CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
96  : Callbacks(Callbacks) {}
97 
99  switch (Record.kind()) {
100  default:
101  if (auto EC = Callbacks.visitUnknownType(Record))
102  return EC;
103  break;
104 #define TYPE_RECORD(EnumName, EnumVal, Name) \
105  case EnumName: { \
106  if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks)) \
107  return EC; \
108  break; \
109  }
110 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
111  TYPE_RECORD(EnumVal, EnumVal, AliasName)
112 #define MEMBER_RECORD(EnumName, EnumVal, Name)
113 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
114 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
115  }
116 
117  if (auto EC = Callbacks.visitTypeEnd(Record))
118  return EC;
119 
120  return Error::success();
121 }
122 
124  if (auto EC = Callbacks.visitTypeBegin(Record, Index))
125  return EC;
126 
127  return finishVisitation(Record);
128 }
129 
131  if (auto EC = Callbacks.visitTypeBegin(Record))
132  return EC;
133 
134  return finishVisitation(Record);
135 }
136 
139 }
140 
141 /// Visits the type records in Data. Sets the error flag on parse failures.
143  for (auto I : Types) {
144  if (auto EC = visitTypeRecord(I))
145  return EC;
146  }
147  return Error::success();
148 }
149 
151  for (auto I : Types) {
152  if (auto EC = visitTypeRecord(I))
153  return EC;
154  }
155  return Error::success();
156 }
157 
159  Optional<TypeIndex> I = Types.getFirst();
160  while (I) {
161  CVType Type = Types.getType(*I);
162  if (auto EC = visitTypeRecord(Type, *I))
163  return EC;
164  I = Types.getNext(*I);
165  }
166  return Error::success();
167 }
168 
169 Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader &Reader) {
170  TypeLeafKind Leaf;
171  while (!Reader.empty()) {
172  if (auto EC = Reader.readEnum(Leaf))
173  return EC;
174 
176  Record.Kind = Leaf;
177  if (auto EC = ::visitMemberRecord(Record, Callbacks))
178  return EC;
179  }
180 
181  return Error::success();
182 }
183 
184 struct FieldListVisitHelper {
185  FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef<uint8_t> Data,
187  : Stream(Data, llvm::support::little), Reader(Stream),
188  Deserializer(Reader),
189  Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
190  if (Source == VDS_BytesPresent) {
191  Pipeline.addCallbackToPipeline(Deserializer);
192  Pipeline.addCallbackToPipeline(Callbacks);
193  }
194  }
195 
196  BinaryByteStream Stream;
197  BinaryStreamReader Reader;
198  FieldListDeserializer Deserializer;
200  CVTypeVisitor Visitor;
201 };
202 
203 struct VisitHelper {
204  VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source)
205  : Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
206  if (Source == VDS_BytesPresent) {
207  Pipeline.addCallbackToPipeline(Deserializer);
208  Pipeline.addCallbackToPipeline(Callbacks);
209  }
210  }
211 
212  TypeDeserializer Deserializer;
214  CVTypeVisitor Visitor;
215 };
216 }
217 
219  TypeVisitorCallbacks &Callbacks,
221  VisitHelper V(Callbacks, Source);
222  return V.Visitor.visitTypeRecord(Record, Index);
223 }
224 
226  TypeVisitorCallbacks &Callbacks,
228  VisitHelper V(Callbacks, Source);
229  return V.Visitor.visitTypeRecord(Record);
230 }
231 
233  TypeVisitorCallbacks &Callbacks,
235  VisitHelper V(Callbacks, Source);
236  return V.Visitor.visitTypeStream(Types);
237 }
238 
240  TypeVisitorCallbacks &Callbacks) {
241  VisitHelper V(Callbacks, VDS_BytesPresent);
242  return V.Visitor.visitTypeStream(Types);
243 }
244 
246  TypeVisitorCallbacks &Callbacks) {
247  // When the internal visitor calls Types.getType(Index) the interface is
248  // required to return a CVType with the bytes filled out. So we can assume
249  // that the bytes will be present when individual records are visited.
250  VisitHelper V(Callbacks, VDS_BytesPresent);
251  return V.Visitor.visitTypeStream(Types);
252 }
253 
255  TypeVisitorCallbacks &Callbacks,
257  FieldListVisitHelper V(Callbacks, Record.Data, Source);
258  return V.Visitor.visitMemberRecord(Record);
259 }
260 
263  TypeVisitorCallbacks &Callbacks) {
265  R.Data = Record;
266  R.Kind = Kind;
267  return visitMemberRecord(R, Callbacks, VDS_BytesPresent);
268 }
269 
271  TypeVisitorCallbacks &Callbacks) {
272  FieldListVisitHelper V(Callbacks, FieldList, VDS_BytesPresent);
273  return V.Visitor.visitFieldListMemberStream(V.Reader);
274 }
BinaryStreamReader.h
llvm::BinaryStreamReader::empty
bool empty() const
Definition: BinaryStreamReader.h:253
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::codeview::TypeCollection::getFirst
virtual Optional< TypeIndex > getFirst()=0
T
llvm::codeview::TypeVisitorCallbacks
Definition: TypeVisitorCallbacks.h:18
BinaryByteStream.h
llvm::codeview::VisitorDataSource
VisitorDataSource
Definition: CVTypeVisitor.h:21
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:331
llvm::codeview::VDS_BytesPresent
@ VDS_BytesPresent
Definition: CVTypeVisitor.h:22
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
visitMemberRecord
static Error visitMemberRecord(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks)
Definition: CVTypeVisitor.cpp:42
llvm::Optional
Definition: APInt.h:33
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
finishVisitation
static Error finishVisitation(CVSymbol &Record, SymbolVisitorCallbacks &Callbacks)
Definition: CVSymbolVisitor.cpp:30
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:198
llvm::codeview::TypeVisitorCallbacks::visitMemberEnd
virtual Error visitMemberEnd(CVMemberRecord &Record)
Definition: TypeVisitorCallbacks.h:45
llvm::codeview::visitMemberRecordStream
Error visitMemberRecordStream(ArrayRef< uint8_t > FieldList, TypeVisitorCallbacks &Callbacks)
Definition: CVTypeVisitor.cpp:270
llvm::codeview::TypeVisitorCallbacks::visitMemberBegin
virtual Error visitMemberBegin(CVMemberRecord &Record)
Definition: TypeVisitorCallbacks.h:41
llvm::codeview::CVMemberRecord
Definition: TypeRecord.h:34
llvm::support::little
@ little
Definition: Endian.h:27
TypeVisitorCallbackPipeline.h
llvm::codeview::TypeCollection::getNext
virtual Optional< TypeIndex > getNext(TypeIndex Prev)=0
llvm::BinaryByteStream
An implementation of BinaryStream which holds its entire data set in a single contiguous buffer.
Definition: BinaryByteStream.h:31
llvm::VarStreamArray< CVType >
llvm::codeview::TypeCollection
Definition: TypeCollection.h:18
llvm::codeview::TypeCollection::getType
virtual CVType getType(TypeIndex Index)=0
llvm::codeview::TypeRecordKind
TypeRecordKind
Distinguishes individual records in .debug$T or .debug$P section or PDB type stream.
Definition: CodeView.h:26
llvm::codeview::TypeVisitorCallbackPipeline
Definition: TypeVisitorCallbackPipeline.h:21
llvm::codeview::visitTypeRecord
Error visitTypeRecord(CVType &Record, TypeIndex Index, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
Definition: CVTypeVisitor.cpp:218
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
llvm::BinaryStreamReader
Provides read only access to a subclass of BinaryStream.
Definition: BinaryStreamReader.h:31
llvm::codeview::TypeDeserializer
Definition: TypeDeserializer.h:28
Index
uint32_t Index
Definition: ELFObjHandler.cpp:84
visitKnownRecord
static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks)
Definition: CVTypeVisitor.cpp:24
I
#define I(x, y, z)
Definition: MD5.cpp:59
TypeRecordMapping.h
llvm::codeview::ContinuationRecordKind::FieldList
@ FieldList
llvm::codeview::visitMemberRecord
Error visitMemberRecord(CVMemberRecord Record, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
Definition: CVTypeVisitor.cpp:254
llvm::codeview::CompileSym2Flags::EC
@ EC
llvm::Record
Definition: Record.h:1472
llvm::Sched::Source
@ Source
Definition: TargetLowering.h:100
llvm::ArrayRef< uint8_t >
llvm::codeview::CVRecord< TypeLeafKind >
llvm::codeview::TypeVisitorCallbacks::visitUnknownMember
virtual Error visitUnknownMember(CVMemberRecord &Record)
Definition: TypeVisitorCallbacks.h:37
TypeDeserializer.h
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
TypeCollection.h
CVTypeVisitor.h
visitKnownMember
static Error visitKnownMember(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks)
Definition: CVTypeVisitor.cpp:33
llvm::BinaryStreamReader::readEnum
Error readEnum(T &Dest)
Similar to readInteger.
Definition: BinaryStreamReader.h:89
llvm::codeview::TypeLeafKind
TypeLeafKind
Duplicate copy of the above enum, but using the official CV names.
Definition: CodeView.h:33
llvm::codeview
Definition: AppendingTypeTableBuilder.h:22
llvm::codeview::visitTypeStream
Error visitTypeStream(const CVTypeArray &Types, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
Definition: CVTypeVisitor.cpp:232
support
Reimplement select in terms of SEL *We would really like to support but we need to prove that the add doesn t need to overflow between the two bit chunks *Implement pre post increment support(e.g. PR935) *Implement smarter const ant generation for binops with large immediates. A few ARMv6T2 ops should be pattern matched
Definition: README.txt:10
llvm::iterator_range
A range adaptor for a pair of iterators.
Definition: iterator_range.h:30
llvm::codeview::TypeIndex
A 32-bit type reference.
Definition: TypeIndex.h:95
CodeViewError.h
llvm::codeview::FieldListDeserializer
Definition: TypeDeserializer.h:102