-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathBlockGraph.hpp
99 lines (82 loc) · 2.96 KB
/
BlockGraph.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#pragma once
#include "SimpleBlock.hpp"
#include "ConditionalBlock.hpp"
#include "Trace.hpp"
#include <vector>
#include <fstream>
#include <unordered_map>
namespace irt {
class BlockGraph {
public:
explicit BlockGraph(Block* root) : root_(root) {}
Block* GetRoot() const {
return root_;
}
std::vector<Trace*> GetTraces() {
TraverseDFS(root_);
return traces_;
}
void TraverseDFS(Block* block, Trace* current_trace = nullptr) {
if (block == nullptr || visited_[block]) {
return;
} else if (current_trace == nullptr) {
traces_.push_back(new Trace());
current_trace = traces_.back();
}
visited_[block] = true;
current_trace->AddBlock(block);
block->SetHasTrace();
if (block->IsSimple()) {
auto simple_block = dynamic_cast<SimpleBlock*>(block);
TraverseDFS(simple_block->GetNextBlock(), current_trace);
} else {
auto conditional_block = dynamic_cast<ConditionalBlock*>(block);
TraverseDFS(conditional_block->GetFalseBlock(), current_trace);
TraverseDFS(conditional_block->GetTrueBlock());
}
}
void TraverseOutput(Block* block) {
if (block == nullptr || visited_[block]) {
return;
}
visited_[block] = true;
stream_ << block->GetLabel().ToString();
if (block->IsSimple()) {
auto simple_block = dynamic_cast<SimpleBlock*>(block);
stream_ << " -> [next]: " << ((simple_block->GetNextBlock() != nullptr) ?
simple_block->GetNextBlock()->GetLabel().ToString() : "null")
<< std::endl;
TraverseOutput(simple_block->GetNextBlock());
} else {
auto conditional_block = dynamic_cast<ConditionalBlock*>(block);
stream_ << " -> [false]: " << ((conditional_block->GetFalseBlock() != nullptr) ?
conditional_block->GetFalseBlock()->GetLabel().ToString() : "null")
<< " [true]: " << ((conditional_block->GetTrueBlock() != nullptr) ?
conditional_block->GetTrueBlock()->GetLabel().ToString() : "null")
<< std::endl;
TraverseOutput(conditional_block->GetFalseBlock());
TraverseOutput(conditional_block->GetTrueBlock());
}
}
void OutputGraph(const std::string& method_name, const std::string& suffix) {
stream_ = std::move(std::ofstream(method_name + suffix));
stream_ << "Blocks for method \'" << method_name << "\':" << std::endl;
visited_.clear();
TraverseOutput(root_);
}
void OutputTraces(const std::string& method_name, const std::string suffix) {
stream_ = std::move(std::ofstream(method_name + suffix));
stream_ << "Traces for method \'" << method_name << "\':" << std::endl;
visited_.clear();
traces_ = GetTraces();
for (const auto& trace : traces_) {
trace->Output(stream_);
}
}
private:
Block* root_;
std::vector<Trace*> traces_;
std::ofstream stream_;
std::unordered_map<Block*, bool> visited_;
};
}