| 70 | void Construct::set_exit(BasicBlock* block) { exit_block_ = block; } |
| 71 | |
| 72 | Construct::ConstructBlockSet Construct::blocks(Function* /*function*/) const { |
| 73 | const auto header = entry_block(); |
| 74 | const auto exit = exit_block(); |
| 75 | const bool is_continue = type() == ConstructType::kContinue; |
| 76 | const bool is_loop = type() == ConstructType::kLoop; |
| 77 | const BasicBlock* continue_header = nullptr; |
| 78 | if (is_loop) { |
| 79 | // The only corresponding construct for a loop is the continue. |
| 80 | continue_header = (*corresponding_constructs().begin())->entry_block(); |
| 81 | } |
| 82 | std::vector<BasicBlock*> stack; |
| 83 | stack.push_back(const_cast<BasicBlock*>(header)); |
| 84 | ConstructBlockSet construct_blocks; |
| 85 | while (!stack.empty()) { |
| 86 | auto* block = stack.back(); |
| 87 | stack.pop_back(); |
| 88 | |
| 89 | if (header->structurally_dominates(*block)) { |
| 90 | bool include = false; |
| 91 | if (is_continue && exit->structurally_postdominates(*block)) { |
| 92 | // Continue construct include blocks dominated by the continue target |
| 93 | // and post-dominated by the back-edge block. |
| 94 | include = true; |
| 95 | } else if (!exit->structurally_dominates(*block)) { |
| 96 | // Selection and loop constructs include blocks dominated by the header |
| 97 | // and not dominated by the merge. |
| 98 | include = true; |
| 99 | if (is_loop && continue_header->structurally_dominates(*block)) { |
| 100 | // Loop constructs have an additional constraint that they do not |
| 101 | // include blocks dominated by the continue construct. Since all |
| 102 | // blocks in the continue construct are dominated by the continue |
| 103 | // target, we just test for dominance by continue target. |
| 104 | include = false; |
| 105 | } |
| 106 | } |
| 107 | if (include) { |
| 108 | if (!construct_blocks.insert(block).second) continue; |
| 109 | |
| 110 | for (auto succ : *block->structural_successors()) { |
| 111 | stack.push_back(succ); |
| 112 | } |
| 113 | } |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | return construct_blocks; |
| 118 | } |
| 119 | |
| 120 | bool Construct::IsStructuredExit(ValidationState_t& _, BasicBlock* dest) const { |
| 121 | // Structured Exits: |
no test coverage detected