]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r308421, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / DebugInfo / CodeView / CVTypeVisitor.cpp
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 //===----------------------------------------------------------------------===//
9
10 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
11
12 #include "llvm/ADT/TinyPtrVector.h"
13 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
14 #include "llvm/DebugInfo/CodeView/TypeCollection.h"
15 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
16 #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
17 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
18 #include "llvm/Support/BinaryByteStream.h"
19 #include "llvm/Support/BinaryStreamReader.h"
20
21 using namespace llvm;
22 using namespace llvm::codeview;
23
24
25 template <typename T>
26 static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) {
27   TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type);
28   T KnownRecord(RK);
29   if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
30     return EC;
31   return Error::success();
32 }
33
34 template <typename T>
35 static Error visitKnownMember(CVMemberRecord &Record,
36                               TypeVisitorCallbacks &Callbacks) {
37   TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
38   T KnownRecord(RK);
39   if (auto EC = Callbacks.visitKnownMember(Record, KnownRecord))
40     return EC;
41   return Error::success();
42 }
43
44 static Error visitMemberRecord(CVMemberRecord &Record,
45                                TypeVisitorCallbacks &Callbacks) {
46   if (auto EC = Callbacks.visitMemberBegin(Record))
47     return EC;
48
49   switch (Record.Kind) {
50   default:
51     if (auto EC = Callbacks.visitUnknownMember(Record))
52       return EC;
53     break;
54 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
55   case EnumName: {                                                             \
56     if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks))           \
57       return EC;                                                               \
58     break;                                                                     \
59   }
60 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
61   MEMBER_RECORD(EnumVal, EnumVal, AliasName)
62 #define TYPE_RECORD(EnumName, EnumVal, Name)
63 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
64 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
65   }
66
67   if (auto EC = Callbacks.visitMemberEnd(Record))
68     return EC;
69
70   return Error::success();
71 }
72
73 namespace {
74
75 class CVTypeVisitor {
76 public:
77   explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
78
79   Error visitTypeRecord(CVType &Record, TypeIndex Index);
80   Error visitTypeRecord(CVType &Record);
81
82   /// Visits the type records in Data. Sets the error flag on parse failures.
83   Error visitTypeStream(const CVTypeArray &Types);
84   Error visitTypeStream(CVTypeRange Types);
85   Error visitTypeStream(TypeCollection &Types);
86
87   Error visitMemberRecord(CVMemberRecord Record);
88   Error visitFieldListMemberStream(BinaryStreamReader &Stream);
89
90 private:
91   Error finishVisitation(CVType &Record);
92
93   /// The interface to the class that gets notified of each visitation.
94   TypeVisitorCallbacks &Callbacks;
95 };
96
97 CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
98     : Callbacks(Callbacks) {}
99
100 Error CVTypeVisitor::finishVisitation(CVType &Record) {
101   switch (Record.Type) {
102   default:
103     if (auto EC = Callbacks.visitUnknownType(Record))
104       return EC;
105     break;
106 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
107   case EnumName: {                                                             \
108     if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks))           \
109       return EC;                                                               \
110     break;                                                                     \
111   }
112 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                  \
113   TYPE_RECORD(EnumVal, EnumVal, AliasName)
114 #define MEMBER_RECORD(EnumName, EnumVal, Name)
115 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
116 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
117   }
118
119   if (auto EC = Callbacks.visitTypeEnd(Record))
120     return EC;
121
122   return Error::success();
123 }
124
125 Error CVTypeVisitor::visitTypeRecord(CVType &Record, TypeIndex Index) {
126   if (auto EC = Callbacks.visitTypeBegin(Record, Index))
127     return EC;
128
129   return finishVisitation(Record);
130 }
131
132 Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
133   if (auto EC = Callbacks.visitTypeBegin(Record))
134     return EC;
135
136   return finishVisitation(Record);
137 }
138
139 Error CVTypeVisitor::visitMemberRecord(CVMemberRecord Record) {
140   return ::visitMemberRecord(Record, Callbacks);
141 }
142
143 /// Visits the type records in Data. Sets the error flag on parse failures.
144 Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
145   for (auto I : Types) {
146     if (auto EC = visitTypeRecord(I))
147       return EC;
148   }
149   return Error::success();
150 }
151
152 Error CVTypeVisitor::visitTypeStream(CVTypeRange Types) {
153   for (auto I : Types) {
154     if (auto EC = visitTypeRecord(I))
155       return EC;
156   }
157   return Error::success();
158 }
159
160 Error CVTypeVisitor::visitTypeStream(TypeCollection &Types) {
161   Optional<TypeIndex> I = Types.getFirst();
162   while (I) {
163     CVType Type = Types.getType(*I);
164     if (auto EC = visitTypeRecord(Type, *I))
165       return EC;
166     I = Types.getNext(*I);
167   }
168   return Error::success();
169 }
170
171 Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader &Reader) {
172   TypeLeafKind Leaf;
173   while (!Reader.empty()) {
174     if (auto EC = Reader.readEnum(Leaf))
175       return EC;
176
177     CVMemberRecord Record;
178     Record.Kind = Leaf;
179     if (auto EC = ::visitMemberRecord(Record, Callbacks))
180       return EC;
181   }
182
183   return Error::success();
184 }
185
186 struct FieldListVisitHelper {
187   FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef<uint8_t> Data,
188                        VisitorDataSource Source)
189       : Stream(Data, llvm::support::little), Reader(Stream),
190         Deserializer(Reader),
191         Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
192     if (Source == VDS_BytesPresent) {
193       Pipeline.addCallbackToPipeline(Deserializer);
194       Pipeline.addCallbackToPipeline(Callbacks);
195     }
196   }
197
198   BinaryByteStream Stream;
199   BinaryStreamReader Reader;
200   FieldListDeserializer Deserializer;
201   TypeVisitorCallbackPipeline Pipeline;
202   CVTypeVisitor Visitor;
203 };
204
205 struct VisitHelper {
206   VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source)
207       : Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
208     if (Source == VDS_BytesPresent) {
209       Pipeline.addCallbackToPipeline(Deserializer);
210       Pipeline.addCallbackToPipeline(Callbacks);
211     }
212   }
213
214   TypeDeserializer Deserializer;
215   TypeVisitorCallbackPipeline Pipeline;
216   CVTypeVisitor Visitor;
217 };
218 }
219
220 Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index,
221                                       TypeVisitorCallbacks &Callbacks,
222                                       VisitorDataSource Source) {
223   VisitHelper V(Callbacks, Source);
224   return V.Visitor.visitTypeRecord(Record, Index);
225 }
226
227 Error llvm::codeview::visitTypeRecord(CVType &Record,
228                                       TypeVisitorCallbacks &Callbacks,
229                                       VisitorDataSource Source) {
230   VisitHelper V(Callbacks, Source);
231   return V.Visitor.visitTypeRecord(Record);
232 }
233
234 Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
235                                       TypeVisitorCallbacks &Callbacks,
236                                       VisitorDataSource Source) {
237   VisitHelper V(Callbacks, Source);
238   return V.Visitor.visitTypeStream(Types);
239 }
240
241 Error llvm::codeview::visitTypeStream(CVTypeRange Types,
242                                       TypeVisitorCallbacks &Callbacks) {
243   VisitHelper V(Callbacks, VDS_BytesPresent);
244   return V.Visitor.visitTypeStream(Types);
245 }
246
247 Error llvm::codeview::visitTypeStream(TypeCollection &Types,
248                                       TypeVisitorCallbacks &Callbacks) {
249   // When the internal visitor calls Types.getType(Index) the interface is
250   // required to return a CVType with the bytes filled out.  So we can assume
251   // that the bytes will be present when individual records are visited.
252   VisitHelper V(Callbacks, VDS_BytesPresent);
253   return V.Visitor.visitTypeStream(Types);
254 }
255
256 Error llvm::codeview::visitMemberRecord(CVMemberRecord Record,
257                                         TypeVisitorCallbacks &Callbacks,
258                                         VisitorDataSource Source) {
259   FieldListVisitHelper V(Callbacks, Record.Data, Source);
260   return V.Visitor.visitMemberRecord(Record);
261 }
262
263 Error llvm::codeview::visitMemberRecord(TypeLeafKind Kind,
264                                         ArrayRef<uint8_t> Record,
265                                         TypeVisitorCallbacks &Callbacks) {
266   CVMemberRecord R;
267   R.Data = Record;
268   R.Kind = Kind;
269   return visitMemberRecord(R, Callbacks, VDS_BytesPresent);
270 }
271
272 Error llvm::codeview::visitMemberRecordStream(ArrayRef<uint8_t> FieldList,
273                                               TypeVisitorCallbacks &Callbacks) {
274   FieldListVisitHelper V(Callbacks, FieldList, VDS_BytesPresent);
275   return V.Visitor.visitFieldListMemberStream(V.Reader);
276 }