]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
Merge ^/head r319251 through r319479.
[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/TypeDatabase.h"
16 #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
17 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
18 #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
19 #include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
20 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
21 #include "llvm/Support/BinaryByteStream.h"
22 #include "llvm/Support/BinaryStreamReader.h"
23
24 using namespace llvm;
25 using namespace llvm::codeview;
26
27
28 template <typename T>
29 static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) {
30   TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type);
31   T KnownRecord(RK);
32   if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
33     return EC;
34   return Error::success();
35 }
36
37 template <typename T>
38 static Error visitKnownMember(CVMemberRecord &Record,
39                               TypeVisitorCallbacks &Callbacks) {
40   TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
41   T KnownRecord(RK);
42   if (auto EC = Callbacks.visitKnownMember(Record, KnownRecord))
43     return EC;
44   return Error::success();
45 }
46
47 static Expected<TypeServer2Record> deserializeTypeServerRecord(CVType &Record) {
48   TypeServer2Record R(TypeRecordKind::TypeServer2);
49   if (auto EC = TypeDeserializer::deserializeAs(Record, R))
50     return std::move(EC);
51   return R;
52 }
53
54 static Error visitMemberRecord(CVMemberRecord &Record,
55                                TypeVisitorCallbacks &Callbacks) {
56   if (auto EC = Callbacks.visitMemberBegin(Record))
57     return EC;
58
59   switch (Record.Kind) {
60   default:
61     if (auto EC = Callbacks.visitUnknownMember(Record))
62       return EC;
63     break;
64 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
65   case EnumName: {                                                             \
66     if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks))           \
67       return EC;                                                               \
68     break;                                                                     \
69   }
70 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
71   MEMBER_RECORD(EnumVal, EnumVal, AliasName)
72 #define TYPE_RECORD(EnumName, EnumVal, Name)
73 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
74 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
75   }
76
77   if (auto EC = Callbacks.visitMemberEnd(Record))
78     return EC;
79
80   return Error::success();
81 }
82
83 namespace {
84
85 class CVTypeVisitor {
86 public:
87   explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
88
89   void addTypeServerHandler(TypeServerHandler &Handler);
90
91   Error visitTypeRecord(CVType &Record, TypeIndex Index);
92   Error visitTypeRecord(CVType &Record);
93
94   /// Visits the type records in Data. Sets the error flag on parse failures.
95   Error visitTypeStream(const CVTypeArray &Types);
96   Error visitTypeStream(CVTypeRange Types);
97   Error visitTypeStream(TypeCollection &Types);
98
99   Error visitMemberRecord(CVMemberRecord Record);
100   Error visitFieldListMemberStream(BinaryStreamReader &Stream);
101
102 private:
103   Expected<bool> handleTypeServer(CVType &Record);
104   Error finishVisitation(CVType &Record);
105
106   /// The interface to the class that gets notified of each visitation.
107   TypeVisitorCallbacks &Callbacks;
108
109   TinyPtrVector<TypeServerHandler *> Handlers;
110 };
111
112 CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
113     : Callbacks(Callbacks) {}
114
115 void CVTypeVisitor::addTypeServerHandler(TypeServerHandler &Handler) {
116   Handlers.push_back(&Handler);
117 }
118
119 Expected<bool> CVTypeVisitor::handleTypeServer(CVType &Record) {
120   if (Record.Type == TypeLeafKind::LF_TYPESERVER2 && !Handlers.empty()) {
121     auto TS = deserializeTypeServerRecord(Record);
122     if (!TS)
123       return TS.takeError();
124
125     for (auto Handler : Handlers) {
126       auto ExpectedResult = Handler->handle(*TS, Callbacks);
127       // If there was an error, return the error.
128       if (!ExpectedResult)
129         return ExpectedResult.takeError();
130
131       // If the handler processed the record, return success.
132       if (*ExpectedResult)
133         return true;
134
135       // Otherwise keep searching for a handler, eventually falling out and
136       // using the default record handler.
137     }
138   }
139   return false;
140 }
141
142 Error CVTypeVisitor::finishVisitation(CVType &Record) {
143   switch (Record.Type) {
144   default:
145     if (auto EC = Callbacks.visitUnknownType(Record))
146       return EC;
147     break;
148 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
149   case EnumName: {                                                             \
150     if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks))           \
151       return EC;                                                               \
152     break;                                                                     \
153   }
154 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                  \
155   TYPE_RECORD(EnumVal, EnumVal, AliasName)
156 #define MEMBER_RECORD(EnumName, EnumVal, Name)
157 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
158 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
159   }
160
161   if (auto EC = Callbacks.visitTypeEnd(Record))
162     return EC;
163
164   return Error::success();
165 }
166
167 Error CVTypeVisitor::visitTypeRecord(CVType &Record, TypeIndex Index) {
168   auto ExpectedResult = handleTypeServer(Record);
169   if (!ExpectedResult)
170     return ExpectedResult.takeError();
171   if (*ExpectedResult)
172     return Error::success();
173
174   if (auto EC = Callbacks.visitTypeBegin(Record, Index))
175     return EC;
176
177   return finishVisitation(Record);
178 }
179
180 Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
181   auto ExpectedResult = handleTypeServer(Record);
182   if (!ExpectedResult)
183     return ExpectedResult.takeError();
184   if (*ExpectedResult)
185     return Error::success();
186
187   if (auto EC = Callbacks.visitTypeBegin(Record))
188     return EC;
189
190   return finishVisitation(Record);
191 }
192
193 Error CVTypeVisitor::visitMemberRecord(CVMemberRecord Record) {
194   return ::visitMemberRecord(Record, Callbacks);
195 }
196
197 /// Visits the type records in Data. Sets the error flag on parse failures.
198 Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
199   for (auto I : Types) {
200     if (auto EC = visitTypeRecord(I))
201       return EC;
202   }
203   return Error::success();
204 }
205
206 Error CVTypeVisitor::visitTypeStream(CVTypeRange Types) {
207   for (auto I : Types) {
208     if (auto EC = visitTypeRecord(I))
209       return EC;
210   }
211   return Error::success();
212 }
213
214 Error CVTypeVisitor::visitTypeStream(TypeCollection &Types) {
215   Optional<TypeIndex> I = Types.getFirst();
216   while (I) {
217     CVType Type = Types.getType(*I);
218     if (auto EC = visitTypeRecord(Type, *I))
219       return EC;
220     I = Types.getNext(*I);
221   }
222   return Error::success();
223 }
224
225 Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader &Reader) {
226   TypeLeafKind Leaf;
227   while (!Reader.empty()) {
228     if (auto EC = Reader.readEnum(Leaf))
229       return EC;
230
231     CVMemberRecord Record;
232     Record.Kind = Leaf;
233     if (auto EC = ::visitMemberRecord(Record, Callbacks))
234       return EC;
235   }
236
237   return Error::success();
238 }
239
240 struct FieldListVisitHelper {
241   FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef<uint8_t> Data,
242                        VisitorDataSource Source)
243       : Stream(Data, llvm::support::little), Reader(Stream),
244         Deserializer(Reader),
245         Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
246     if (Source == VDS_BytesPresent) {
247       Pipeline.addCallbackToPipeline(Deserializer);
248       Pipeline.addCallbackToPipeline(Callbacks);
249     }
250   }
251
252   BinaryByteStream Stream;
253   BinaryStreamReader Reader;
254   FieldListDeserializer Deserializer;
255   TypeVisitorCallbackPipeline Pipeline;
256   CVTypeVisitor Visitor;
257 };
258
259 struct VisitHelper {
260   VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source)
261       : Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
262     if (Source == VDS_BytesPresent) {
263       Pipeline.addCallbackToPipeline(Deserializer);
264       Pipeline.addCallbackToPipeline(Callbacks);
265     }
266   }
267
268   TypeDeserializer Deserializer;
269   TypeVisitorCallbackPipeline Pipeline;
270   CVTypeVisitor Visitor;
271 };
272 }
273
274 Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index,
275                                       TypeVisitorCallbacks &Callbacks,
276                                       VisitorDataSource Source,
277                                       TypeServerHandler *TS) {
278   VisitHelper V(Callbacks, Source);
279   if (TS)
280     V.Visitor.addTypeServerHandler(*TS);
281   return V.Visitor.visitTypeRecord(Record, Index);
282 }
283
284 Error llvm::codeview::visitTypeRecord(CVType &Record,
285                                       TypeVisitorCallbacks &Callbacks,
286                                       VisitorDataSource Source,
287                                       TypeServerHandler *TS) {
288   VisitHelper V(Callbacks, Source);
289   if (TS)
290     V.Visitor.addTypeServerHandler(*TS);
291   return V.Visitor.visitTypeRecord(Record);
292 }
293
294 Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
295                                       TypeVisitorCallbacks &Callbacks,
296                                       VisitorDataSource Source,
297                                       TypeServerHandler *TS) {
298   VisitHelper V(Callbacks, Source);
299   if (TS)
300     V.Visitor.addTypeServerHandler(*TS);
301   return V.Visitor.visitTypeStream(Types);
302 }
303
304 Error llvm::codeview::visitTypeStream(CVTypeRange Types,
305                                       TypeVisitorCallbacks &Callbacks,
306                                       TypeServerHandler *TS) {
307   VisitHelper V(Callbacks, VDS_BytesPresent);
308   if (TS)
309     V.Visitor.addTypeServerHandler(*TS);
310   return V.Visitor.visitTypeStream(Types);
311 }
312
313 Error llvm::codeview::visitTypeStream(TypeCollection &Types,
314                                       TypeVisitorCallbacks &Callbacks,
315                                       TypeServerHandler *TS) {
316   // When the internal visitor calls Types.getType(Index) the interface is
317   // required to return a CVType with the bytes filled out.  So we can assume
318   // that the bytes will be present when individual records are visited.
319   VisitHelper V(Callbacks, VDS_BytesPresent);
320   if (TS)
321     V.Visitor.addTypeServerHandler(*TS);
322   return V.Visitor.visitTypeStream(Types);
323 }
324
325 Error llvm::codeview::visitMemberRecord(CVMemberRecord Record,
326                                         TypeVisitorCallbacks &Callbacks,
327                                         VisitorDataSource Source) {
328   FieldListVisitHelper V(Callbacks, Record.Data, Source);
329   return V.Visitor.visitMemberRecord(Record);
330 }
331
332 Error llvm::codeview::visitMemberRecord(TypeLeafKind Kind,
333                                         ArrayRef<uint8_t> Record,
334                                         TypeVisitorCallbacks &Callbacks) {
335   CVMemberRecord R;
336   R.Data = Record;
337   R.Kind = Kind;
338   return visitMemberRecord(R, Callbacks, VDS_BytesPresent);
339 }
340
341 Error llvm::codeview::visitMemberRecordStream(ArrayRef<uint8_t> FieldList,
342                                               TypeVisitorCallbacks &Callbacks) {
343   FieldListVisitHelper V(Callbacks, FieldList, VDS_BytesPresent);
344   return V.Visitor.visitFieldListMemberStream(V.Reader);
345 }