]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
Merge ^/head r311132 through r311305.
[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/DebugInfo/CodeView/CodeViewError.h"
13 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
14 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
15 #include "llvm/DebugInfo/MSF/ByteStream.h"
16
17 using namespace llvm;
18 using namespace llvm::codeview;
19
20 CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
21     : Callbacks(Callbacks) {}
22
23 template <typename T>
24 static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) {
25   TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type);
26   T KnownRecord(RK);
27   if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
28     return EC;
29   return Error::success();
30 }
31
32 template <typename T>
33 static Error visitKnownMember(CVMemberRecord &Record,
34                               TypeVisitorCallbacks &Callbacks) {
35   TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
36   T KnownRecord(RK);
37   if (auto EC = Callbacks.visitKnownMember(Record, KnownRecord))
38     return EC;
39   return Error::success();
40 }
41
42 Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
43   if (auto EC = Callbacks.visitTypeBegin(Record))
44     return EC;
45
46   switch (Record.Type) {
47   default:
48     if (auto EC = Callbacks.visitUnknownType(Record))
49       return EC;
50     break;
51 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
52   case EnumName: {                                                             \
53     if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks))           \
54       return EC;                                                               \
55     break;                                                                     \
56   }
57 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                  \
58   TYPE_RECORD(EnumVal, EnumVal, AliasName)
59 #define MEMBER_RECORD(EnumName, EnumVal, Name)
60 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
61 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
62   }
63
64   if (auto EC = Callbacks.visitTypeEnd(Record))
65     return EC;
66
67   return Error::success();
68 }
69
70 static Error visitMemberRecord(CVMemberRecord &Record,
71                                TypeVisitorCallbacks &Callbacks) {
72   if (auto EC = Callbacks.visitMemberBegin(Record))
73     return EC;
74
75   switch (Record.Kind) {
76   default:
77     if (auto EC = Callbacks.visitUnknownMember(Record))
78       return EC;
79     break;
80 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
81   case EnumName: {                                                             \
82     if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks))           \
83       return EC;                                                               \
84     break;                                                                     \
85   }
86 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
87   MEMBER_RECORD(EnumVal, EnumVal, AliasName)
88 #define TYPE_RECORD(EnumName, EnumVal, Name)
89 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
90 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
91   }
92
93   if (auto EC = Callbacks.visitMemberEnd(Record))
94     return EC;
95
96   return Error::success();
97 }
98
99 Error CVTypeVisitor::visitMemberRecord(CVMemberRecord &Record) {
100   return ::visitMemberRecord(Record, Callbacks);
101 }
102
103 /// Visits the type records in Data. Sets the error flag on parse failures.
104 Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
105   for (auto I : Types) {
106     if (auto EC = visitTypeRecord(I))
107       return EC;
108   }
109   return Error::success();
110 }
111
112 Error CVTypeVisitor::visitFieldListMemberStream(msf::StreamReader Reader) {
113   FieldListDeserializer Deserializer(Reader);
114   TypeVisitorCallbackPipeline Pipeline;
115   Pipeline.addCallbackToPipeline(Deserializer);
116   Pipeline.addCallbackToPipeline(Callbacks);
117
118   TypeLeafKind Leaf;
119   while (!Reader.empty()) {
120     if (auto EC = Reader.readEnum(Leaf))
121       return EC;
122
123     CVMemberRecord Record;
124     Record.Kind = Leaf;
125     if (auto EC = ::visitMemberRecord(Record, Pipeline))
126       return EC;
127   }
128
129   return Error::success();
130 }
131
132 Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
133   msf::ByteStream S(Data);
134   msf::StreamReader SR(S);
135   return visitFieldListMemberStream(SR);
136 }