Jlm
Loading...
Searching...
No Matches
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>
14
15#include <unordered_map>
16#include <unordered_set>
17
18namespace jlm::llvm
19{
20
21class InterProceduralGraphNode;
22
24{
27 std::vector<std::unique_ptr<InterProceduralGraphNode>>::const_iterator>;
28
29public:
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
89private:
90 std::vector<std::unique_ptr<InterProceduralGraphNode>> nodes_;
91};
92
93class output;
94
96{
97 typedef std::unordered_set<const InterProceduralGraphNode *>::const_iterator const_iterator;
98
99public:
100 virtual ~InterProceduralGraphNode() noexcept;
101
102protected:
106
107public:
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
162private:
164 std::unordered_set<const InterProceduralGraphNode *> dependencies_;
165};
166
168{
169public:
170 ~FunctionNode() noexcept override;
171
172private:
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),
186 {}
187
188public:
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 *
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 *
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
270private:
271 std::shared_ptr<const rvsdg::FunctionType> FunctionType_;
272 std::string name_;
276 std::unique_ptr<ControlFlowGraph> cfg_;
277};
278
280{
281public:
282 ~FunctionVariable() noexcept override;
283
285 : GlobalVariable(node->Type(), node->name()),
286 node_(node)
287 {}
288
290 function() const noexcept
291 {
292 return node_;
293 }
294
295private:
297};
298
299class DataNodeInit final
300{
301public:
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
327 operator=(const DataNodeInit &) = delete;
328
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
344private:
347};
348
350{
351public:
352 ~DataNode() noexcept override;
353
354private:
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)),
368 ValueType_(std::move(valueType)),
369 alignment_(alignment)
370 {}
371
372public:
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
453private:
455 std::string name_;
456 std::string Section_;
458 std::shared_ptr<const jlm::rvsdg::Type> ValueType_;
459 std::unique_ptr<DataNodeInit> init_;
461};
462
463}
464
465#endif
DataNodeInit(tacsvector_t tacs)
Definition ipgraph.hpp:306
DataNodeInit(DataNodeInit &&other) noexcept
Definition ipgraph.hpp:321
const tacsvector_t & tacs() const noexcept
Definition ipgraph.hpp:339
const Variable * value_
Definition ipgraph.hpp:346
const Variable * value() const noexcept
Definition ipgraph.hpp:333
DataNodeInit & operator=(const DataNodeInit &)=delete
DataNodeInit(const Variable *value)
Definition ipgraph.hpp:302
DataNodeInit(const DataNodeInit &)=delete
DataNodeInit & operator=(DataNodeInit &&)=delete
const std::string & name() const noexcept override
Definition ipgraph.cpp:192
const DataNodeInit * initialization() const noexcept
Definition ipgraph.hpp:413
std::string name_
Definition ipgraph.hpp:455
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
const std::shared_ptr< const jlm::rvsdg::Type > & GetValueType() const noexcept
Definition ipgraph.hpp:380
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
const std::string & Section() const noexcept
Definition ipgraph.hpp:407
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
bool hasBody() const noexcept override
Definition ipgraph.cpp:217
std::string Section_
Definition ipgraph.hpp:456
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
llvm::CallingConvention callingConvention_
Definition ipgraph.hpp:274
AttributeSet attributes_
Definition ipgraph.hpp:275
static FunctionNode * create(InterProceduralGraph &ipg, const std::string &name, std::shared_ptr< const rvsdg::FunctionType > type, const llvm::Linkage &linkage)
Definition ipgraph.hpp:261
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 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
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
const AttributeSet & attributes() const noexcept
Definition ipgraph.hpp:229
const CallingConvention & callingConvention() const noexcept
Definition ipgraph.hpp:223
const std::shared_ptr< const rvsdg::FunctionType > & GetFunctionType() const noexcept
Definition ipgraph.hpp:208
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
FunctionNode * function() const noexcept
Definition ipgraph.hpp:290
InterProceduralGraph & clg_
Definition ipgraph.hpp:163
virtual ~InterProceduralGraphNode() noexcept
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
InterProceduralGraph & clg() const noexcept
Definition ipgraph.hpp:109
std::unordered_set< constInterProceduralGraphNode * >::const_iterator const_iterator
Definition ipgraph.hpp:97
const_iterator begin() const
Definition ipgraph.hpp:121
virtual const jlm::rvsdg::Type & type() const noexcept=0
virtual const std::string & name() const noexcept=0
virtual std::shared_ptr< const jlm::rvsdg::Type > Type() const =0
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