LLVM 20.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
20using namespace llvm;
21using namespace llvm::codeview;
22
23
24template <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
33template <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
72namespace {
73
74class CVTypeVisitor {
75public:
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
89private:
91
92 /// The interface to the class that gets notified of each visitation.
93 TypeVisitorCallbacks &Callbacks;
94};
95
96CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
97 : Callbacks(Callbacks) {}
98
99Error CVTypeVisitor::finishVisitation(CVType &Record) {
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
124Error CVTypeVisitor::visitTypeRecord(CVType &Record, TypeIndex Index) {
125 if (auto EC = Callbacks.visitTypeBegin(Record, Index))
126 return EC;
127
128 return finishVisitation(Record);
129}
130
131Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
132 if (auto EC = Callbacks.visitTypeBegin(Record))
133 return EC;
134
135 return finishVisitation(Record);
136}
137
138Error CVTypeVisitor::visitMemberRecord(CVMemberRecord Record) {
139 return ::visitMemberRecord(Record, Callbacks);
140}
141
142/// Visits the type records in Data. Sets the error flag on parse failures.
143Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
144 for (auto I : Types) {
145 if (auto EC = visitTypeRecord(I))
146 return EC;
147 }
148 return Error::success();
149}
150
151Error CVTypeVisitor::visitTypeStream(CVTypeRange Types) {
152 for (auto I : Types) {
153 if (auto EC = visitTypeRecord(I))
154 return EC;
155 }
156 return Error::success();
157}
158
159Error CVTypeVisitor::visitTypeStream(TypeCollection &Types) {
160 std::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
170Error 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
185struct FieldListVisitHelper {
186 FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef<uint8_t> Data,
187 VisitorDataSource Source)
188 : Stream(Data, llvm::endianness::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
197 BinaryByteStream Stream;
198 BinaryStreamReader Reader;
199 FieldListDeserializer Deserializer;
201 CVTypeVisitor Visitor;
202};
203
204struct 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,
221 VisitorDataSource Source) {
222 VisitHelper V(Callbacks, Source);
223 return V.Visitor.visitTypeRecord(Record, Index);
224}
225
227 TypeVisitorCallbacks &Callbacks,
228 VisitorDataSource Source) {
229 VisitHelper V(Callbacks, Source);
230 return V.Visitor.visitTypeRecord(Record);
231}
232
234 TypeVisitorCallbacks &Callbacks,
235 VisitorDataSource Source) {
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,
257 VisitorDataSource Source) {
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}
static Error finishVisitation(CVSymbol &Record, SymbolVisitorCallbacks &Callbacks)
static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks)
static Error visitKnownMember(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks)
static Error visitMemberRecord(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks)
#define I(x, y, z)
Definition: MD5.cpp:58
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
An implementation of BinaryStream which holds its entire data set in a single contiguous buffer.
Provides read only access to a subclass of BinaryStream.
Error readEnum(T &Dest)
Similar to readInteger.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
A 32-bit type reference.
Definition: TypeIndex.h:96
virtual Error visitUnknownMember(CVMemberRecord &Record)
virtual Error visitMemberEnd(CVMemberRecord &Record)
virtual Error visitMemberBegin(CVMemberRecord &Record)
A range adaptor for a pair of iterators.
Error visitMemberRecord(CVMemberRecord Record, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
Error visitMemberRecordStream(ArrayRef< uint8_t > FieldList, TypeVisitorCallbacks &Callbacks)
Error visitTypeStream(const CVTypeArray &Types, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
TypeLeafKind
Duplicate copy of the above enum, but using the official CV names.
Definition: CodeView.h:34
TypeRecordKind
Distinguishes individual records in .debug$T or .debug$P section or PDB type stream.
Definition: CodeView.h:27
Error visitTypeRecord(CVType &Record, TypeIndex Index, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
endianness
Definition: bit.h:70