1 //===- CVTypeVisitor.cpp ----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
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"
18 using namespace llvm::codeview;
20 CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
21 : Callbacks(Callbacks) {}
24 static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) {
25 TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type);
27 if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
29 return Error::success();
33 static Error visitKnownMember(CVMemberRecord &Record,
34 TypeVisitorCallbacks &Callbacks) {
35 TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
37 if (auto EC = Callbacks.visitKnownMember(Record, KnownRecord))
39 return Error::success();
42 Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
43 if (auto EC = Callbacks.visitTypeBegin(Record))
46 switch (Record.Type) {
48 if (auto EC = Callbacks.visitUnknownType(Record))
51 #define TYPE_RECORD(EnumName, EnumVal, Name) \
53 if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks)) \
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"
64 if (auto EC = Callbacks.visitTypeEnd(Record))
67 return Error::success();
70 static Error visitMemberRecord(CVMemberRecord &Record,
71 TypeVisitorCallbacks &Callbacks) {
72 if (auto EC = Callbacks.visitMemberBegin(Record))
75 switch (Record.Kind) {
77 if (auto EC = Callbacks.visitUnknownMember(Record))
80 #define MEMBER_RECORD(EnumName, EnumVal, Name) \
82 if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks)) \
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"
93 if (auto EC = Callbacks.visitMemberEnd(Record))
96 return Error::success();
99 Error CVTypeVisitor::visitMemberRecord(CVMemberRecord &Record) {
100 return ::visitMemberRecord(Record, Callbacks);
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))
109 return Error::success();
112 Error CVTypeVisitor::visitFieldListMemberStream(msf::StreamReader Reader) {
113 FieldListDeserializer Deserializer(Reader);
114 TypeVisitorCallbackPipeline Pipeline;
115 Pipeline.addCallbackToPipeline(Deserializer);
116 Pipeline.addCallbackToPipeline(Callbacks);
119 while (!Reader.empty()) {
120 if (auto EC = Reader.readEnum(Leaf))
123 CVMemberRecord Record;
125 if (auto EC = ::visitMemberRecord(Record, Pipeline))
129 return Error::success();
132 Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
133 msf::ByteStream S(Data);
134 msf::StreamReader SR(S);
135 return visitFieldListMemberStream(SR);