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#include "BasicBlock.h" 28 29#include <utility> 30#include <vector> 31 32using std::vector; 33 34namespace libspirv { 35 36BasicBlock::BasicBlock(uint32_t label_id) 37 : id_(label_id), 38 immediate_dominator_(nullptr), 39 immediate_post_dominator_(nullptr), 40 predecessors_(), 41 successors_(), 42 type_(0), 43 reachable_(false) {} 44 45void BasicBlock::SetImmediateDominator(BasicBlock* dom_block) { 46 immediate_dominator_ = dom_block; 47} 48 49void BasicBlock::SetImmediatePostDominator(BasicBlock* pdom_block) { 50 immediate_post_dominator_ = pdom_block; 51} 52 53const BasicBlock* BasicBlock::immediate_dominator() const { 54 return immediate_dominator_; 55} 56 57const BasicBlock* BasicBlock::immediate_post_dominator() const { 58 return immediate_post_dominator_; 59} 60 61BasicBlock* BasicBlock::immediate_dominator() { return immediate_dominator_; } 62BasicBlock* BasicBlock::immediate_post_dominator() { 63 return immediate_post_dominator_; 64} 65 66void BasicBlock::RegisterSuccessors(const vector<BasicBlock*>& next_blocks) { 67 for (auto& block : next_blocks) { 68 block->predecessors_.push_back(this); 69 successors_.push_back(block); 70 if (block->reachable_ == false) block->set_reachable(reachable_); 71 } 72} 73 74void BasicBlock::RegisterBranchInstruction(SpvOp branch_instruction) { 75 if (branch_instruction == SpvOpUnreachable) reachable_ = false; 76 return; 77} 78 79void BasicBlock::SetSuccessorsUnsafe(std::vector<BasicBlock*>&& others) { 80 successors_ = std::move(others); 81} 82 83void BasicBlock::SetPredecessorsUnsafe(std::vector<BasicBlock*>&& others) { 84 predecessors_ = std::move(others); 85} 86 87BasicBlock::DominatorIterator::DominatorIterator() : current_(nullptr) {} 88 89BasicBlock::DominatorIterator::DominatorIterator( 90 const BasicBlock* block, 91 std::function<const BasicBlock*(const BasicBlock*)> dominator_func) 92 : current_(block), dom_func_(dominator_func) {} 93 94BasicBlock::DominatorIterator& BasicBlock::DominatorIterator::operator++() { 95 if (current_ == dom_func_(current_)) { 96 current_ = nullptr; 97 } else { 98 current_ = dom_func_(current_); 99 } 100 return *this; 101} 102 103const BasicBlock::DominatorIterator BasicBlock::dom_begin() const { 104 return DominatorIterator( 105 this, [](const BasicBlock* b) { return b->immediate_dominator(); }); 106} 107 108BasicBlock::DominatorIterator BasicBlock::dom_begin() { 109 return DominatorIterator( 110 this, [](const BasicBlock* b) { return b->immediate_dominator(); }); 111} 112 113const BasicBlock::DominatorIterator BasicBlock::dom_end() const { 114 return DominatorIterator(); 115} 116 117BasicBlock::DominatorIterator BasicBlock::dom_end() { 118 return DominatorIterator(); 119} 120 121const BasicBlock::DominatorIterator BasicBlock::pdom_begin() const { 122 return DominatorIterator( 123 this, [](const BasicBlock* b) { return b->immediate_post_dominator(); }); 124} 125 126BasicBlock::DominatorIterator BasicBlock::pdom_begin() { 127 return DominatorIterator( 128 this, [](const BasicBlock* b) { return b->immediate_post_dominator(); }); 129} 130 131const BasicBlock::DominatorIterator BasicBlock::pdom_end() const { 132 return DominatorIterator(); 133} 134 135BasicBlock::DominatorIterator BasicBlock::pdom_end() { 136 return DominatorIterator(); 137} 138 139bool operator==(const BasicBlock::DominatorIterator& lhs, 140 const BasicBlock::DominatorIterator& rhs) { 141 return lhs.current_ == rhs.current_; 142} 143 144bool operator!=(const BasicBlock::DominatorIterator& lhs, 145 const BasicBlock::DominatorIterator& rhs) { 146 return !(lhs == rhs); 147} 148 149const BasicBlock*& BasicBlock::DominatorIterator::operator*() { 150 return current_; 151} 152} // namespace libspirv 153