LLVM  15.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 
19 
20 using namespace llvm;
21 using namespace llvm::codeview;
22 
23 
24 template <typename T>
26  TypeRecordKind RK = static_cast<TypeRecordKind>(Record.kind());
27  T KnownRecord(RK);
28  if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
29  return EC;
30  return Error::success();
31 }
32 
33 template <typename T>
35  TypeVisitorCallbacks &Callbacks) {
36  TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
37  T KnownRecord(RK);
38  if (auto EC = Callbacks.visitKnownMember(Record, KnownRecord))
39  return EC;
40  return Error::success();
41 }
42 
44  TypeVisitorCallbacks &Callbacks) {
45  if (auto EC = Callbacks.visitMemberBegin(Record))
46  return EC;
47 
48  switch (Record.Kind) {
49  default:
50  if (auto EC = Callbacks.visitUnknownMember(Record))
51  return EC;
52  break;
53 #define MEMBER_RECORD(EnumName, EnumVal, Name) \
54  case EnumName: { \
55  if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks)) \
56  return EC; \
57  break; \
58  }
59 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
60  MEMBER_RECORD(EnumVal, EnumVal, AliasName)
61 #define TYPE_RECORD(EnumName, EnumVal, Name)
62 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
63 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
64  }
65 
66  if (auto EC = Callbacks.visitMemberEnd(Record))
67  return EC;
68 
69  return Error::success();
70 }
71 
72 namespace {
73 
74 class CVTypeVisitor {
75 public:
76  explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
77 
80 
81  /// Visits the type records in Data. Sets the error flag on parse failures.
82  Error visitTypeStream(const CVTypeArray &Types);
85 
87  Error visitFieldListMemberStream(BinaryStreamReader &Stream);
88 
89 private:
91 
92  /// The interface to the class that gets notified of each visitation.
93  TypeVisitorCallbacks &Callbacks;
94 };
95 
96 CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
97  : Callbacks(Callbacks) {}
98 
100  switch (Record.kind()) {
101  default:
102  if (auto EC = Callbacks.visitUnknownType(Record))
103  return EC;
104  break;
105 #define TYPE_RECORD(EnumName, EnumVal, Name) \
106  case EnumName: { \
107  if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks)) \
108  return EC; \
109  break; \
110  }
111 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
112  TYPE_RECORD(EnumVal, EnumVal, AliasName)
113 #define MEMBER_RECORD(EnumName, EnumVal, Name)
114 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
115 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
116  }
117 
118  if (auto EC = Callbacks.visitTypeEnd(Record))
119  return EC;
120 
121  return Error::success();
122 }
123 
125  if (auto EC = Callbacks.visitTypeBegin(Record, Index))
126  return EC;
127 
128  return finishVisitation(Record);
129 }
130 
132  if (auto EC = Callbacks.visitTypeBegin(Record))
133  return EC;
134 
135  return finishVisitation(Record);
136 }
137 
140 }
141 
142 /// Visits the type records in Data. Sets the error flag on parse failures.
144  for (auto I : Types) {
145  if (auto EC = visitTypeRecord(I))
146  return EC;
147  }
148  return Error::success();
149 }
150 
152  for (auto I : Types) {
153  if (auto EC = visitTypeRecord(I))
154  return EC;
155  }
156  return Error::success();
157 }
158 
160  Optional<TypeIndex> I = Types.getFirst();
161  while (I) {
162  CVType Type = Types.getType(*I);
163  if (auto EC = visitTypeRecord(Type, *I))
164  return EC;
165  I = Types.getNext(*I);
166  }
167  return Error::success();
168 }
169 
170 Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader &Reader) {
171  TypeLeafKind Leaf;
172  while (!Reader.empty()) {
173  if (auto EC = Reader.readEnum(Leaf))
174  return EC;
175 
177  Record.Kind = Leaf;
178  if (auto EC = ::visitMemberRecord(Record, Callbacks))
179  return EC;
180  }
181 
182  return Error::success();
183 }
184 
185 struct FieldListVisitHelper {
186  FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef<uint8_t> Data,
188  : Stream(Data, llvm::support::little), Reader(Stream),
189  Deserializer(Reader),
190  Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
191  if (Source == VDS_BytesPresent) {
192  Pipeline.addCallbackToPipeline(Deserializer);
193  Pipeline.addCallbackToPipeline(Callbacks);
194  }
195  }
196 
198  BinaryStreamReader Reader;
199  FieldListDeserializer Deserializer;
201  CVTypeVisitor Visitor;
202 };
203 
204 struct VisitHelper {
205  VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source)
206  : Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
207  if (Source == VDS_BytesPresent) {
208  Pipeline.addCallbackToPipeline(Deserializer);
209  Pipeline.addCallbackToPipeline(Callbacks);
210  }
211  }
212 
213  TypeDeserializer Deserializer;
215  CVTypeVisitor Visitor;
216 };
217 }
218 
220  TypeVisitorCallbacks &Callbacks,
222  VisitHelper V(Callbacks, Source);
223  return V.Visitor.visitTypeRecord(Record, Index);
224 }
225 
227  TypeVisitorCallbacks &Callbacks,
229  VisitHelper V(Callbacks, Source);
230  return V.Visitor.visitTypeRecord(Record);
231 }
232 
234  TypeVisitorCallbacks &Callbacks,
236  VisitHelper V(Callbacks, Source);
237  return V.Visitor.visitTypeStream(Types);
238 }
239 
241  TypeVisitorCallbacks &Callbacks) {
242  VisitHelper V(Callbacks, VDS_BytesPresent);
243  return V.Visitor.visitTypeStream(Types);
244 }
245 
247  TypeVisitorCallbacks &Callbacks) {
248  // When the internal visitor calls Types.getType(Index) the interface is
249  // required to return a CVType with the bytes filled out. So we can assume
250  // that the bytes will be present when individual records are visited.
251  VisitHelper V(Callbacks, VDS_BytesPresent);
252  return V.Visitor.visitTypeStream(Types);
253 }
254 
256  TypeVisitorCallbacks &Callbacks,
258  FieldListVisitHelper V(Callbacks, Record.Data, Source);
259  return V.Visitor.visitMemberRecord(Record);
260 }
261 
264  TypeVisitorCallbacks &Callbacks) {
266  R.Data = Record;
267  R.Kind = Kind;
268  return visitMemberRecord(R, Callbacks, VDS_BytesPresent);
269 }
270 
272  TypeVisitorCallbacks &Callbacks) {
273  FieldListVisitHelper V(Callbacks, FieldList, VDS_BytesPresent);
274  return V.Visitor.visitFieldListMemberStream(V.Reader);
275 }
BinaryStreamReader.h
llvm::BinaryStreamReader::empty
bool empty() const
Definition: BinaryStreamReader.h:246
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
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:24
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
llvm::codeview::VDS_BytesPresent
@ VDS_BytesPresent
Definition: CVTypeVisitor.h:25
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:43
TypeVisitorCallbacks.h
llvm::Optional
Definition: APInt.h:33
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
finishVisitation
static Error finishVisitation(CVSymbol &Record, SymbolVisitorCallbacks &Callbacks)
Definition: CVSymbolVisitor.cpp:34
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:241
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:271
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:30
llvm::VarStreamArray< CVType >
llvm::codeview::TypeCollection
Definition: TypeCollection.h:18
llvm::dwarf::Index
Index
Definition: Dwarf.h:472
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:219
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
llvm::BinaryStreamReader
Provides read only access to a subclass of BinaryStream.
Definition: BinaryStreamReader.h:29
llvm::codeview::TypeDeserializer
Definition: TypeDeserializer.h:28
TypeRecord.h
visitKnownRecord
static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks)
Definition: CVTypeVisitor.cpp:25
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::codeview::ContinuationRecordKind::FieldList
@ FieldList
llvm::codeview::visitMemberRecord
Error visitMemberRecord(CVMemberRecord Record, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
Definition: CVTypeVisitor.cpp:255
llvm::SPIRV::Decoration::Stream
@ Stream
llvm::codeview::CompileSym2Flags::EC
@ EC
llvm::Record
Definition: Record.h:1543
llvm::Sched::Source
@ Source
Definition: TargetLowering.h:99
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:155
TypeCollection.h
CVTypeVisitor.h
visitKnownMember
static Error visitKnownMember(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks)
Definition: CVTypeVisitor.cpp:34
TypeIndex.h
llvm::BinaryStreamReader::readEnum
Error readEnum(T &Dest)
Similar to readInteger.
Definition: BinaryStreamReader.h:82
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:233
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:96
llvm::codeview::FieldListDeserializer
Definition: TypeDeserializer.h:102