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