Home | History | Annotate | Download | only in val
      1 // Copyright (c) 2015-2016 The Khronos Group Inc.
      2 //
      3 // Permission is hereby granted, free of charge, to any person obtaining a
      4 // copy of this software and/or associated documentation files (the
      5 // "Materials"), to deal in the Materials without restriction, including
      6 // without limitation the rights to use, copy, modify, merge, publish,
      7 // distribute, sublicense, and/or sell copies of the Materials, and to
      8 // permit persons to whom the Materials are furnished to do so, subject to
      9 // the following conditions:
     10 //
     11 // The above copyright notice and this permission notice shall be included
     12 // in all copies or substantial portions of the Materials.
     13 //
     14 // MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
     15 // KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
     16 // SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
     17 //    https://www.khronos.org/registry/
     18 //
     19 // THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     22 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     23 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     24 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     25 // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
     26 
     27 #ifndef LIBSPIRV_VAL_BASICBLOCK_H_
     28 #define LIBSPIRV_VAL_BASICBLOCK_H_
     29 
     30 #include "spirv/1.1/spirv.h"
     31 
     32 #include <cstdint>
     33 
     34 #include <bitset>
     35 #include <functional>
     36 #include <vector>
     37 
     38 namespace libspirv {
     39 
     40 enum BlockType : uint32_t {
     41   kBlockTypeUndefined,
     42   kBlockTypeHeader,
     43   kBlockTypeLoop,
     44   kBlockTypeMerge,
     45   kBlockTypeBreak,
     46   kBlockTypeContinue,
     47   kBlockTypeReturn,
     48   kBlockTypeCOUNT  ///< Total number of block types. (must be the last element)
     49 };
     50 
     51 // This class represents a basic block in a SPIR-V module
     52 class BasicBlock {
     53  public:
     54   /// Constructor for a BasicBlock
     55   ///
     56   /// @param[in] id The ID of the basic block
     57   explicit BasicBlock(uint32_t id);
     58 
     59   /// Returns the id of the BasicBlock
     60   uint32_t id() const { return id_; }
     61 
     62   /// Returns the predecessors of the BasicBlock
     63   const std::vector<BasicBlock*>* predecessors() const {
     64     return &predecessors_;
     65   }
     66 
     67   /// Returns the predecessors of the BasicBlock
     68   std::vector<BasicBlock*>* predecessors() { return &predecessors_; }
     69 
     70   /// Returns the successors of the BasicBlock
     71   const std::vector<BasicBlock*>* successors() const { return &successors_; }
     72 
     73   /// Returns the successors of the BasicBlock
     74   std::vector<BasicBlock*>* successors() { return &successors_; }
     75 
     76   /// Returns true if the block is reachable in the CFG
     77   bool reachable() const { return reachable_; }
     78 
     79   /// Returns true if BasicBlock is of the given type
     80   bool is_type(BlockType type) const {
     81     if (type == kBlockTypeUndefined) return type_.none();
     82     return type_.test(type);
     83   }
     84 
     85   /// Sets the reachability of the basic block in the CFG
     86   void set_reachable(bool reachability) { reachable_ = reachability; }
     87 
     88   /// Sets the type of the BasicBlock
     89   void set_type(BlockType type) {
     90     if (type == kBlockTypeUndefined)
     91       type_.reset();
     92     else
     93       type_.set(type);
     94   }
     95 
     96   /// Sets the immedate dominator of this basic block
     97   ///
     98   /// @param[in] dom_block The dominator block
     99   void SetImmediateDominator(BasicBlock* dom_block);
    100 
    101   /// Sets the immedate post dominator of this basic block
    102   ///
    103   /// @param[in] pdom_block The post dominator block
    104   void SetImmediatePostDominator(BasicBlock* pdom_block);
    105 
    106   /// Returns the immedate dominator of this basic block
    107   BasicBlock* immediate_dominator();
    108 
    109   /// Returns the immedate dominator of this basic block
    110   const BasicBlock* immediate_dominator() const;
    111 
    112   /// Returns the immedate post dominator of this basic block
    113   BasicBlock* immediate_post_dominator();
    114 
    115   /// Returns the immedate post dominator of this basic block
    116   const BasicBlock* immediate_post_dominator() const;
    117 
    118   /// Ends the block without a successor
    119   void RegisterBranchInstruction(SpvOp branch_instruction);
    120 
    121   /// Adds @p next BasicBlocks as successors of this BasicBlock
    122   void RegisterSuccessors(const std::vector<BasicBlock*>& next = {});
    123 
    124   /// Set the successors to this block, without updating other internal state,
    125   /// and without updating the other blocks.
    126   void SetSuccessorsUnsafe(std::vector<BasicBlock*>&& others);
    127 
    128   /// Set the predecessors to this block, without updating other internal state,
    129   /// and without updating the other blocks.
    130   void SetPredecessorsUnsafe(std::vector<BasicBlock*>&& others);
    131 
    132   /// Returns true if the id of the BasicBlock matches
    133   bool operator==(const BasicBlock& other) const { return other.id_ == id_; }
    134 
    135   /// Returns true if the id of the BasicBlock matches
    136   bool operator==(const uint32_t& other_id) const { return other_id == id_; }
    137 
    138   /// @brief A BasicBlock dominator iterator class
    139   ///
    140   /// This iterator will iterate over the (post)dominators of the block
    141   class DominatorIterator
    142       : public std::iterator<std::forward_iterator_tag, BasicBlock*> {
    143    public:
    144     /// @brief Constructs the end of dominator iterator
    145     ///
    146     /// This will create an iterator which will represent the element
    147     /// before the root node of the dominator tree
    148     DominatorIterator();
    149 
    150     /// @brief Constructs an iterator for the given block which points to
    151     ///        @p block
    152     ///
    153     /// @param block          The block which is referenced by the iterator
    154     /// @param dominator_func This function will be called to get the immediate
    155     ///                       (post)dominator of the current block
    156     DominatorIterator(
    157         const BasicBlock* block,
    158         std::function<const BasicBlock*(const BasicBlock*)> dominator_func);
    159 
    160     /// @brief Advances the iterator
    161     DominatorIterator& operator++();
    162 
    163     /// @brief Returns the current element
    164     const BasicBlock*& operator*();
    165 
    166     friend bool operator==(const DominatorIterator& lhs,
    167                            const DominatorIterator& rhs);
    168 
    169    private:
    170     const BasicBlock* current_;
    171     std::function<const BasicBlock*(const BasicBlock*)> dom_func_;
    172   };
    173 
    174   /// Returns a dominator iterator which points to the current block
    175   const DominatorIterator dom_begin() const;
    176 
    177   /// Returns a dominator iterator which points to the current block
    178   DominatorIterator dom_begin();
    179 
    180   /// Returns a dominator iterator which points to one element past the first
    181   /// block
    182   const DominatorIterator dom_end() const;
    183 
    184   /// Returns a dominator iterator which points to one element past the first
    185   /// block
    186   DominatorIterator dom_end();
    187 
    188   /// Returns a post dominator iterator which points to the current block
    189   const DominatorIterator pdom_begin() const;
    190   /// Returns a post dominator iterator which points to the current block
    191   DominatorIterator pdom_begin();
    192 
    193   /// Returns a post dominator iterator which points to one element past the
    194   /// last block
    195   const DominatorIterator pdom_end() const;
    196 
    197   /// Returns a post dominator iterator which points to one element past the
    198   /// last block
    199   DominatorIterator pdom_end();
    200 
    201  private:
    202   /// Id of the BasicBlock
    203   const uint32_t id_;
    204 
    205   /// Pointer to the immediate dominator of the BasicBlock
    206   BasicBlock* immediate_dominator_;
    207 
    208   /// Pointer to the immediate dominator of the BasicBlock
    209   BasicBlock* immediate_post_dominator_;
    210 
    211   /// The set of predecessors of the BasicBlock
    212   std::vector<BasicBlock*> predecessors_;
    213 
    214   /// The set of successors of the BasicBlock
    215   std::vector<BasicBlock*> successors_;
    216 
    217   /// The type of the block
    218   std::bitset<kBlockTypeCOUNT - 1> type_;
    219 
    220   /// True if the block is reachable in the CFG
    221   bool reachable_;
    222 };
    223 
    224 /// @brief Returns true if the iterators point to the same element or if both
    225 ///        iterators point to the @p dom_end block
    226 bool operator==(const BasicBlock::DominatorIterator& lhs,
    227                 const BasicBlock::DominatorIterator& rhs);
    228 
    229 /// @brief Returns true if the iterators point to different elements and they
    230 ///        do not both point to the @p dom_end block
    231 bool operator!=(const BasicBlock::DominatorIterator& lhs,
    232                 const BasicBlock::DominatorIterator& rhs);
    233 
    234 }  /// namespace libspirv
    235 
    236 #endif  /// LIBSPIRV_VAL_BASICBLOCK_H_
    237