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 LIBSPIRV_OPT_MODULE_H_
     16 #define LIBSPIRV_OPT_MODULE_H_
     17 
     18 #include <functional>
     19 #include <memory>
     20 #include <utility>
     21 #include <vector>
     22 
     23 #include "function.h"
     24 #include "instruction.h"
     25 #include "iterator.h"
     26 
     27 namespace spvtools {
     28 namespace ir {
     29 
     30 // A struct for containing the module header information.
     31 struct ModuleHeader {
     32   uint32_t magic_number;
     33   uint32_t version;
     34   uint32_t generator;
     35   uint32_t bound;
     36   uint32_t reserved;
     37 };
     38 
     39 // A SPIR-V module. It contains all the information for a SPIR-V module and
     40 // serves as the backbone of optimization transformations.
     41 class Module {
     42  public:
     43   using iterator = UptrVectorIterator<Function>;
     44   using const_iterator = UptrVectorIterator<Function, true>;
     45   using inst_iterator = UptrVectorIterator<Instruction>;
     46   using const_inst_iterator = UptrVectorIterator<Instruction, true>;
     47 
     48   // Creates an empty module with zero'd header.
     49   Module() : header_({}) {}
     50 
     51   // Sets the header to the given |header|.
     52   void SetHeader(const ModuleHeader& header) { header_ = header; }
     53   // Sets the Id bound.
     54   void SetIdBound(uint32_t bound) { header_.bound = bound; }
     55   // Returns the Id bound.
     56   uint32_t IdBound() { return header_.bound; }
     57   // Appends a capability instruction to this module.
     58   inline void AddCapability(std::unique_ptr<Instruction> c);
     59   // Appends an extension instruction to this module.
     60   inline void AddExtension(std::unique_ptr<Instruction> e);
     61   // Appends an extended instruction set instruction to this module.
     62   inline void AddExtInstImport(std::unique_ptr<Instruction> e);
     63   // Set the memory model for this module.
     64   inline void SetMemoryModel(std::unique_ptr<Instruction> m);
     65   // Appends an entry point instruction to this module.
     66   inline void AddEntryPoint(std::unique_ptr<Instruction> e);
     67   // Appends an execution mode instruction to this module.
     68   inline void AddExecutionMode(std::unique_ptr<Instruction> e);
     69   // Appends a debug instruction (excluding OpLine & OpNoLine) to this module.
     70   inline void AddDebugInst(std::unique_ptr<Instruction> d);
     71   // Appends an annotation instruction to this module.
     72   inline void AddAnnotationInst(std::unique_ptr<Instruction> a);
     73   // Appends a type-declaration instruction to this module.
     74   inline void AddType(std::unique_ptr<Instruction> t);
     75   // Appends a constant, global variable, or OpUndef instruction to this module.
     76   inline void AddGlobalValue(std::unique_ptr<Instruction> v);
     77   // Appends a function to this module.
     78   inline void AddFunction(std::unique_ptr<Function> f);
     79 
     80   // Returns a vector of pointers to type-declaration instructions in this
     81   // module.
     82   std::vector<Instruction*> GetTypes();
     83   std::vector<const Instruction*> GetTypes() const;
     84   // Returns a vector of pointers to constant-creation instructions in this
     85   // module.
     86   std::vector<Instruction*> GetConstants();
     87   std::vector<const Instruction*> GetConstants() const;
     88 
     89   // Return result id of global value with |opcode|, 0 if not present.
     90   uint32_t GetGlobalValue(SpvOp opcode) const;
     91 
     92   // Add global value with |opcode|, |result_id| and |type_id|
     93   void AddGlobalValue(SpvOp opcode, uint32_t result_id, uint32_t type_id);
     94 
     95   inline uint32_t id_bound() const { return header_.bound; }
     96 
     97   // Iterators for debug instructions (excluding OpLine & OpNoLine) contained in
     98   // this module.
     99   inline inst_iterator debug_begin();
    100   inline inst_iterator debug_end();
    101   inline IteratorRange<inst_iterator> debugs();
    102   inline IteratorRange<const_inst_iterator> debugs() const;
    103 
    104   // Iterators for entry point instructions contained in this module
    105   inline IteratorRange<inst_iterator> entry_points();
    106   inline IteratorRange<const_inst_iterator> entry_points() const;
    107 
    108   // Clears all debug instructions (excluding OpLine & OpNoLine).
    109   void debug_clear() { debugs_.clear(); }
    110 
    111   // Iterators for annotation instructions contained in this module.
    112   IteratorRange<inst_iterator> annotations();
    113   IteratorRange<const_inst_iterator> annotations() const;
    114 
    115   // Iterators for extension instructions contained in this module.
    116   IteratorRange<inst_iterator> extensions();
    117   IteratorRange<const_inst_iterator> extensions() const;
    118 
    119   // Iterators for types, constants and global variables instructions.
    120   inline inst_iterator types_values_begin();
    121   inline inst_iterator types_values_end();
    122   inline IteratorRange<inst_iterator> types_values();
    123   inline IteratorRange<const_inst_iterator> types_values() const;
    124 
    125   // Iterators for functions contained in this module.
    126   iterator begin() { return iterator(&functions_, functions_.begin()); }
    127   iterator end() { return iterator(&functions_, functions_.end()); }
    128   inline const_iterator cbegin() const;
    129   inline const_iterator cend() const;
    130 
    131   // Invokes function |f| on all instructions in this module, and optionally on
    132   // the debug line instructions that precede them.
    133   void ForEachInst(const std::function<void(Instruction*)>& f,
    134                    bool run_on_debug_line_insts = false);
    135   void ForEachInst(const std::function<void(const Instruction*)>& f,
    136                    bool run_on_debug_line_insts = false) const;
    137 
    138   // Pushes the binary segments for this instruction into the back of *|binary|.
    139   // If |skip_nop| is true and this is a OpNop, do nothing.
    140   void ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const;
    141 
    142   // Returns 1 more than the maximum Id value mentioned in the module.
    143   uint32_t ComputeIdBound() const;
    144 
    145   // Returns true if module has capability |cap|
    146   bool HasCapability(uint32_t cap);
    147 
    148   // Returns id for OpExtInst instruction for extension |extstr|.
    149   // Returns 0 if not found.
    150   uint32_t GetExtInstImportId(const char* extstr);
    151 
    152  private:
    153   ModuleHeader header_;  // Module header
    154 
    155   // The following fields respect the "Logical Layout of a Module" in
    156   // Section 2.4 of the SPIR-V specification.
    157   std::vector<std::unique_ptr<Instruction>> capabilities_;
    158   std::vector<std::unique_ptr<Instruction>> extensions_;
    159   std::vector<std::unique_ptr<Instruction>> ext_inst_imports_;
    160   // A module only has one memory model instruction.
    161   std::unique_ptr<Instruction> memory_model_;
    162   std::vector<std::unique_ptr<Instruction>> entry_points_;
    163   std::vector<std::unique_ptr<Instruction>> execution_modes_;
    164   std::vector<std::unique_ptr<Instruction>> debugs_;
    165   std::vector<std::unique_ptr<Instruction>> annotations_;
    166   // Type declarations, constants, and global variable declarations.
    167   std::vector<std::unique_ptr<Instruction>> types_values_;
    168   std::vector<std::unique_ptr<Function>> functions_;
    169 };
    170 
    171 inline void Module::AddCapability(std::unique_ptr<Instruction> c) {
    172   capabilities_.emplace_back(std::move(c));
    173 }
    174 
    175 inline void Module::AddExtension(std::unique_ptr<Instruction> e) {
    176   extensions_.emplace_back(std::move(e));
    177 }
    178 
    179 inline void Module::AddExtInstImport(std::unique_ptr<Instruction> e) {
    180   ext_inst_imports_.emplace_back(std::move(e));
    181 }
    182 
    183 inline void Module::SetMemoryModel(std::unique_ptr<Instruction> m) {
    184   memory_model_ = std::move(m);
    185 }
    186 
    187 inline void Module::AddEntryPoint(std::unique_ptr<Instruction> e) {
    188   entry_points_.emplace_back(std::move(e));
    189 }
    190 
    191 inline void Module::AddExecutionMode(std::unique_ptr<Instruction> e) {
    192   execution_modes_.emplace_back(std::move(e));
    193 }
    194 
    195 inline void Module::AddDebugInst(std::unique_ptr<Instruction> d) {
    196   debugs_.emplace_back(std::move(d));
    197 }
    198 
    199 inline void Module::AddAnnotationInst(std::unique_ptr<Instruction> a) {
    200   annotations_.emplace_back(std::move(a));
    201 }
    202 
    203 inline void Module::AddType(std::unique_ptr<Instruction> t) {
    204   types_values_.emplace_back(std::move(t));
    205 }
    206 
    207 inline void Module::AddGlobalValue(std::unique_ptr<Instruction> v) {
    208   types_values_.emplace_back(std::move(v));
    209 }
    210 
    211 inline void Module::AddFunction(std::unique_ptr<Function> f) {
    212   functions_.emplace_back(std::move(f));
    213 }
    214 
    215 inline Module::inst_iterator Module::debug_begin() {
    216   return inst_iterator(&debugs_, debugs_.begin());
    217 }
    218 inline Module::inst_iterator Module::debug_end() {
    219   return inst_iterator(&debugs_, debugs_.end());
    220 }
    221 
    222 inline IteratorRange<Module::inst_iterator> Module::debugs() {
    223   return make_range(debugs_);
    224 }
    225 
    226 inline IteratorRange<Module::const_inst_iterator> Module::debugs() const {
    227   return make_const_range(debugs_);
    228 }
    229 
    230 inline IteratorRange<Module::inst_iterator> Module::entry_points() {
    231   return make_range(entry_points_);
    232 }
    233 
    234 inline IteratorRange<Module::const_inst_iterator> Module::entry_points() const {
    235   return make_const_range(entry_points_);
    236 }
    237 
    238 inline IteratorRange<Module::inst_iterator> Module::annotations() {
    239   return make_range(annotations_);
    240 }
    241 
    242 inline IteratorRange<Module::const_inst_iterator> Module::annotations() const {
    243   return make_const_range(annotations_);
    244 }
    245 
    246 inline IteratorRange<Module::inst_iterator> Module::extensions() {
    247   return make_range(extensions_);
    248 }
    249 
    250 inline IteratorRange<Module::const_inst_iterator> Module::extensions() const {
    251   return make_const_range(extensions_);
    252 }
    253 
    254 inline Module::inst_iterator Module::types_values_begin() {
    255   return inst_iterator(&types_values_, types_values_.begin());
    256 }
    257 
    258 inline Module::inst_iterator Module::types_values_end() {
    259   return inst_iterator(&types_values_, types_values_.end());
    260 }
    261 
    262 inline IteratorRange<Module::inst_iterator> Module::types_values() {
    263   return make_range(types_values_);
    264 }
    265 
    266 inline IteratorRange<Module::const_inst_iterator> Module::types_values() const {
    267   return make_const_range(types_values_);
    268 }
    269 
    270 inline Module::const_iterator Module::cbegin() const {
    271   return const_iterator(&functions_, functions_.cbegin());
    272 }
    273 
    274 inline Module::const_iterator Module::cend() const {
    275   return const_iterator(&functions_, functions_.cend());
    276 }
    277 
    278 }  // namespace ir
    279 }  // namespace spvtools
    280 
    281 #endif  // LIBSPIRV_OPT_MODULE_H_
    282