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