LLVM  6.0.0svn
CVTypeVisitor.cpp
Go to the documentation of this file.
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 
11 
12 #include "llvm/ADT/TinyPtrVector.h"
20 
21 using namespace llvm;
22 using namespace llvm::codeview;
23 
24 
25 template <typename T>
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>
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 
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 
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);
86 
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 
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 
126  if (auto EC = Callbacks.visitTypeBegin(Record, Index))
127  return EC;
128 
129  return finishVisitation(Record);
130 }
131 
133  if (auto EC = Callbacks.visitTypeBegin(Record))
134  return EC;
135 
136  return finishVisitation(Record);
137 }
138 
140  return ::visitMemberRecord(Record, Callbacks);
141 }
142 
143 /// Visits the type records in Data. Sets the error flag on parse failures.
145  for (auto I : Types) {
146  if (auto EC = visitTypeRecord(I))
147  return EC;
148  }
149  return Error::success();
150 }
151 
153  for (auto I : Types) {
154  if (auto EC = visitTypeRecord(I))
155  return EC;
156  }
157  return Error::success();
158 }
159 
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,
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;
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;
216  CVTypeVisitor Visitor;
217 };
218 }
219 
221  TypeVisitorCallbacks &Callbacks,
223  VisitHelper V(Callbacks, Source);
224  return V.Visitor.visitTypeRecord(Record, Index);
225 }
226 
228  TypeVisitorCallbacks &Callbacks,
230  VisitHelper V(Callbacks, Source);
231  return V.Visitor.visitTypeRecord(Record);
232 }
233 
235  TypeVisitorCallbacks &Callbacks,
237  VisitHelper V(Callbacks, Source);
238  return V.Visitor.visitTypeStream(Types);
239 }
240 
242  TypeVisitorCallbacks &Callbacks) {
243  VisitHelper V(Callbacks, VDS_BytesPresent);
244  return V.Visitor.visitTypeStream(Types);
245 }
246 
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 
257  TypeVisitorCallbacks &Callbacks,
259  FieldListVisitHelper V(Callbacks, Record.Data, Source);
260  return V.Visitor.visitMemberRecord(Record);
261 }
262 
265  TypeVisitorCallbacks &Callbacks) {
266  CVMemberRecord R;
267  R.Data = Record;
268  R.Kind = Kind;
269  return visitMemberRecord(R, Callbacks, VDS_BytesPresent);
270 }
271 
273  TypeVisitorCallbacks &Callbacks) {
274  FieldListVisitHelper V(Callbacks, FieldList, VDS_BytesPresent);
275  return V.Visitor.visitFieldListMemberStream(V.Reader);
276 }
An implementation of BinaryStream which holds its entire data set in a single contiguous buffer...
virtual Optional< TypeIndex > getNext(TypeIndex Prev)=0
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
TypeLeafKind
Duplicate copy of the above enum, but using the official CV names.
Definition: CodeView.h:34
ArrayRef< uint8_t > Data
Definition: TypeRecord.h:41
virtual CVType getType(TypeIndex Index)=0
Error visitMemberRecordStream(ArrayRef< uint8_t > FieldList, TypeVisitorCallbacks &Callbacks)
virtual Optional< TypeIndex > getFirst()=0
virtual Error visitUnknownMember(CVMemberRecord &Record)
virtual Error visitUnknownType(CVType &Record)
Action to take on unknown types. By default, they are ignored.
A 32-bit type reference.
Definition: TypeIndex.h:96
virtual Error visitTypeEnd(CVType &Record)
TypeRecordKind
Distinguishes individual records in .debug$T section or PDB type stream.
Definition: CodeView.h:27
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
static Error visitKnownMember(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks)
static Error visitMemberRecord(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks)
Error visitTypeRecord(CVType &Record, TypeIndex Index, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
Error visitTypeStream(const CVTypeArray &Types, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
static ErrorSuccess success()
Create a success value.
Definition: Error.h:313
virtual Error visitMemberBegin(CVMemberRecord &Record)
Error visitMemberRecord(CVMemberRecord Record, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
virtual Error visitTypeBegin(CVType &Record)
Paired begin/end actions for all types.
A range adaptor for a pair of iterators.
#define I(x, y, z)
Definition: MD5.cpp:58
static Error finishVisitation(CVSymbol &Record, SymbolVisitorCallbacks &Callbacks)
static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks)
const unsigned Kind
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
Provides read only access to a subclass of BinaryStream.
Error readEnum(T &Dest)
Similar to readInteger.
virtual Error visitMemberEnd(CVMemberRecord &Record)