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