[llvm-exegesis][NFC] Fix typo
[llvm-complete.git] / lib / DebugInfo / CodeView / CVTypeVisitor.cpp
bloba4182a3b2fa15c76e9e36009f622e037c9fcaf4a
1 //===- CVTypeVisitor.cpp ----------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
10 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
12 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
13 #include "llvm/DebugInfo/CodeView/TypeCollection.h"
14 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
15 #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
16 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
17 #include "llvm/Support/BinaryByteStream.h"
18 #include "llvm/Support/BinaryStreamReader.h"
20 using namespace llvm;
21 using namespace llvm::codeview;
24 template <typename T>
25 static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) {
26 TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type);
27 T KnownRecord(RK);
28 if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
29 return EC;
30 return Error::success();
33 template <typename T>
34 static Error visitKnownMember(CVMemberRecord &Record,
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();
43 static Error visitMemberRecord(CVMemberRecord &Record,
44 TypeVisitorCallbacks &Callbacks) {
45 if (auto EC = Callbacks.visitMemberBegin(Record))
46 return EC;
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; \
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"
66 if (auto EC = Callbacks.visitMemberEnd(Record))
67 return EC;
69 return Error::success();
72 namespace {
74 class CVTypeVisitor {
75 public:
76 explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
78 Error visitTypeRecord(CVType &Record, TypeIndex Index);
79 Error visitTypeRecord(CVType &Record);
81 /// Visits the type records in Data. Sets the error flag on parse failures.
82 Error visitTypeStream(const CVTypeArray &Types);
83 Error visitTypeStream(CVTypeRange Types);
84 Error visitTypeStream(TypeCollection &Types);
86 Error visitMemberRecord(CVMemberRecord Record);
87 Error visitFieldListMemberStream(BinaryStreamReader &Stream);
89 private:
90 Error finishVisitation(CVType &Record);
92 /// The interface to the class that gets notified of each visitation.
93 TypeVisitorCallbacks &Callbacks;
96 CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
97 : Callbacks(Callbacks) {}
99 Error CVTypeVisitor::finishVisitation(CVType &Record) {
100 switch (Record.Type) {
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; \
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"
118 if (auto EC = Callbacks.visitTypeEnd(Record))
119 return EC;
121 return Error::success();
124 Error CVTypeVisitor::visitTypeRecord(CVType &Record, TypeIndex Index) {
125 if (auto EC = Callbacks.visitTypeBegin(Record, Index))
126 return EC;
128 return finishVisitation(Record);
131 Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
132 if (auto EC = Callbacks.visitTypeBegin(Record))
133 return EC;
135 return finishVisitation(Record);
138 Error CVTypeVisitor::visitMemberRecord(CVMemberRecord Record) {
139 return ::visitMemberRecord(Record, Callbacks);
142 /// Visits the type records in Data. Sets the error flag on parse failures.
143 Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
144 for (auto I : Types) {
145 if (auto EC = visitTypeRecord(I))
146 return EC;
148 return Error::success();
151 Error CVTypeVisitor::visitTypeStream(CVTypeRange Types) {
152 for (auto I : Types) {
153 if (auto EC = visitTypeRecord(I))
154 return EC;
156 return Error::success();
159 Error CVTypeVisitor::visitTypeStream(TypeCollection &Types) {
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);
167 return Error::success();
170 Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader &Reader) {
171 TypeLeafKind Leaf;
172 while (!Reader.empty()) {
173 if (auto EC = Reader.readEnum(Leaf))
174 return EC;
176 CVMemberRecord Record;
177 Record.Kind = Leaf;
178 if (auto EC = ::visitMemberRecord(Record, Callbacks))
179 return EC;
182 return Error::success();
185 struct FieldListVisitHelper {
186 FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef<uint8_t> Data,
187 VisitorDataSource Source)
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);
197 BinaryByteStream Stream;
198 BinaryStreamReader Reader;
199 FieldListDeserializer Deserializer;
200 TypeVisitorCallbackPipeline Pipeline;
201 CVTypeVisitor Visitor;
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);
213 TypeDeserializer Deserializer;
214 TypeVisitorCallbackPipeline Pipeline;
215 CVTypeVisitor Visitor;
219 Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index,
220 TypeVisitorCallbacks &Callbacks,
221 VisitorDataSource Source) {
222 VisitHelper V(Callbacks, Source);
223 return V.Visitor.visitTypeRecord(Record, Index);
226 Error llvm::codeview::visitTypeRecord(CVType &Record,
227 TypeVisitorCallbacks &Callbacks,
228 VisitorDataSource Source) {
229 VisitHelper V(Callbacks, Source);
230 return V.Visitor.visitTypeRecord(Record);
233 Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
234 TypeVisitorCallbacks &Callbacks,
235 VisitorDataSource Source) {
236 VisitHelper V(Callbacks, Source);
237 return V.Visitor.visitTypeStream(Types);
240 Error llvm::codeview::visitTypeStream(CVTypeRange Types,
241 TypeVisitorCallbacks &Callbacks) {
242 VisitHelper V(Callbacks, VDS_BytesPresent);
243 return V.Visitor.visitTypeStream(Types);
246 Error llvm::codeview::visitTypeStream(TypeCollection &Types,
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);
255 Error llvm::codeview::visitMemberRecord(CVMemberRecord Record,
256 TypeVisitorCallbacks &Callbacks,
257 VisitorDataSource Source) {
258 FieldListVisitHelper V(Callbacks, Record.Data, Source);
259 return V.Visitor.visitMemberRecord(Record);
262 Error llvm::codeview::visitMemberRecord(TypeLeafKind Kind,
263 ArrayRef<uint8_t> Record,
264 TypeVisitorCallbacks &Callbacks) {
265 CVMemberRecord R;
266 R.Data = Record;
267 R.Kind = Kind;
268 return visitMemberRecord(R, Callbacks, VDS_BytesPresent);
271 Error llvm::codeview::visitMemberRecordStream(ArrayRef<uint8_t> FieldList,
272 TypeVisitorCallbacks &Callbacks) {
273 FieldListVisitHelper V(Callbacks, FieldList, VDS_BytesPresent);
274 return V.Visitor.visitFieldListMemberStream(V.Reader);