16 #include <unordered_map>
23 EntryNode::~EntryNode() noexcept = default;
25 ExitNode::~ExitNode() noexcept = default;
30 entry_ = std::make_unique<EntryNode>(*
this);
31 exit_ = std::make_unique<ExitNode>(*
this);
32 entry_->add_outedge(exit_.get());
38 auto & cfg = nodeit->cfg();
40 for (
auto & inedge : nodeit->InEdges())
42 if (inedge.source() != &*nodeit)
43 throw util::Error(
"cannot remove node. It has still incoming edges.");
46 nodeit->remove_outedges();
47 std::unique_ptr<BasicBlock> tmp(&*nodeit);
48 auto rit =
iterator(std::next(cfg.nodes_.find(tmp)));
49 cfg.nodes_.erase(tmp);
57 auto & cfg = bb->
cfg();
70 const auto entryNode = controlFlowGraph.
entry();
71 auto & dotEntryNode = dotGraph.
CreateInOutNode(0, entryNode->NumOutEdges());
74 std::string label =
"Entry\n";
75 for (
const auto argument : entryNode->arguments())
77 label += argument->name() +
" <" + argument->type().debug_string() +
">\n";
79 dotEntryNode.SetLabel(label);
82 const auto exitNode = controlFlowGraph.
exit();
83 auto & dotExitNode = dotGraph.
CreateInOutNode(exitNode->NumInEdges(), 0);
87 for (
const auto result : exitNode->results())
89 label += result->name() +
" <" + result->type().debug_string() +
">\n";
91 dotExitNode.SetLabel(label);
94 for (
auto & basicBlock : controlFlowGraph)
96 auto & dotBasicBlock =
97 dotGraph.
CreateInOutNode(basicBlock.NumInEdges(), basicBlock.NumOutEdges());
101 for (
const auto & tac : basicBlock.tacs())
103 dotBasicBlock.SetLabel(label);
120 for (
auto & edge : node.InEdges())
122 createEdge(edge, index++);
126 for (
auto & basicBlock : controlFlowGraph)
128 createEdges(basicBlock);
130 createEdges(*exitNode);
139 toDot(graphWriter, *
this);
144 std::ofstream outputFile(outputFilePath.
to_str());
156 for (
const auto & node : nodes)
158 str += labels.at(node) +
":";
159 str += (is<BasicBlock>(node) ?
"\n" :
" ");
161 if (
const auto entryNode =
dynamic_cast<const EntryNode *
>(node))
165 else if (
const auto exitNode =
dynamic_cast<const ExitNode *
>(node))
169 else if (
auto basicBlock =
dynamic_cast<const BasicBlock *
>(node))
171 str +=
ToAscii(*basicBlock, labels);
186 for (
size_t n = 0; n < entryNode.
narguments(); n++)
198 for (
size_t n = 0; n < exitNode.
nresults(); n++)
209 const std::unordered_map<ControlFlowGraphNode *, std::string> & labels)
211 auto & threeAddressCodes = basicBlock.
tacs();
214 for (
const auto & tac : threeAddressCodes)
217 if (tac != threeAddressCodes.last())
221 if (threeAddressCodes.last())
223 if (is<BranchOperation>(threeAddressCodes.last()->operation()))
239 const std::unordered_map<ControlFlowGraphNode *, std::string> & labels)
242 std::string str(
"[");
243 for (
auto & outedge : node.
OutEdges())
245 str += labels.at(outedge.sink());
254 std::unordered_map<ControlFlowGraphNode *, std::string>
257 std::unordered_map<ControlFlowGraphNode *, std::string> map;
258 for (
size_t n = 0; n < nodes.size(); n++)
260 auto node = nodes[n];
261 if (is<EntryNode>(node))
265 else if (is<ExitNode>(node))
269 else if (is<BasicBlock>(node))
282 std::vector<ControlFlowGraphNode *>
289 std::unordered_set<ControlFlowGraphNode *> &,
290 std::vector<ControlFlowGraphNode *> &)>
292 std::unordered_set<ControlFlowGraphNode *> & visited,
293 std::vector<ControlFlowGraphNode *> & nodes)
295 visited.insert(node);
299 if (visited.find(edge->sink()) == visited.end())
300 traverse(edge->sink(), visited, nodes);
303 nodes.push_back(node);
306 std::vector<ControlFlowGraphNode *> nodes;
307 std::unordered_set<ControlFlowGraphNode *> visited;
308 traverse(cfg.
entry(), visited, nodes);
313 std::vector<ControlFlowGraphNode *>
317 std::reverse(nodes.begin(), nodes.end());
321 std::vector<ControlFlowGraphNode *>
324 std::deque<ControlFlowGraphNode *> next({ cfg.
entry() });
325 std::vector<ControlFlowGraphNode *> nodes({ cfg.
entry() });
326 std::unordered_set<ControlFlowGraphNode *> visited({ cfg.
entry() });
327 while (!next.empty())
329 auto node = next.front();
332 for (
auto & outedge : node->OutEdges())
334 if (visited.find(outedge.sink()) == visited.end())
336 visited.insert(outedge.sink());
337 next.push_back(outedge.sink());
338 nodes.push_back(outedge.sink());
350 for (
auto & node : cfg)
352 if (
auto bb =
dynamic_cast<const BasicBlock *
>(&node))
353 ntacs += bb->ntacs();
~Argument() noexcept override
const ThreeAddressCodeList & tacs() const noexcept
size_t index() const noexcept
ControlFlowGraphNode * sink() const noexcept
ControlFlowGraphNode * source() const noexcept
ControlFlowGraphEdge * OutEdge(size_t n) const
ControlFlowGraph & cfg() const noexcept
outedge_iterator_range OutEdges() const
size_t NumOutEdges() const noexcept
static std::string ToAscii(const ControlFlowGraph &controlFlowGraph)
EntryNode * entry() const noexcept
static ControlFlowGraph::iterator remove_node(ControlFlowGraph::iterator &it)
ControlFlowGraph::iterator find_node(BasicBlock *bb)
ExitNode * exit() const noexcept
static std::unordered_map< ControlFlowGraphNode *, std::string > CreateLabels(const std::vector< ControlFlowGraphNode * > &nodes)
static std::string CreateTargets(const ControlFlowGraphNode &node, const std::unordered_map< ControlFlowGraphNode *, std::string > &labels)
static util::graph::Graph & toDot(util::graph::Writer &writer, const ControlFlowGraph &controlFlowGraph)
util::PtrIterator< BasicBlock, std::unordered_set< std::unique_ptr< BasicBlock > >::iterator > iterator
size_t narguments() const noexcept
const llvm::Argument * argument(size_t index) const
const Variable * result(size_t index) const
size_t nresults() const noexcept
static std::string ToAscii(const ThreeAddressCode &threeAddressCode)
virtual std::string debug_string() const
static FilePath createUniqueFileName(const FilePath &directory, const std::string &fileNamePrefix, const std::string &fileNameSuffix)
Generates a unique file in a given directory with a prefix and suffix.
static FilePath TempDirectoryPath()
const std::string & to_str() const noexcept
void SetProgramObject(const T &object)
void SetLabel(std::string label)
InOutNode & CreateInOutNode(size_t inputPorts, size_t outputPorts)
Edge & CreateDirectedEdge(Port &from, Port &to)
Element & GetFromProgramObject(const ProgramObject &object) const
OutputPort & GetOutputPort(size_t index)
InputPort & GetInputPort(size_t index)
void outputAllGraphs(std::ostream &out, OutputFormat format)
#define JLM_UNREACHABLE(msg)
Global memory state passed between functions.
std::vector< ControlFlowGraphNode * > breadth_first(const ControlFlowGraph &cfg)
std::vector< ControlFlowGraphNode * > postorder(const ControlFlowGraph &cfg)
size_t ntacs(const AggregationNode &root)
bool is_closed(const ControlFlowGraph &cfg)
std::vector< ControlFlowGraphNode * > reverse_postorder(const ControlFlowGraph &cfg)
std::string getDotViewer()
static std::string strfmt(Args... args)
int executeProgramAndWait(const std::string &programName, const std::vector< std::string > &programArguments)