Home | History | Annotate | Download | only in opt
      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 SOURCE_OPT_PASS_MANAGER_H_
     16 #define SOURCE_OPT_PASS_MANAGER_H_
     17 
     18 #include <memory>
     19 #include <ostream>
     20 #include <utility>
     21 #include <vector>
     22 
     23 #include "source/opt/log.h"
     24 #include "source/opt/module.h"
     25 #include "source/opt/pass.h"
     26 
     27 #include "source/opt/ir_context.h"
     28 #include "spirv-tools/libspirv.hpp"
     29 
     30 namespace spvtools {
     31 namespace opt {
     32 
     33 // The pass manager, responsible for tracking and running passes.
     34 // Clients should first call AddPass() to add passes and then call Run()
     35 // to run on a module. Passes are executed in the exact order of addition.
     36 class PassManager {
     37  public:
     38   // Constructs a pass manager.
     39   //
     40   // The constructed instance will have an empty message consumer, which just
     41   // ignores all messages from the library. Use SetMessageConsumer() to supply
     42   // one if messages are of concern.
     43   PassManager()
     44       : consumer_(nullptr),
     45         print_all_stream_(nullptr),
     46         time_report_stream_(nullptr) {}
     47 
     48   // Sets the message consumer to the given |consumer|.
     49   void SetMessageConsumer(MessageConsumer c) { consumer_ = std::move(c); }
     50 
     51   // Adds an externally constructed pass.
     52   void AddPass(std::unique_ptr<Pass> pass);
     53   // Uses the argument |args| to construct a pass instance of type |T|, and adds
     54   // the pass instance to this pass manger. The pass added will use this pass
     55   // manager's message consumer.
     56   template <typename T, typename... Args>
     57   void AddPass(Args&&... args);
     58 
     59   // Returns the number of passes added.
     60   uint32_t NumPasses() const;
     61   // Returns a pointer to the |index|th pass added.
     62   inline Pass* GetPass(uint32_t index) const;
     63 
     64   // Returns the message consumer.
     65   inline const MessageConsumer& consumer() const;
     66 
     67   // Runs all passes on the given |module|. Returns Status::Failure if errors
     68   // occur when processing using one of the registered passes. All passes
     69   // registered after the error-reporting pass will be skipped. Returns the
     70   // corresponding Status::Success if processing is succesful to indicate
     71   // whether changes are made to the module.
     72   //
     73   // After running all the passes, they are removed from the list.
     74   Pass::Status Run(IRContext* context);
     75 
     76   // Sets the option to print the disassembly before each pass and after the
     77   // last pass.   Output is written to |out| if that is not null.  No output
     78   // is generated if |out| is null.
     79   PassManager& SetPrintAll(std::ostream* out) {
     80     print_all_stream_ = out;
     81     return *this;
     82   }
     83 
     84   // Sets the option to print the resource utilization of each pass. Output is
     85   // written to |out| if that is not null. No output is generated if |out| is
     86   // null.
     87   PassManager& SetTimeReport(std::ostream* out) {
     88     time_report_stream_ = out;
     89     return *this;
     90   }
     91 
     92  private:
     93   // Consumer for messages.
     94   MessageConsumer consumer_;
     95   // A vector of passes. Order matters.
     96   std::vector<std::unique_ptr<Pass>> passes_;
     97   // The output stream to write disassembly to before each pass, and after
     98   // the last pass.  If this is null, no output is generated.
     99   std::ostream* print_all_stream_;
    100   // The output stream to write the resource utilization of each pass. If this
    101   // is null, no output is generated.
    102   std::ostream* time_report_stream_;
    103 };
    104 
    105 inline void PassManager::AddPass(std::unique_ptr<Pass> pass) {
    106   passes_.push_back(std::move(pass));
    107 }
    108 
    109 template <typename T, typename... Args>
    110 inline void PassManager::AddPass(Args&&... args) {
    111   passes_.emplace_back(new T(std::forward<Args>(args)...));
    112   passes_.back()->SetMessageConsumer(consumer_);
    113 }
    114 
    115 inline uint32_t PassManager::NumPasses() const {
    116   return static_cast<uint32_t>(passes_.size());
    117 }
    118 
    119 inline Pass* PassManager::GetPass(uint32_t index) const {
    120   SPIRV_ASSERT(consumer_, index < passes_.size(), "index out of bound");
    121   return passes_[index].get();
    122 }
    123 
    124 inline const MessageConsumer& PassManager::consumer() const {
    125   return consumer_;
    126 }
    127 
    128 }  // namespace opt
    129 }  // namespace spvtools
    130 
    131 #endif  // SOURCE_OPT_PASS_MANAGER_H_
    132