1 //===- TypeVisitorCallbackPipeline.h ----------------------------*- 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 #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEVISITORCALLBACKPIPELINE_H
11 #define LLVM_DEBUGINFO_CODEVIEW_TYPEVISITORCALLBACKPIPELINE_H
12 
13 #include "llvm/DebugInfo/CodeView/CodeView.h"
14 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
15 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
16 #include "llvm/Support/Error.h"
17 #include <vector>
18 
19 namespace llvm {
20 namespace codeview {
21 
22 class TypeVisitorCallbackPipeline : public TypeVisitorCallbacks {
23 public:
24   TypeVisitorCallbackPipeline() = default;
25 
visitUnknownType(CVRecord<TypeLeafKind> & Record)26   Error visitUnknownType(CVRecord<TypeLeafKind> &Record) override {
27     for (auto Visitor : Pipeline) {
28       if (auto EC = Visitor->visitUnknownType(Record))
29         return EC;
30     }
31     return Error::success();
32   }
33 
visitUnknownMember(CVMemberRecord & Record)34   Error visitUnknownMember(CVMemberRecord &Record) override {
35     for (auto Visitor : Pipeline) {
36       if (auto EC = Visitor->visitUnknownMember(Record))
37         return EC;
38     }
39     return Error::success();
40   }
41 
visitTypeBegin(CVType & Record)42   Error visitTypeBegin(CVType &Record) override {
43     for (auto Visitor : Pipeline) {
44       if (auto EC = Visitor->visitTypeBegin(Record))
45         return EC;
46     }
47     return Error::success();
48   }
49 
visitTypeBegin(CVType & Record,TypeIndex Index)50   Error visitTypeBegin(CVType &Record, TypeIndex Index) override {
51     for (auto Visitor : Pipeline) {
52       if (auto EC = Visitor->visitTypeBegin(Record, Index))
53         return EC;
54     }
55     return Error::success();
56   }
57 
visitTypeEnd(CVType & Record)58   Error visitTypeEnd(CVType &Record) override {
59     for (auto Visitor : Pipeline) {
60       if (auto EC = Visitor->visitTypeEnd(Record))
61         return EC;
62     }
63     return Error::success();
64   }
65 
visitMemberBegin(CVMemberRecord & Record)66   Error visitMemberBegin(CVMemberRecord &Record) override {
67     for (auto Visitor : Pipeline) {
68       if (auto EC = Visitor->visitMemberBegin(Record))
69         return EC;
70     }
71     return Error::success();
72   }
73 
visitMemberEnd(CVMemberRecord & Record)74   Error visitMemberEnd(CVMemberRecord &Record) override {
75     for (auto Visitor : Pipeline) {
76       if (auto EC = Visitor->visitMemberEnd(Record))
77         return EC;
78     }
79     return Error::success();
80   }
81 
addCallbackToPipeline(TypeVisitorCallbacks & Callbacks)82   void addCallbackToPipeline(TypeVisitorCallbacks &Callbacks) {
83     Pipeline.push_back(&Callbacks);
84   }
85 
86 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
87   Error visitKnownRecord(CVType &CVR, Name##Record &Record) override {         \
88     return visitKnownRecordImpl(CVR, Record);                                  \
89   }
90 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
91   Error visitKnownMember(CVMemberRecord &CVMR, Name##Record &Record)           \
92       override {                                                               \
93     return visitKnownMemberImpl(CVMR, Record);                                 \
94   }
95 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
96 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
97 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
98 
99 private:
visitKnownRecordImpl(CVType & CVR,T & Record)100   template <typename T> Error visitKnownRecordImpl(CVType &CVR, T &Record) {
101     for (auto Visitor : Pipeline) {
102       if (auto EC = Visitor->visitKnownRecord(CVR, Record))
103         return EC;
104     }
105     return Error::success();
106   }
107 
108   template <typename T>
visitKnownMemberImpl(CVMemberRecord & CVMR,T & Record)109   Error visitKnownMemberImpl(CVMemberRecord &CVMR, T &Record) {
110     for (auto Visitor : Pipeline) {
111       if (auto EC = Visitor->visitKnownMember(CVMR, Record))
112         return EC;
113     }
114     return Error::success();
115   }
116   std::vector<TypeVisitorCallbacks *> Pipeline;
117 };
118 
119 } // end namespace codeview
120 } // end namespace llvm
121 
122 #endif // LLVM_DEBUGINFO_CODEVIEW_TYPEVISITORCALLBACKPIPELINE_H
123