1 // Copyright (c) 2016 Google Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef LIBSPIRV_OPT_PASS_MANAGER_H_ 16 #define LIBSPIRV_OPT_PASS_MANAGER_H_ 17 18 #include <memory> 19 #include <vector> 20 21 #include "log.h" 22 #include "module.h" 23 #include "pass.h" 24 25 #include "spirv-tools/libspirv.hpp" 26 27 namespace spvtools { 28 namespace opt { 29 30 // The pass manager, responsible for tracking and running passes. 31 // Clients should first call AddPass() to add passes and then call Run() 32 // to run on a module. Passes are executed in the exact order of addition. 33 class PassManager { 34 public: 35 // Constructs a pass manager. 36 // 37 // The constructed instance will have an empty message consumer, which just 38 // ignores all messages from the library. Use SetMessageConsumer() to supply 39 // one if messages are of concern. 40 PassManager() : consumer_(nullptr) {} 41 42 // Sets the message consumer to the given |consumer|. 43 void SetMessageConsumer(MessageConsumer c) { consumer_ = std::move(c); } 44 45 // Adds an externally constructed pass. 46 void AddPass(std::unique_ptr<Pass> pass); 47 // Uses the argument |args| to construct a pass instance of type |T|, and adds 48 // the pass instance to this pass manger. The pass added will use this pass 49 // manager's message consumer. 50 template <typename T, typename... Args> 51 void AddPass(Args&&... args); 52 53 // Returns the number of passes added. 54 uint32_t NumPasses() const; 55 // Returns a pointer to the |index|th pass added. 56 inline Pass* GetPass(uint32_t index) const; 57 58 // Returns the message consumer. 59 inline const MessageConsumer& consumer() const; 60 61 // Runs all passes on the given |module|. Returns Status::Failure if errors 62 // occur when processing using one of the registered passes. All passes 63 // registered after the error-reporting pass will be skipped. Returns the 64 // corresponding Status::Success if processing is succesful to indicate 65 // whether changes are made to the module. 66 Pass::Status Run(ir::Module* module); 67 68 private: 69 // Consumer for messages. 70 MessageConsumer consumer_; 71 // A vector of passes. Order matters. 72 std::vector<std::unique_ptr<Pass>> passes_; 73 }; 74 75 inline void PassManager::AddPass(std::unique_ptr<Pass> pass) { 76 passes_.push_back(std::move(pass)); 77 } 78 79 template <typename T, typename... Args> 80 inline void PassManager::AddPass(Args&&... args) { 81 passes_.emplace_back(new T(std::forward<Args>(args)...)); 82 passes_.back()->SetMessageConsumer(consumer_); 83 } 84 85 inline uint32_t PassManager::NumPasses() const { 86 return static_cast<uint32_t>(passes_.size()); 87 } 88 89 inline Pass* PassManager::GetPass(uint32_t index) const { 90 SPIRV_ASSERT(consumer_, index < passes_.size(), "index out of bound"); 91 return passes_[index].get(); 92 } 93 94 inline const MessageConsumer& PassManager::consumer() const { 95 return consumer_; 96 } 97 98 } // namespace opt 99 } // namespace spvtools 100 101 #endif // LIBSPIRV_OPT_PASS_MANAGER_H_ 102