1 // Copyright (c) 2015-2016 The Khronos Group 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_VAL_CONSTRUCT_H_ 16 #define LIBSPIRV_VAL_CONSTRUCT_H_ 17 18 #include <cstdint> 19 #include <vector> 20 21 namespace libspirv { 22 23 enum class ConstructType : int { 24 kNone = 0, 25 /// The set of blocks dominated by a selection header, minus the set of blocks 26 /// dominated by the header's merge block 27 kSelection, 28 /// The set of blocks dominated by an OpLoopMerge's Continue Target and post 29 /// dominated by the corresponding back 30 kContinue, 31 /// The set of blocks dominated by a loop header, minus the set of blocks 32 /// dominated by the loop's merge block, minus the loop's corresponding 33 /// continue construct 34 kLoop, 35 /// The set of blocks dominated by an OpSwitch's Target or Default, minus the 36 /// set of blocks dominated by the OpSwitch's merge block (this construct is 37 /// only defined for those OpSwitch Target or Default that are not equal to 38 /// the OpSwitch's corresponding merge block) 39 kCase 40 }; 41 42 class BasicBlock; 43 44 /// @brief This class tracks the CFG constructs as defined in the SPIR-V spec 45 class Construct { 46 public: 47 Construct(ConstructType type, BasicBlock* dominator, 48 BasicBlock* exit = nullptr, 49 std::vector<Construct*> constructs = std::vector<Construct*>()); 50 51 /// Returns the type of the construct 52 ConstructType type() const; 53 54 const std::vector<Construct*>& corresponding_constructs() const; 55 std::vector<Construct*>& corresponding_constructs(); 56 void set_corresponding_constructs(std::vector<Construct*> constructs); 57 58 /// Returns the dominator block of the construct. 59 /// 60 /// This is usually the header block or the first block of the construct. 61 const BasicBlock* entry_block() const; 62 63 /// Returns the dominator block of the construct. 64 /// 65 /// This is usually the header block or the first block of the construct. 66 BasicBlock* entry_block(); 67 68 /// Returns the exit block of the construct. 69 /// 70 /// For a continue construct it is the backedge block of the corresponding 71 /// loop construct. For the case construct it is the block that branches to 72 /// the OpSwitch merge block or other case blocks. Otherwise it is the merge 73 /// block of the corresponding header block 74 const BasicBlock* exit_block() const; 75 76 /// Returns the exit block of the construct. 77 /// 78 /// For a continue construct it is the backedge block of the corresponding 79 /// loop construct. For the case construct it is the block that branches to 80 /// the OpSwitch merge block or other case blocks. Otherwise it is the merge 81 /// block of the corresponding header block 82 BasicBlock* exit_block(); 83 84 /// Sets the exit block for this construct. This is useful for continue 85 /// constructs which do not know the back-edge block during construction 86 void set_exit(BasicBlock* exit_block); 87 88 // Returns whether the exit block of this construct is the merge block 89 // for an OpLoopMerge or OpSelectionMerge ExitBlockIsMergeBlock()90 bool ExitBlockIsMergeBlock() const { 91 return type_ == ConstructType::kLoop || type_ == ConstructType::kSelection; 92 } 93 94 private: 95 /// The type of the construct 96 ConstructType type_; 97 98 /// These are the constructs that are related to this construct. These 99 /// constructs can be the continue construct, for the corresponding loop 100 /// construct, the case construct that are part of the same OpSwitch 101 /// instruction 102 /// 103 /// Here is a table that describes what constructs are included in 104 /// @p corresponding_constructs_ 105 /// | this construct | corresponding construct | 106 /// |----------------|----------------------------------| 107 /// | loop | continue | 108 /// | continue | loop | 109 /// | case | other cases in the same OpSwitch | 110 /// 111 /// kContinue and kLoop constructs will always have corresponding 112 /// constructs even if they are represented by the same block 113 std::vector<Construct*> corresponding_constructs_; 114 115 /// @brief Dominator block for the construct 116 /// 117 /// The dominator block for the construct. Depending on the construct this may 118 /// be a selection header, a continue target of a loop, a loop header or a 119 /// Target or Default block of a switch 120 BasicBlock* entry_block_; 121 122 /// @brief Exiting block for the construct 123 /// 124 /// The exit block for the construct. This can be a merge block for the loop 125 /// and selection constructs, a back-edge block for a continue construct, or 126 /// the branching block for the case construct 127 BasicBlock* exit_block_; 128 }; 129 130 } /// namespace libspirv 131 132 #endif /// LIBSPIRV_VAL_CONSTRUCT_H_ 133