Jlm
cfg.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2014 Helge Bahmann <hcb@chaoticmind.net>
3  * Copyright 2013 2014 2015 Nico Reißmann <nico.reissmann@gmail.com>
4  * See COPYING for terms of redistribution.
5  */
6 
11 
12 #include <algorithm>
13 #include <deque>
14 #include <unordered_map>
15 
16 namespace jlm::llvm
17 {
18 
19 Argument::~Argument() noexcept = default;
20 
21 EntryNode::~EntryNode() noexcept = default;
22 
23 ExitNode::~ExitNode() noexcept = default;
24 
26  : module_(im)
27 {
28  entry_ = std::make_unique<EntryNode>(*this);
29  exit_ = std::make_unique<ExitNode>(*this);
30  entry_->add_outedge(exit_.get());
31 }
32 
35 {
36  auto & cfg = nodeit->cfg();
37 
38  for (auto & inedge : nodeit->InEdges())
39  {
40  if (inedge.source() != &*nodeit)
41  throw util::Error("cannot remove node. It has still incoming edges.");
42  }
43 
44  nodeit->remove_outedges();
45  std::unique_ptr<BasicBlock> tmp(&*nodeit);
46  auto rit = iterator(std::next(cfg.nodes_.find(tmp)));
47  cfg.nodes_.erase(tmp);
48  tmp.release();
49  return rit;
50 }
51 
54 {
55  auto & cfg = bb->cfg();
56 
57  auto it = cfg.find_node(bb);
58  return remove_node(it);
59 }
60 
61 std::string
63 {
64  std::string str;
65  auto nodes = breadth_first(controlFlowGraph);
66  auto labels = CreateLabels(nodes);
67  for (const auto & node : nodes)
68  {
69  str += labels.at(node) + ":";
70  str += (is<BasicBlock>(node) ? "\n" : " ");
71 
72  if (const auto entryNode = dynamic_cast<const EntryNode *>(node))
73  {
74  str += ToAscii(*entryNode);
75  }
76  else if (const auto exitNode = dynamic_cast<const ExitNode *>(node))
77  {
78  str += ToAscii(*exitNode);
79  }
80  else if (auto basicBlock = dynamic_cast<const BasicBlock *>(node))
81  {
82  str += ToAscii(*basicBlock, labels);
83  }
84  else
85  {
86  JLM_UNREACHABLE("Unhandled control flow graph node type!");
87  }
88  }
89 
90  return str;
91 }
92 
93 std::string
95 {
96  std::string str;
97  for (size_t n = 0; n < entryNode.narguments(); n++)
98  {
99  str += entryNode.argument(n)->debug_string() + " ";
100  }
101 
102  return str + "\n";
103 }
104 
105 std::string
107 {
108  std::string str;
109  for (size_t n = 0; n < exitNode.nresults(); n++)
110  {
111  str += exitNode.result(n)->debug_string() + " ";
112  }
113 
114  return str;
115 }
116 
117 std::string
119  const BasicBlock & basicBlock,
120  const std::unordered_map<ControlFlowGraphNode *, std::string> & labels)
121 {
122  auto & threeAddressCodes = basicBlock.tacs();
123 
124  std::string str;
125  for (const auto & tac : threeAddressCodes)
126  {
127  str += "\t" + ThreeAddressCode::ToAscii(*tac);
128  if (tac != threeAddressCodes.last())
129  str += "\n";
130  }
131 
132  if (threeAddressCodes.last())
133  {
134  if (is<BranchOperation>(threeAddressCodes.last()->operation()))
135  str += " " + CreateTargets(basicBlock, labels);
136  else
137  str += "\n\t" + CreateTargets(basicBlock, labels);
138  }
139  else
140  {
141  str += "\t" + CreateTargets(basicBlock, labels);
142  }
143 
144  return str + "\n";
145 }
146 
147 std::string
149  const ControlFlowGraphNode & node,
150  const std::unordered_map<ControlFlowGraphNode *, std::string> & labels)
151 {
152  size_t n = 0;
153  std::string str("[");
154  for (auto & outedge : node.OutEdges())
155  {
156  str += labels.at(outedge.sink());
157  if (n != node.NumOutEdges() - 1)
158  str += ", ";
159  }
160  str += "]";
161 
162  return str;
163 }
164 
165 std::unordered_map<ControlFlowGraphNode *, std::string>
166 ControlFlowGraph::CreateLabels(const std::vector<ControlFlowGraphNode *> & nodes)
167 {
168  std::unordered_map<ControlFlowGraphNode *, std::string> map;
169  for (size_t n = 0; n < nodes.size(); n++)
170  {
171  auto node = nodes[n];
172  if (is<EntryNode>(node))
173  {
174  map[node] = "entry";
175  }
176  else if (is<ExitNode>(node))
177  {
178  map[node] = "exit";
179  }
180  else if (is<BasicBlock>(node))
181  {
182  map[node] = util::strfmt("bb", n);
183  }
184  else
185  {
186  JLM_UNREACHABLE("Unhandled control flow graph node type!");
187  }
188  }
189 
190  return map;
191 }
192 
193 std::vector<ControlFlowGraphNode *>
195 {
196  JLM_ASSERT(is_closed(cfg));
197 
198  std::function<void(
200  std::unordered_set<ControlFlowGraphNode *> &,
201  std::vector<ControlFlowGraphNode *> &)>
202  traverse = [&](ControlFlowGraphNode * node,
203  std::unordered_set<ControlFlowGraphNode *> & visited,
204  std::vector<ControlFlowGraphNode *> & nodes)
205  {
206  visited.insert(node);
207  for (size_t n = 0; n < node->NumOutEdges(); n++)
208  {
209  auto edge = node->OutEdge(n);
210  if (visited.find(edge->sink()) == visited.end())
211  traverse(edge->sink(), visited, nodes);
212  }
213 
214  nodes.push_back(node);
215  };
216 
217  std::vector<ControlFlowGraphNode *> nodes;
218  std::unordered_set<ControlFlowGraphNode *> visited;
219  traverse(cfg.entry(), visited, nodes);
220 
221  return nodes;
222 }
223 
224 std::vector<ControlFlowGraphNode *>
226 {
227  auto nodes = postorder(cfg);
228  std::reverse(nodes.begin(), nodes.end());
229  return nodes;
230 }
231 
232 std::vector<ControlFlowGraphNode *>
234 {
235  std::deque<ControlFlowGraphNode *> next({ cfg.entry() });
236  std::vector<ControlFlowGraphNode *> nodes({ cfg.entry() });
237  std::unordered_set<ControlFlowGraphNode *> visited({ cfg.entry() });
238  while (!next.empty())
239  {
240  auto node = next.front();
241  next.pop_front();
242 
243  for (auto & outedge : node->OutEdges())
244  {
245  if (visited.find(outedge.sink()) == visited.end())
246  {
247  visited.insert(outedge.sink());
248  next.push_back(outedge.sink());
249  nodes.push_back(outedge.sink());
250  }
251  }
252  }
253 
254  return nodes;
255 }
256 
257 size_t
259 {
260  size_t ntacs = 0;
261  for (auto & node : cfg)
262  {
263  if (auto bb = dynamic_cast<const BasicBlock *>(&node))
264  ntacs += bb->ntacs();
265  }
266 
267  return ntacs;
268 }
269 
270 }
~Argument() noexcept override
const ThreeAddressCodeList & tacs() const noexcept
Definition: basic-block.hpp:38
ControlFlowGraphEdge * OutEdge(size_t n) const
Definition: cfg-node.hpp:115
ControlFlowGraph & cfg() const noexcept
Definition: cfg-node.hpp:106
outedge_iterator_range OutEdges() const
Definition: cfg-node.hpp:122
size_t NumOutEdges() const noexcept
Definition: cfg-node.cpp:46
static std::string ToAscii(const ControlFlowGraph &controlFlowGraph)
Definition: cfg.cpp:62
EntryNode * entry() const noexcept
Definition: cfg.hpp:205
static ControlFlowGraph::iterator remove_node(ControlFlowGraph::iterator &it)
Definition: cfg.cpp:34
ControlFlowGraph::iterator find_node(BasicBlock *bb)
Definition: cfg.hpp:225
static std::unordered_map< ControlFlowGraphNode *, std::string > CreateLabels(const std::vector< ControlFlowGraphNode * > &nodes)
Definition: cfg.cpp:166
static std::string CreateTargets(const ControlFlowGraphNode &node, const std::unordered_map< ControlFlowGraphNode *, std::string > &labels)
Definition: cfg.cpp:148
util::PtrIterator< BasicBlock, std::unordered_set< std::unique_ptr< BasicBlock > >::iterator > iterator
Definition: cfg.hpp:160
size_t narguments() const noexcept
Definition: cfg.hpp:86
const llvm::Argument * argument(size_t index) const
Definition: cfg.hpp:92
const Variable * result(size_t index) const
Definition: cfg.hpp:135
size_t nresults() const noexcept
Definition: cfg.hpp:129
static std::string ToAscii(const ThreeAddressCode &threeAddressCode)
Definition: tac.cpp:120
virtual std::string debug_string() const
Definition: variable.cpp:14
#define JLM_ASSERT(x)
Definition: common.hpp:16
#define JLM_UNREACHABLE(msg)
Definition: common.hpp:43
Global memory state passed between functions.
std::vector< ControlFlowGraphNode * > breadth_first(const ControlFlowGraph &cfg)
Definition: cfg.cpp:233
std::vector< ControlFlowGraphNode * > postorder(const ControlFlowGraph &cfg)
Definition: cfg.cpp:194
size_t ntacs(const AggregationNode &root)
bool is_closed(const ControlFlowGraph &cfg)
std::vector< ControlFlowGraphNode * > reverse_postorder(const ControlFlowGraph &cfg)
Definition: cfg.cpp:225
static std::string strfmt(Args... args)
Definition: strfmt.hpp:35