Jlm
Loading...
Searching...
No Matches
ipgraph.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2013 2014 2015 Nico Reißmann <nico.reissmann@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
7#include <jlm/util/file.hpp>
9
10#include <algorithm>
11#include <fstream>
12
13/* Tarjan's SCC algorithm */
14
15static void
18 std::unordered_map<const jlm::llvm::InterProceduralGraphNode *, std::pair<size_t, size_t>> &
19 map,
20 std::vector<const jlm::llvm::InterProceduralGraphNode *> & node_stack,
21 size_t & index,
22 std::vector<std::unordered_set<const jlm::llvm::InterProceduralGraphNode *>> & sccs)
23{
24 map.emplace(node, std::make_pair(index, index));
25 node_stack.push_back(node);
26 index++;
27
28 for (auto callee : *node)
29 {
30 if (map.find(callee) == map.end())
31 {
32 /* successor has not been visited yet; recurse on it */
33 strongconnect(callee, map, node_stack, index, sccs);
34 map[node].second = std::min(map[node].second, map[callee].second);
35 }
36 else if (std::find(node_stack.begin(), node_stack.end(), callee) != node_stack.end())
37 {
38 /* successor is in stack and hence in the current SCC */
39 map[node].second = std::min(map[node].second, map[callee].first);
40 }
41 }
42
43 if (map[node].second == map[node].first)
44 {
45 std::unordered_set<const jlm::llvm::InterProceduralGraphNode *> scc;
46 const jlm::llvm::InterProceduralGraphNode * w = nullptr;
47 do
48 {
49 w = node_stack.back();
50 node_stack.pop_back();
51 scc.insert(w);
52 } while (w != node);
53
54 sccs.push_back(scc);
55 }
56}
57
58namespace jlm::llvm
59{
60
61void
62InterProceduralGraph::add_node(std::unique_ptr<InterProceduralGraphNode> node)
63{
64 nodes_.push_back(std::move(node));
65}
66
67std::vector<std::unordered_set<const InterProceduralGraphNode *>>
69{
70 std::vector<std::unordered_set<const InterProceduralGraphNode *>> sccs;
71
72 std::unordered_map<const InterProceduralGraphNode *, std::pair<size_t, size_t>> map;
73 std::vector<const InterProceduralGraphNode *> node_stack;
74 size_t index = 0;
75
76 for (auto & node : *this)
77 {
78 if (map.find(&node) == map.end())
79 strongconnect(&node, map, node_stack, index, sccs);
80 }
81
82 return sccs;
83}
84
86InterProceduralGraph::find(const std::string & name) const noexcept
87{
88 for (auto & node : nodes_)
89 {
90 if (node->name() == name)
91 return node.get();
92 }
93
94 return nullptr;
95}
96
98
99util::graph::Graph &
101 util::graph::Writer & writer,
102 const InterProceduralGraph & interProceduralGraph)
103{
104 util::graph::Graph & dotGraph = writer.CreateGraph();
105 dotGraph.SetProgramObject(interProceduralGraph);
106
107 // Create nodes
108 for (auto & node : interProceduralGraph)
109 {
110 auto & dotNode = dotGraph.CreateInOutNode(0, 0);
111 dotNode.SetProgramObject(node);
112 dotNode.SetLabel(node.name());
113 }
114
115 // Create edges
116 for (auto & node : interProceduralGraph)
117 {
118 auto & dotNode = dotGraph.GetFromProgramObject<util::graph::InOutNode>(node);
119 for (auto & depNode : node)
120 {
121 auto & dotDepNode = dotGraph.GetFromProgramObject<util::graph::InOutNode>(*depNode);
122 auto & outputPort = dotDepNode.CreateOutputPort();
123 auto & inputPort = dotNode.CreateInputPort();
124 dotGraph.CreateEdge(inputPort, outputPort, false);
125 }
126 }
127
128 return dotGraph;
129}
130
131void
133{
134 util::graph::Writer graphWriter;
135 toDot(graphWriter, *this);
136
137 const util::FilePath outputFilePath =
139
140 std::ofstream outputFile(outputFilePath.to_str());
141 graphWriter.outputAllGraphs(outputFile, util::graph::OutputFormat::Dot);
142
144}
145
146FunctionNode::~FunctionNode() noexcept = default;
147
148const std::string &
149FunctionNode::name() const noexcept
150{
151 return name_;
152}
153
154const jlm::rvsdg::Type &
155FunctionNode::type() const noexcept
156{
157 return *FunctionType_;
158}
159
160std::shared_ptr<const jlm::rvsdg::Type>
162{
163 return FunctionType_;
164}
165
166const llvm::Linkage &
167FunctionNode::linkage() const noexcept
168{
169 return linkage_;
170}
171
172bool
173FunctionNode::hasBody() const noexcept
174{
175 return cfg() != nullptr;
176}
177
178void
179FunctionNode::add_cfg(std::unique_ptr<ControlFlowGraph> cfg)
180{
181 if (cfg->fcttype() != fcttype())
182 throw util::Error("CFG does not match the function node's type.");
183
184 cfg_ = std::move(cfg);
185}
186
187FunctionVariable::~FunctionVariable() noexcept = default;
188
189DataNode::~DataNode() noexcept = default;
190
191const std::string &
192DataNode::name() const noexcept
193{
194 return name_;
195}
196
197const PointerType &
198DataNode::type() const noexcept
199{
200 static PointerType pointerType;
201 return pointerType;
202}
203
204std::shared_ptr<const rvsdg::Type>
206{
207 return PointerType::Create();
208}
209
210const llvm::Linkage &
211DataNode::linkage() const noexcept
212{
213 return linkage_;
214}
215
216bool
217DataNode::hasBody() const noexcept
218{
219 return initialization() != nullptr;
220}
221
222}
rvsdg::FunctionType fcttype() const
Definition cfg.hpp:253
const DataNodeInit * initialization() const noexcept
Definition ipgraph.hpp:413
llvm::Linkage linkage_
Definition ipgraph.hpp:457
std::shared_ptr< const jlm::rvsdg::Type > Type() const override
Definition ipgraph.cpp:205
const llvm::Linkage & linkage() const noexcept override
Definition ipgraph.cpp:211
const PointerType & type() const noexcept override
Definition ipgraph.cpp:198
bool hasBody() const noexcept override
Definition ipgraph.cpp:217
const jlm::rvsdg::Type & type() const noexcept override
Definition ipgraph.cpp:155
std::shared_ptr< const rvsdg::FunctionType > FunctionType_
Definition ipgraph.hpp:271
void add_cfg(std::unique_ptr< ControlFlowGraph > cfg)
Adds cfg to the function node. If the function node already has a CFG, then it is replaced with cfg.
Definition ipgraph.cpp:179
std::unique_ptr< ControlFlowGraph > cfg_
Definition ipgraph.hpp:276
llvm::Linkage linkage_
Definition ipgraph.hpp:273
bool hasBody() const noexcept override
Definition ipgraph.cpp:173
llvm::ControlFlowGraph * cfg() const noexcept
Definition ipgraph.hpp:190
const llvm::Linkage & linkage() const noexcept override
Definition ipgraph.cpp:167
~FunctionNode() noexcept override
std::shared_ptr< const jlm::rvsdg::Type > Type() const override
Definition ipgraph.cpp:161
const rvsdg::FunctionType & fcttype() const noexcept
Definition ipgraph.hpp:202
~FunctionVariable() noexcept override
virtual ~InterProceduralGraphNode() noexcept
std::vector< std::unordered_set< const InterProceduralGraphNode * > > find_sccs() const
Definition ipgraph.cpp:68
const InterProceduralGraphNode * find(const std::string &name) const noexcept
Definition ipgraph.cpp:86
std::vector< std::unique_ptr< InterProceduralGraphNode > > nodes_
Definition ipgraph.hpp:90
void add_node(std::unique_ptr< InterProceduralGraphNode > node)
Definition ipgraph.cpp:62
static util::graph::Graph & toDot(util::graph::Writer &writer, const InterProceduralGraph &interProceduralGraph)
Definition ipgraph.cpp:100
PointerType class.
Definition types.hpp:25
static std::shared_ptr< const PointerType > Create()
Definition types.cpp:45
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.
Definition file.hpp:301
static FilePath TempDirectoryPath()
Definition file.hpp:317
const std::string & to_str() const noexcept
Definition file.hpp:275
void SetProgramObject(const T &object)
InOutNode & CreateInOutNode(size_t inputPorts, size_t outputPorts)
Edge & CreateEdge(Port &from, Port &to, bool directed)
Element & GetFromProgramObject(const ProgramObject &object) const
void outputAllGraphs(std::ostream &out, OutputFormat format)
static void strongconnect(const jlm::llvm::InterProceduralGraphNode *node, std::unordered_map< const jlm::llvm::InterProceduralGraphNode *, std::pair< size_t, size_t > > &map, std::vector< const jlm::llvm::InterProceduralGraphNode * > &node_stack, size_t &index, std::vector< std::unordered_set< const jlm::llvm::InterProceduralGraphNode * > > &sccs)
Definition ipgraph.cpp:16
Global memory state passed between functions.
static void strongconnect(ControlFlowGraphNode *node, ControlFlowGraphNode *exit, std::unordered_map< ControlFlowGraphNode *, std::pair< size_t, size_t > > &map, std::vector< ControlFlowGraphNode * > &node_stack, size_t &index, std::vector< StronglyConnectedComponent > &sccs)
std::string getDotViewer()
Definition Program.cpp:42
int executeProgramAndWait(const std::string &programName, const std::vector< std::string > &programArguments)
Definition Program.cpp:18