]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
Merge ^/head r317503 through r317807.
[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/TypeDatabase.h"
14 #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.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 CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
26     : Callbacks(Callbacks) {}
27
28 template <typename T>
29 static Error visitKnownRecord(CVTypeVisitor &Visitor, CVType &Record,
30                               TypeVisitorCallbacks &Callbacks) {
31   TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type);
32   T KnownRecord(RK);
33   if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
34     return EC;
35   return Error::success();
36 }
37
38 template <typename T>
39 static Error visitKnownMember(CVMemberRecord &Record,
40                               TypeVisitorCallbacks &Callbacks) {
41   TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
42   T KnownRecord(RK);
43   if (auto EC = Callbacks.visitKnownMember(Record, KnownRecord))
44     return EC;
45   return Error::success();
46 }
47
48 static Expected<TypeServer2Record> deserializeTypeServerRecord(CVType &Record) {
49   class StealTypeServerVisitor : public TypeVisitorCallbacks {
50   public:
51     explicit StealTypeServerVisitor(TypeServer2Record &TR) : TR(TR) {}
52
53     Error visitKnownRecord(CVType &CVR, TypeServer2Record &Record) override {
54       TR = Record;
55       return Error::success();
56     }
57
58   private:
59     TypeServer2Record &TR;
60   };
61
62   TypeServer2Record R(TypeRecordKind::TypeServer2);
63   TypeDeserializer Deserializer;
64   StealTypeServerVisitor Thief(R);
65   TypeVisitorCallbackPipeline Pipeline;
66   Pipeline.addCallbackToPipeline(Deserializer);
67   Pipeline.addCallbackToPipeline(Thief);
68   CVTypeVisitor Visitor(Pipeline);
69   if (auto EC = Visitor.visitTypeRecord(Record))
70     return std::move(EC);
71
72   return R;
73 }
74
75 void CVTypeVisitor::addTypeServerHandler(TypeServerHandler &Handler) {
76   Handlers.push_back(&Handler);
77 }
78
79 Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
80   if (Record.Type == TypeLeafKind::LF_TYPESERVER2 && !Handlers.empty()) {
81     auto TS = deserializeTypeServerRecord(Record);
82     if (!TS)
83       return TS.takeError();
84
85     for (auto Handler : Handlers) {
86       auto ExpectedResult = Handler->handle(*TS, Callbacks);
87       // If there was an error, return the error.
88       if (!ExpectedResult)
89         return ExpectedResult.takeError();
90
91       // If the handler processed the record, return success.
92       if (*ExpectedResult)
93         return Error::success();
94
95       // Otherwise keep searching for a handler, eventually falling out and
96       // using the default record handler.
97     }
98   }
99
100   if (auto EC = Callbacks.visitTypeBegin(Record))
101     return EC;
102
103   switch (Record.Type) {
104   default:
105     if (auto EC = Callbacks.visitUnknownType(Record))
106       return EC;
107     break;
108 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
109   case EnumName: {                                                             \
110     if (auto EC = visitKnownRecord<Name##Record>(*this, Record, Callbacks))    \
111       return EC;                                                               \
112     break;                                                                     \
113   }
114 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                  \
115   TYPE_RECORD(EnumVal, EnumVal, AliasName)
116 #define MEMBER_RECORD(EnumName, EnumVal, Name)
117 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
118 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
119   }
120
121   if (auto EC = Callbacks.visitTypeEnd(Record))
122     return EC;
123
124   return Error::success();
125 }
126
127 static Error visitMemberRecord(CVMemberRecord &Record,
128                                TypeVisitorCallbacks &Callbacks) {
129   if (auto EC = Callbacks.visitMemberBegin(Record))
130     return EC;
131
132   switch (Record.Kind) {
133   default:
134     if (auto EC = Callbacks.visitUnknownMember(Record))
135       return EC;
136     break;
137 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
138   case EnumName: {                                                             \
139     if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks))           \
140       return EC;                                                               \
141     break;                                                                     \
142   }
143 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
144   MEMBER_RECORD(EnumVal, EnumVal, AliasName)
145 #define TYPE_RECORD(EnumName, EnumVal, Name)
146 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
147 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
148   }
149
150   if (auto EC = Callbacks.visitMemberEnd(Record))
151     return EC;
152
153   return Error::success();
154 }
155
156 Error CVTypeVisitor::visitMemberRecord(CVMemberRecord &Record) {
157   return ::visitMemberRecord(Record, Callbacks);
158 }
159
160 /// Visits the type records in Data. Sets the error flag on parse failures.
161 Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
162   for (auto I : Types) {
163     if (auto EC = visitTypeRecord(I))
164       return EC;
165   }
166   return Error::success();
167 }
168
169 Error CVTypeVisitor::visitTypeStream(CVTypeRange Types) {
170   for (auto I : Types) {
171     if (auto EC = visitTypeRecord(I))
172       return EC;
173   }
174   return Error::success();
175 }
176
177 Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader Reader) {
178   FieldListDeserializer Deserializer(Reader);
179   TypeVisitorCallbackPipeline Pipeline;
180   Pipeline.addCallbackToPipeline(Deserializer);
181   Pipeline.addCallbackToPipeline(Callbacks);
182
183   TypeLeafKind Leaf;
184   while (!Reader.empty()) {
185     if (auto EC = Reader.readEnum(Leaf))
186       return EC;
187
188     CVMemberRecord Record;
189     Record.Kind = Leaf;
190     if (auto EC = ::visitMemberRecord(Record, Pipeline))
191       return EC;
192   }
193
194   return Error::success();
195 }
196
197 Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
198   BinaryByteStream S(Data, llvm::support::little);
199   BinaryStreamReader SR(S);
200   return visitFieldListMemberStream(SR);
201 }