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 
10 #include <jlm/llvm/ir/cfg.hpp>
11 #include <jlm/llvm/ir/tac.hpp>
12 #include <jlm/llvm/ir/types.hpp>
13 #include <jlm/llvm/ir/variable.hpp>
14 
15 #include <unordered_map>
16 #include <unordered_set>
17 
18 namespace jlm::llvm
19 {
20 
21 class InterProceduralGraphNode;
22 
24 {
27  std::vector<std::unique_ptr<InterProceduralGraphNode>>::const_iterator>;
28 
29 public:
30  ~InterProceduralGraph() noexcept = default;
31 
32  InterProceduralGraph() noexcept = default;
33 
35 
37 
39  operator=(const InterProceduralGraph &) = delete;
40 
42  operator=(InterProceduralGraph &&) = delete;
43 
44  inline const_iterator
45  begin() const noexcept
46  {
47  return const_iterator(nodes_.begin());
48  }
49 
50  inline const_iterator
51  end() const noexcept
52  {
53  return const_iterator(nodes_.end());
54  }
55 
56  void
57  add_node(std::unique_ptr<InterProceduralGraphNode> node);
58 
59  inline size_t
60  nnodes() const noexcept
61  {
62  return nodes_.size();
63  }
64 
65  [[nodiscard]] std::vector<std::unordered_set<const InterProceduralGraphNode *>>
66  find_sccs() const;
67 
68  [[nodiscard]] const InterProceduralGraphNode *
69  find(const std::string & name) const noexcept;
70 
78  static util::graph::Graph &
79  toDot(util::graph::Writer & writer, const InterProceduralGraph & interProceduralGraph);
80 
86  void
87  view() const;
88 
89 private:
90  std::vector<std::unique_ptr<InterProceduralGraphNode>> nodes_;
91 };
92 
93 class output;
94 
96 {
97  typedef std::unordered_set<const InterProceduralGraphNode *>::const_iterator const_iterator;
98 
99 public:
100  virtual ~InterProceduralGraphNode() noexcept;
101 
102 protected:
104  : clg_(clg)
105  {}
106 
107 public:
109  clg() const noexcept
110  {
111  return clg_;
112  }
113 
114  void
116  {
117  dependencies_.insert(dep);
118  }
119 
120  inline const_iterator
121  begin() const
122  {
123  return dependencies_.begin();
124  }
125 
126  inline const_iterator
127  end() const
128  {
129  return dependencies_.end();
130  }
131 
132  bool
133  is_selfrecursive() const noexcept
134  {
135  if (dependencies_.find(this) != dependencies_.end())
136  return true;
137 
138  return false;
139  }
140 
141  virtual const std::string &
142  name() const noexcept = 0;
143 
144  virtual const jlm::rvsdg::Type &
145  type() const noexcept = 0;
146 
147  virtual std::shared_ptr<const jlm::rvsdg::Type>
148  Type() const = 0;
149 
150  virtual const llvm::Linkage &
151  linkage() const noexcept = 0;
152 
153  virtual bool
154  hasBody() const noexcept = 0;
155 
156  [[nodiscard]] size_t
157  numDependencies() const noexcept
158  {
159  return dependencies_.size();
160  }
161 
162 private:
164  std::unordered_set<const InterProceduralGraphNode *> dependencies_;
165 };
166 
168 {
169 public:
170  ~FunctionNode() noexcept override;
171 
172 private:
175  const std::string & name,
176  std::shared_ptr<const rvsdg::FunctionType> type,
177  const llvm::Linkage & linkage,
179  const AttributeSet & attributes)
182  name_(name),
183  linkage_(linkage),
186  {}
187 
188 public:
189  inline llvm::ControlFlowGraph *
190  cfg() const noexcept
191  {
192  return cfg_.get();
193  }
194 
195  [[nodiscard]] const jlm::rvsdg::Type &
196  type() const noexcept override;
197 
198  std::shared_ptr<const jlm::rvsdg::Type>
199  Type() const override;
200 
201  const rvsdg::FunctionType &
202  fcttype() const noexcept
203  {
204  return *FunctionType_;
205  }
206 
207  const std::shared_ptr<const rvsdg::FunctionType> &
208  GetFunctionType() const noexcept
209  {
210  return FunctionType_;
211  }
212 
213  [[nodiscard]] const llvm::Linkage &
214  linkage() const noexcept override;
215 
216  [[nodiscard]] const std::string &
217  name() const noexcept override;
218 
219  [[nodiscard]] bool
220  hasBody() const noexcept override;
221 
222  [[nodiscard]] const CallingConvention &
223  callingConvention() const noexcept
224  {
225  return callingConvention_;
226  }
227 
228  const AttributeSet &
229  attributes() const noexcept
230  {
231  return attributes_;
232  }
233 
238  void
239  add_cfg(std::unique_ptr<ControlFlowGraph> cfg);
240 
241  static FunctionNode *
243  InterProceduralGraph & ipg,
244  const std::string & name,
245  std::shared_ptr<const rvsdg::FunctionType> type,
246  const llvm::Linkage & linkage,
248  const AttributeSet & attributes)
249  {
250  std::unique_ptr<FunctionNode> node(
251  new FunctionNode(ipg, name, std::move(type), linkage, callingConvention, attributes));
252  auto tmp = node.get();
253  ipg.add_node(std::move(node));
254  return tmp;
255  }
256 
260  static FunctionNode *
262  InterProceduralGraph & ipg,
263  const std::string & name,
264  std::shared_ptr<const rvsdg::FunctionType> type,
265  const llvm::Linkage & linkage)
266  {
267  return create(ipg, name, std::move(type), linkage, llvm::CallingConvention::Default, {});
268  }
269 
270 private:
271  std::shared_ptr<const rvsdg::FunctionType> FunctionType_;
272  std::string name_;
276  std::unique_ptr<ControlFlowGraph> cfg_;
277 };
278 
279 class FunctionVariable final : public GlobalVariable
280 {
281 public:
282  ~FunctionVariable() noexcept override;
283 
285  : GlobalVariable(node->Type(), node->name()),
286  node_(node)
287  {}
288 
289  FunctionNode *
290  function() const noexcept
291  {
292  return node_;
293  }
294 
295 private:
297 };
298 
299 class DataNodeInit final
300 {
301 public:
302  explicit DataNodeInit(const Variable * value)
303  : value_(value)
304  {}
305 
307  : tacs_(std::move(tacs))
308  {
309  if (tacs_.empty())
310  throw util::Error("Initialization cannot be empty.");
311 
312  auto & tac = tacs_.back();
313  if (tac->nresults() != 1)
314  throw util::Error("Last TAC of initialization needs exactly one result.");
315 
316  value_ = tac->result(0);
317  }
318 
319  DataNodeInit(const DataNodeInit &) = delete;
320 
321  DataNodeInit(DataNodeInit && other) noexcept
322  : tacs_(std::move(other.tacs_)),
323  value_(other.value_)
324  {}
325 
326  DataNodeInit &
327  operator=(const DataNodeInit &) = delete;
328 
329  DataNodeInit &
330  operator=(DataNodeInit &&) = delete;
331 
332  const Variable *
333  value() const noexcept
334  {
335  return value_;
336  }
337 
338  const tacsvector_t &
339  tacs() const noexcept
340  {
341  return tacs_;
342  }
343 
344 private:
346  const Variable * value_;
347 };
348 
349 class DataNode final : public InterProceduralGraphNode
350 {
351 public:
352  ~DataNode() noexcept override;
353 
354 private:
357  const std::string & name,
358  std::shared_ptr<const jlm::rvsdg::Type> valueType,
359  const llvm::Linkage & linkage,
360  std::string section,
361  const bool constant,
362  const size_t alignment)
365  name_(name),
366  Section_(std::move(section)),
367  linkage_(linkage),
368  ValueType_(std::move(valueType)),
369  alignment_(alignment)
370  {}
371 
372 public:
373  [[nodiscard]] const PointerType &
374  type() const noexcept override;
375 
376  std::shared_ptr<const jlm::rvsdg::Type>
377  Type() const override;
378 
379  [[nodiscard]] const std::shared_ptr<const jlm::rvsdg::Type> &
380  GetValueType() const noexcept
381  {
382  return ValueType_;
383  }
384 
385  [[nodiscard]] const std::string &
386  name() const noexcept override;
387 
388  [[nodiscard]] const llvm::Linkage &
389  linkage() const noexcept override;
390 
391  [[nodiscard]] bool
392  hasBody() const noexcept override;
393 
394  [[nodiscard]] size_t
395  getAlignment() const noexcept
396  {
397  return alignment_;
398  }
399 
400  inline bool
401  constant() const noexcept
402  {
403  return constant_;
404  }
405 
406  const std::string &
407  Section() const noexcept
408  {
409  return Section_;
410  }
411 
412  const DataNodeInit *
413  initialization() const noexcept
414  {
415  return init_.get();
416  }
417 
418  void
419  set_initialization(std::unique_ptr<DataNodeInit> init)
420  {
421  if (!init)
422  return;
423 
424  if (init->value()->type() != *GetValueType())
425  throw util::Error("Invalid type.");
426 
427  init_ = std::move(init);
428  }
429 
430  static DataNode *
433  const std::string & name,
434  std::shared_ptr<const jlm::rvsdg::Type> valueType,
435  const llvm::Linkage & linkage,
436  std::string section,
437  const bool constant,
438  const size_t alignment)
439  {
440  std::unique_ptr<DataNode> node(new DataNode(
441  clg,
442  name,
443  std::move(valueType),
444  linkage,
445  std::move(section),
446  constant,
447  alignment));
448  const auto ptr = node.get();
449  clg.add_node(std::move(node));
450  return ptr;
451  }
452 
453 private:
454  bool constant_;
455  std::string name_;
456  std::string Section_;
458  std::shared_ptr<const jlm::rvsdg::Type> ValueType_;
459  std::unique_ptr<DataNodeInit> init_;
460  size_t alignment_;
461 };
462 
463 }
464 
465 #endif
const Variable * value() const noexcept
Definition: ipgraph.hpp:333
DataNodeInit(tacsvector_t tacs)
Definition: ipgraph.hpp:306
DataNodeInit(DataNodeInit &&other) noexcept
Definition: ipgraph.hpp:321
const Variable * value_
Definition: ipgraph.hpp:346
const tacsvector_t & tacs() const noexcept
Definition: ipgraph.hpp:339
DataNodeInit & operator=(DataNodeInit &&)=delete
tacsvector_t tacs_
Definition: ipgraph.hpp:345
DataNodeInit & operator=(const DataNodeInit &)=delete
DataNodeInit(const Variable *value)
Definition: ipgraph.hpp:302
DataNodeInit(const DataNodeInit &)=delete
const std::shared_ptr< const jlm::rvsdg::Type > & GetValueType() const noexcept
Definition: ipgraph.hpp:380
const std::string & name() const noexcept override
Definition: ipgraph.cpp:192
const std::string & Section() const noexcept
Definition: ipgraph.hpp:407
std::string name_
Definition: ipgraph.hpp:455
static DataNode * Create(InterProceduralGraph &clg, const std::string &name, std::shared_ptr< const jlm::rvsdg::Type > valueType, const llvm::Linkage &linkage, std::string section, const bool constant, const size_t alignment)
Definition: ipgraph.hpp:431
llvm::Linkage linkage_
Definition: ipgraph.hpp:457
void set_initialization(std::unique_ptr< DataNodeInit > init)
Definition: ipgraph.hpp:419
std::shared_ptr< const jlm::rvsdg::Type > ValueType_
Definition: ipgraph.hpp:458
std::shared_ptr< const jlm::rvsdg::Type > Type() const override
Definition: ipgraph.cpp:205
size_t getAlignment() const noexcept
Definition: ipgraph.hpp:395
const llvm::Linkage & linkage() const noexcept override
Definition: ipgraph.cpp:211
DataNode(InterProceduralGraph &clg, const std::string &name, std::shared_ptr< const jlm::rvsdg::Type > valueType, const llvm::Linkage &linkage, std::string section, const bool constant, const size_t alignment)
Definition: ipgraph.hpp:355
const DataNodeInit * initialization() const noexcept
Definition: ipgraph.hpp:413
std::unique_ptr< DataNodeInit > init_
Definition: ipgraph.hpp:459
~DataNode() noexcept override
const PointerType & type() const noexcept override
Definition: ipgraph.cpp:198
bool constant() const noexcept
Definition: ipgraph.hpp:401
bool hasBody() const noexcept override
Definition: ipgraph.cpp:217
std::string Section_
Definition: ipgraph.hpp:456
const AttributeSet & attributes() const noexcept
Definition: ipgraph.hpp:229
const jlm::rvsdg::Type & type() const noexcept override
Definition: ipgraph.cpp:155
static FunctionNode * create(InterProceduralGraph &ipg, const std::string &name, std::shared_ptr< const rvsdg::FunctionType > type, const llvm::Linkage &linkage, const CallingConvention &callingConvention, const AttributeSet &attributes)
Definition: ipgraph.hpp:242
const rvsdg::FunctionType & fcttype() const noexcept
Definition: ipgraph.hpp:202
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
const std::shared_ptr< const rvsdg::FunctionType > & GetFunctionType() const noexcept
Definition: ipgraph.hpp:208
llvm::CallingConvention callingConvention_
Definition: ipgraph.hpp:274
static FunctionNode * create(InterProceduralGraph &ipg, const std::string &name, std::shared_ptr< const rvsdg::FunctionType > type, const llvm::Linkage &linkage)
Definition: ipgraph.hpp:261
AttributeSet attributes_
Definition: ipgraph.hpp:275
FunctionNode(InterProceduralGraph &clg, const std::string &name, std::shared_ptr< const rvsdg::FunctionType > type, const llvm::Linkage &linkage, const llvm::CallingConvention &callingConvention, const AttributeSet &attributes)
Definition: ipgraph.hpp:173
const std::string & name() const noexcept override
Definition: ipgraph.cpp:149
std::unique_ptr< ControlFlowGraph > cfg_
Definition: ipgraph.hpp:276
llvm::Linkage linkage_
Definition: ipgraph.hpp:273
const CallingConvention & callingConvention() const noexcept
Definition: ipgraph.hpp:223
bool hasBody() const noexcept override
Definition: ipgraph.cpp:173
const llvm::Linkage & linkage() const noexcept override
Definition: ipgraph.cpp:167
~FunctionNode() noexcept override
llvm::ControlFlowGraph * cfg() const noexcept
Definition: ipgraph.hpp:190
std::shared_ptr< const jlm::rvsdg::Type > Type() const override
Definition: ipgraph.cpp:161
~FunctionVariable() noexcept override
virtual std::shared_ptr< const jlm::rvsdg::Type > Type() const =0
InterProceduralGraph & clg_
Definition: ipgraph.hpp:163
virtual ~InterProceduralGraphNode() noexcept
virtual const jlm::rvsdg::Type & type() const noexcept=0
size_t numDependencies() const noexcept
Definition: ipgraph.hpp:157
const_iterator end() const
Definition: ipgraph.hpp:127
virtual const llvm::Linkage & linkage() const noexcept=0
virtual const std::string & name() const noexcept=0
const_iterator begin() const
Definition: ipgraph.hpp:121
std::unordered_set< const InterProceduralGraphNode * >::const_iterator const_iterator
Definition: ipgraph.hpp:97
InterProceduralGraph & clg() const noexcept
Definition: ipgraph.hpp:109
virtual bool hasBody() const noexcept=0
void add_dependency(const InterProceduralGraphNode *dep)
Definition: ipgraph.hpp:115
bool is_selfrecursive() const noexcept
Definition: ipgraph.hpp:133
std::unordered_set< const InterProceduralGraphNode * > dependencies_
Definition: ipgraph.hpp:164
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
const_iterator begin() const noexcept
Definition: ipgraph.hpp:45
~InterProceduralGraph() noexcept=default
util::PtrIterator< const InterProceduralGraphNode, std::vector< std::unique_ptr< InterProceduralGraphNode > >::const_iterator > const_iterator
Definition: ipgraph.hpp:27
size_t nnodes() const noexcept
Definition: ipgraph.hpp:60
static util::graph::Graph & toDot(util::graph::Writer &writer, const InterProceduralGraph &interProceduralGraph)
Definition: ipgraph.cpp:100
const_iterator end() const noexcept
Definition: ipgraph.hpp:51
PointerType class.
Definition: types.hpp:25
const std::string & name() const noexcept
Definition: variable.hpp:50
const std::shared_ptr< const jlm::rvsdg::Type > Type() const noexcept
Definition: variable.hpp:62
Global memory state passed between functions.
std::vector< std::unique_ptr< llvm::ThreeAddressCode > > tacsvector_t
Definition: tac.hpp:202