Jlm
ipgraph.hpp
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 
6 #ifndef JLM_LLVM_IR_IPGRAPH_HPP
7 #define JLM_LLVM_IR_IPGRAPH_HPP
8 
9 #include <jlm/llvm/ir/cfg.hpp>
10 #include <jlm/llvm/ir/tac.hpp>
11 #include <jlm/llvm/ir/types.hpp>
12 #include <jlm/llvm/ir/variable.hpp>
13 
14 #include <unordered_map>
15 #include <unordered_set>
16 
17 namespace jlm::llvm
18 {
19 
20 class InterProceduralGraphNode;
21 
23 {
26  std::vector<std::unique_ptr<InterProceduralGraphNode>>::const_iterator>;
27 
28 public:
29  ~InterProceduralGraph() noexcept = default;
30 
31  InterProceduralGraph() noexcept = default;
32 
34 
36 
38  operator=(const InterProceduralGraph &) = delete;
39 
41  operator=(InterProceduralGraph &&) = delete;
42 
43  inline const_iterator
44  begin() const noexcept
45  {
46  return const_iterator(nodes_.begin());
47  }
48 
49  inline const_iterator
50  end() const noexcept
51  {
52  return const_iterator(nodes_.end());
53  }
54 
55  void
56  add_node(std::unique_ptr<InterProceduralGraphNode> node);
57 
58  inline size_t
59  nnodes() const noexcept
60  {
61  return nodes_.size();
62  }
63 
64  [[nodiscard]] std::vector<std::unordered_set<const InterProceduralGraphNode *>>
65  find_sccs() const;
66 
67  [[nodiscard]] const InterProceduralGraphNode *
68  find(const std::string & name) const noexcept;
69 
70 private:
71  std::vector<std::unique_ptr<InterProceduralGraphNode>> nodes_;
72 };
73 
74 class output;
75 
77 {
78  typedef std::unordered_set<const InterProceduralGraphNode *>::const_iterator const_iterator;
79 
80 public:
81  virtual ~InterProceduralGraphNode() noexcept;
82 
83 protected:
85  : clg_(clg)
86  {}
87 
88 public:
90  clg() const noexcept
91  {
92  return clg_;
93  }
94 
95  void
97  {
98  dependencies_.insert(dep);
99  }
100 
101  inline const_iterator
102  begin() const
103  {
104  return dependencies_.begin();
105  }
106 
107  inline const_iterator
108  end() const
109  {
110  return dependencies_.end();
111  }
112 
113  bool
114  is_selfrecursive() const noexcept
115  {
116  if (dependencies_.find(this) != dependencies_.end())
117  return true;
118 
119  return false;
120  }
121 
122  virtual const std::string &
123  name() const noexcept = 0;
124 
125  virtual const jlm::rvsdg::Type &
126  type() const noexcept = 0;
127 
128  virtual std::shared_ptr<const jlm::rvsdg::Type>
129  Type() const = 0;
130 
131  virtual const llvm::Linkage &
132  linkage() const noexcept = 0;
133 
134  virtual bool
135  hasBody() const noexcept = 0;
136 
137 private:
139  std::unordered_set<const InterProceduralGraphNode *> dependencies_;
140 };
141 
143 {
144 public:
145  ~FunctionNode() noexcept override;
146 
147 private:
150  const std::string & name,
151  std::shared_ptr<const rvsdg::FunctionType> type,
152  const llvm::Linkage & linkage,
153  const AttributeSet & attributes)
155  FunctionType_(type),
156  name_(name),
157  linkage_(linkage),
158  attributes_(attributes)
159  {}
160 
161 public:
162  inline llvm::ControlFlowGraph *
163  cfg() const noexcept
164  {
165  return cfg_.get();
166  }
167 
168  [[nodiscard]] const jlm::rvsdg::Type &
169  type() const noexcept override;
170 
171  std::shared_ptr<const jlm::rvsdg::Type>
172  Type() const override;
173 
174  const rvsdg::FunctionType &
175  fcttype() const noexcept
176  {
177  return *FunctionType_;
178  }
179 
180  const std::shared_ptr<const rvsdg::FunctionType> &
181  GetFunctionType() const noexcept
182  {
183  return FunctionType_;
184  }
185 
186  [[nodiscard]] const llvm::Linkage &
187  linkage() const noexcept override;
188 
189  [[nodiscard]] const std::string &
190  name() const noexcept override;
191 
192  [[nodiscard]] bool
193  hasBody() const noexcept override;
194 
195  const AttributeSet &
196  attributes() const noexcept
197  {
198  return attributes_;
199  }
200 
205  void
206  add_cfg(std::unique_ptr<ControlFlowGraph> cfg);
207 
208  static FunctionNode *
210  InterProceduralGraph & ipg,
211  const std::string & name,
212  std::shared_ptr<const rvsdg::FunctionType> type,
213  const llvm::Linkage & linkage,
214  const AttributeSet & attributes)
215  {
216  std::unique_ptr<FunctionNode> node(
217  new FunctionNode(ipg, name, std::move(type), linkage, attributes));
218  auto tmp = node.get();
219  ipg.add_node(std::move(node));
220  return tmp;
221  }
222 
223  static FunctionNode *
225  InterProceduralGraph & ipg,
226  const std::string & name,
227  std::shared_ptr<const rvsdg::FunctionType> type,
228  const llvm::Linkage & linkage)
229  {
230  return create(ipg, name, std::move(type), linkage, {});
231  }
232 
233 private:
234  std::shared_ptr<const rvsdg::FunctionType> FunctionType_;
235  std::string name_;
238  std::unique_ptr<ControlFlowGraph> cfg_;
239 };
240 
241 class FunctionVariable final : public GlobalVariable
242 {
243 public:
244  ~FunctionVariable() noexcept override;
245 
247  : GlobalVariable(node->Type(), node->name()),
248  node_(node)
249  {}
250 
251  FunctionNode *
252  function() const noexcept
253  {
254  return node_;
255  }
256 
257 private:
259 };
260 
261 class DataNodeInit final
262 {
263 public:
264  explicit DataNodeInit(const Variable * value)
265  : value_(value)
266  {}
267 
268  explicit DataNodeInit(tacsvector_t tacs)
269  : tacs_(std::move(tacs))
270  {
271  if (tacs_.empty())
272  throw util::Error("Initialization cannot be empty.");
273 
274  auto & tac = tacs_.back();
275  if (tac->nresults() != 1)
276  throw util::Error("Last TAC of initialization needs exactly one result.");
277 
278  value_ = tac->result(0);
279  }
280 
281  DataNodeInit(const DataNodeInit &) = delete;
282 
283  DataNodeInit(DataNodeInit && other) noexcept
284  : tacs_(std::move(other.tacs_)),
285  value_(other.value_)
286  {}
287 
288  DataNodeInit &
289  operator=(const DataNodeInit &) = delete;
290 
291  DataNodeInit &
292  operator=(DataNodeInit &&) = delete;
293 
294  const Variable *
295  value() const noexcept
296  {
297  return value_;
298  }
299 
300  const tacsvector_t &
301  tacs() const noexcept
302  {
303  return tacs_;
304  }
305 
306 private:
307  tacsvector_t tacs_{};
308  const Variable * value_;
309 };
310 
311 class DataNode final : public InterProceduralGraphNode
312 {
313 public:
314  ~DataNode() noexcept override;
315 
316 private:
319  const std::string & name,
320  std::shared_ptr<const jlm::rvsdg::Type> valueType,
321  const llvm::Linkage & linkage,
322  std::string section,
323  bool constant)
325  constant_(constant),
326  name_(name),
327  Section_(std::move(section)),
328  linkage_(linkage),
329  ValueType_(std::move(valueType))
330  {}
331 
332 public:
333  [[nodiscard]] const PointerType &
334  type() const noexcept override;
335 
336  std::shared_ptr<const jlm::rvsdg::Type>
337  Type() const override;
338 
339  [[nodiscard]] const std::shared_ptr<const jlm::rvsdg::Type> &
340  GetValueType() const noexcept
341  {
342  return ValueType_;
343  }
344 
345  [[nodiscard]] const std::string &
346  name() const noexcept override;
347 
348  [[nodiscard]] const llvm::Linkage &
349  linkage() const noexcept override;
350 
351  [[nodiscard]] bool
352  hasBody() const noexcept override;
353 
354  inline bool
355  constant() const noexcept
356  {
357  return constant_;
358  }
359 
360  const std::string &
361  Section() const noexcept
362  {
363  return Section_;
364  }
365 
366  const DataNodeInit *
367  initialization() const noexcept
368  {
369  return init_.get();
370  }
371 
372  void
373  set_initialization(std::unique_ptr<DataNodeInit> init)
374  {
375  if (!init)
376  return;
377 
378  if (init->value()->type() != *GetValueType())
379  throw util::Error("Invalid type.");
380 
381  init_ = std::move(init);
382  }
383 
384  static DataNode *
387  const std::string & name,
388  std::shared_ptr<const jlm::rvsdg::Type> valueType,
389  const llvm::Linkage & linkage,
390  std::string section,
391  bool constant)
392  {
393  std::unique_ptr<DataNode> node(
394  new DataNode(clg, name, std::move(valueType), linkage, std::move(section), constant));
395  auto ptr = node.get();
396  clg.add_node(std::move(node));
397  return ptr;
398  }
399 
400 private:
401  bool constant_;
402  std::string name_;
403  std::string Section_;
405  std::shared_ptr<const jlm::rvsdg::Type> ValueType_;
406  std::unique_ptr<DataNodeInit> init_;
407 };
408 
409 }
410 
411 #endif
const Variable * value() const noexcept
Definition: ipgraph.hpp:295
DataNodeInit(tacsvector_t tacs)
Definition: ipgraph.hpp:268
DataNodeInit(DataNodeInit &&other) noexcept
Definition: ipgraph.hpp:283
const Variable * value_
Definition: ipgraph.hpp:308
const tacsvector_t & tacs() const noexcept
Definition: ipgraph.hpp:301
DataNodeInit & operator=(DataNodeInit &&)=delete
DataNodeInit & operator=(const DataNodeInit &)=delete
DataNodeInit(const Variable *value)
Definition: ipgraph.hpp:264
DataNodeInit(const DataNodeInit &)=delete
const std::string & Section() const noexcept
Definition: ipgraph.hpp:361
std::string name_
Definition: ipgraph.hpp:402
llvm::Linkage linkage_
Definition: ipgraph.hpp:404
void set_initialization(std::unique_ptr< DataNodeInit > init)
Definition: ipgraph.hpp:373
std::shared_ptr< const jlm::rvsdg::Type > ValueType_
Definition: ipgraph.hpp:405
static DataNode * Create(InterProceduralGraph &clg, const std::string &name, std::shared_ptr< const jlm::rvsdg::Type > valueType, const llvm::Linkage &linkage, std::string section, bool constant)
Definition: ipgraph.hpp:385
const DataNodeInit * initialization() const noexcept
Definition: ipgraph.hpp:367
std::unique_ptr< DataNodeInit > init_
Definition: ipgraph.hpp:406
~DataNode() noexcept override
std::string Section_
Definition: ipgraph.hpp:403
std::shared_ptr< const rvsdg::FunctionType > FunctionType_
Definition: ipgraph.hpp:234
const std::shared_ptr< const rvsdg::FunctionType > & GetFunctionType() const noexcept
Definition: ipgraph.hpp:181
static FunctionNode * create(InterProceduralGraph &ipg, const std::string &name, std::shared_ptr< const rvsdg::FunctionType > type, const llvm::Linkage &linkage)
Definition: ipgraph.hpp:224
AttributeSet attributes_
Definition: ipgraph.hpp:237
std::unique_ptr< ControlFlowGraph > cfg_
Definition: ipgraph.hpp:238
llvm::Linkage linkage_
Definition: ipgraph.hpp:236
~FunctionNode() noexcept override
llvm::ControlFlowGraph * cfg() const noexcept
Definition: ipgraph.hpp:163
static FunctionNode * create(InterProceduralGraph &ipg, const std::string &name, std::shared_ptr< const rvsdg::FunctionType > type, const llvm::Linkage &linkage, const AttributeSet &attributes)
Definition: ipgraph.hpp:209
~FunctionVariable() noexcept override
virtual std::shared_ptr< const jlm::rvsdg::Type > Type() const =0
InterProceduralGraph & clg_
Definition: ipgraph.hpp:138
virtual ~InterProceduralGraphNode() noexcept
virtual const jlm::rvsdg::Type & type() const noexcept=0
const_iterator end() const
Definition: ipgraph.hpp:108
virtual const llvm::Linkage & linkage() const noexcept=0
virtual const std::string & name() const noexcept=0
const_iterator begin() const
Definition: ipgraph.hpp:102
std::unordered_set< const InterProceduralGraphNode * >::const_iterator const_iterator
Definition: ipgraph.hpp:78
InterProceduralGraph & clg() const noexcept
Definition: ipgraph.hpp:90
virtual bool hasBody() const noexcept=0
void add_dependency(const InterProceduralGraphNode *dep)
Definition: ipgraph.hpp:96
bool is_selfrecursive() const noexcept
Definition: ipgraph.hpp:114
std::unordered_set< const InterProceduralGraphNode * > dependencies_
Definition: ipgraph.hpp:139
std::vector< std::unordered_set< const InterProceduralGraphNode * > > find_sccs() const
Definition: ipgraph.cpp:65
const InterProceduralGraphNode * find(const std::string &name) const noexcept
Definition: ipgraph.cpp:83
std::vector< std::unique_ptr< InterProceduralGraphNode > > nodes_
Definition: ipgraph.hpp:71
void add_node(std::unique_ptr< InterProceduralGraphNode > node)
Definition: ipgraph.cpp:59
const_iterator begin() const noexcept
Definition: ipgraph.hpp:44
~InterProceduralGraph() noexcept=default
util::PtrIterator< const InterProceduralGraphNode, std::vector< std::unique_ptr< InterProceduralGraphNode > >::const_iterator > const_iterator
Definition: ipgraph.hpp:26
size_t nnodes() const noexcept
Definition: ipgraph.hpp:59
const_iterator end() const noexcept
Definition: ipgraph.hpp:50
PointerType class.
Definition: types.hpp:25
Global memory state passed between functions.
std::vector< std::unique_ptr< llvm::ThreeAddressCode > > tacsvector_t
Definition: tac.hpp:202