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