Jlm
print.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Nico Reißmann <nico.reissmann@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
8 #include <jlm/llvm/ir/cfg.hpp>
11 #include <jlm/llvm/ir/print.hpp>
12 #include <jlm/llvm/ir/tac.hpp>
13 
14 #include <typeindex>
15 
16 #include <deque>
17 
18 namespace jlm::llvm
19 {
20 
21 /* string converters */
22 
23 static std::string
24 emit_tacs(const tacsvector_t & tacs)
25 {
26  std::string str;
27  for (const auto & tac : tacs)
28  str += ThreeAddressCode::ToAscii(*tac) + ", ";
29 
30  return "[" + str + "]";
31 }
32 
33 static std::string
35 {
36  const auto & node = *util::assertedCast<const FunctionNode>(&clg_node);
37 
38  const auto & fcttype = node.fcttype();
39 
40  /* convert result types */
41  std::string results("<");
42  for (size_t n = 0; n < fcttype.NumResults(); n++)
43  {
44  results += fcttype.ResultType(n).debug_string();
45  if (n != fcttype.NumResults() - 1)
46  results += ", ";
47  }
48  results += ">";
49 
50  /* convert operand types */
51  std::string operands("<");
52  for (size_t n = 0; n < fcttype.NumArguments(); n++)
53  {
54  operands += fcttype.ArgumentType(n).debug_string();
55  if (n != fcttype.NumArguments() - 1)
56  operands += ", ";
57  }
58  operands += ">";
59 
60  std::string cfg = node.cfg() ? ControlFlowGraph::ToAscii(*node.cfg()) : "";
61  std::string exported = isPrivateOrInternal(node.linkage()) ? "static" : "";
62 
63  return exported + results + " " + node.name() + " " + operands + "\n{\n" + cfg + "\n}\n";
64 }
65 
66 static std::string
68 {
69  const auto & node = *util::assertedCast<const DataNode>(&clg_node);
70  auto init = node.initialization();
71 
72  std::string str = node.name();
73  if (init)
74  str += " = " + emit_tacs(init->tacs());
75 
76  return str;
77 }
78 
79 std::string
81 {
82  static std::
83  unordered_map<std::type_index, std::function<std::string(const InterProceduralGraphNode &)>>
84  map({ { typeid(FunctionNode), emit_function_node },
85  { typeid(DataNode), emit_data_node } });
86 
87  std::string str;
88  for (const auto & node : clg)
89  {
90  JLM_ASSERT(map.find(typeid(node)) != map.end());
91  str += map[typeid(node)](node) + "\n";
92  }
93 
94  return str;
95 }
96 
97 /* dot converters */
98 
99 static inline std::string
101 {
102  JLM_ASSERT(is<EntryNode>(&node));
103  const auto en = static_cast<const EntryNode *>(&node);
104 
105  std::string str;
106  for (size_t n = 0; n < en->narguments(); n++)
107  {
108  auto argument = en->argument(n);
109  str += "<" + argument->type().debug_string() + "> " + argument->name() + "\\n";
110  }
111 
112  return str;
113 }
114 
115 static inline std::string
117 {
118  JLM_ASSERT(is<ExitNode>(&node));
119  const auto xn = static_cast<const ExitNode *>(&node);
120 
121  std::string str;
122  for (size_t n = 0; n < xn->nresults(); n++)
123  {
124  auto result = xn->result(n);
125  str += "<" + result->type().debug_string() + "> " + result->name() + "\\n";
126  }
127 
128  return str;
129 }
130 
131 static inline std::string
133 {
134  JLM_ASSERT(is<BasicBlock>(&node));
135  auto & tacs = static_cast<const BasicBlock *>(&node)->tacs();
136 
137  std::string str;
138  for (const auto & tac : tacs)
139  str += ThreeAddressCode::ToAscii(*tac) + "\\n";
140 
141  return str;
142 }
143 
144 static inline std::string
146 {
147  if (is<EntryNode>(&node))
148  return "ENTRY";
149 
150  if (is<ExitNode>(&node))
151  return "EXIT";
152 
153  return util::strfmt(&node);
154 }
155 
156 static inline std::string
158 {
159  static std::unordered_map<std::type_index, std::string (*)(const ControlFlowGraphNode &)> map(
160  { { typeid(EntryNode), emit_entry_dot },
161  { typeid(ExitNode), emit_exit_dot },
162  { typeid(BasicBlock), emit_basic_block } });
163 
164  JLM_ASSERT(map.find(typeid(node)) != map.end());
165  std::string body = map[typeid(node)](node);
166 
167  return emit_header(node) + "\\n" + body;
168 }
169 
170 std::string
172 {
173  auto entry = cfg.entry();
174  auto exit = cfg.exit();
175 
176  std::string dot("digraph cfg {\n");
177 
178  /* emit entry node */
179  dot += util::strfmt(
180  "{ rank = source; ",
181  (intptr_t)entry,
182  "[shape=box, label = \"",
183  emit_node(*entry),
184  "\"]; }\n");
185  dot += util::strfmt(
186  (intptr_t)entry,
187  " -> ",
188  (intptr_t)entry->OutEdge(0)->sink(),
189  "[label=\"0\"];\n");
190 
191  /* emit exit node */
192  dot += util::strfmt(
193  "{ rank = sink; ",
194  (intptr_t)exit,
195  "[shape=box, label = \"",
196  emit_node(*exit),
197  "\"]; }\n");
198 
199  for (const auto & node : cfg)
200  {
201  dot += util::strfmt("{", (intptr_t)&node);
202  dot += util::strfmt("[shape = box, label = \"", emit_node(node), "\"]; }\n");
203  for (auto & edge : node.OutEdges())
204  {
205  dot += util::strfmt((intptr_t)edge.source(), " -> ", (intptr_t)edge.sink());
206  dot += util::strfmt("[label = \"", edge.index(), "\"];\n");
207  }
208  }
209  dot += "}\n";
210 
211  return dot;
212 }
213 
214 std::string
216 {
217  std::string dot("digraph clg {\n");
218  for (const auto & node : clg)
219  {
220  dot += util::strfmt((intptr_t)&node);
221  dot += util::strfmt("[label = \"", node.name(), "\"];\n");
222 
223  for (const auto & call : node)
224  dot += util::strfmt((intptr_t)&node, " -> ", (intptr_t)call, ";\n");
225  }
226  dot += "}\n";
227 
228  return dot;
229 }
230 
231 /* aggregation node */
232 
233 std::string
234 to_str(const AggregationNode & n, const AnnotationMap & dm)
235 {
236  std::function<std::string(const AggregationNode &, size_t)> f =
237  [&](const AggregationNode & n, size_t depth)
238  {
239  std::string subtree(depth, '-');
240  subtree += n.debug_string();
241 
242  if (dm.Contains(n))
243  subtree += " " + dm.Lookup<AnnotationSet>(n).DebugString() + "\n";
244 
245  for (const auto & child : n)
246  subtree += f(child, depth + 1);
247 
248  return subtree;
249  };
250 
251  return f(n, 0);
252 }
253 
254 void
255 print(const AggregationNode & n, const AnnotationMap & dm, FILE * out)
256 {
257  fputs(to_str(n, dm).c_str(), out);
258  fflush(out);
259 }
260 
261 }
virtual std::string debug_string() const =0
T & Lookup(const AggregationNode &aggregationNode) const noexcept
Definition: Annotation.hpp:504
bool Contains(const AggregationNode &aggregationNode) const noexcept
Definition: Annotation.hpp:497
static std::string ToAscii(const ControlFlowGraph &controlFlowGraph)
Definition: cfg.cpp:62
EntryNode * entry() const noexcept
Definition: cfg.hpp:205
ExitNode * exit() const noexcept
Definition: cfg.hpp:211
const llvm::Argument * argument(size_t index) const
Definition: cfg.hpp:92
const Variable * result(size_t index) const
Definition: cfg.hpp:135
static std::string ToAscii(const ThreeAddressCode &threeAddressCode)
Definition: tac.cpp:120
const jlm::rvsdg::Type & type() const noexcept
Definition: variable.hpp:56
virtual std::string debug_string() const =0
#define JLM_ASSERT(x)
Definition: common.hpp:16
Global memory state passed between functions.
static std::string emit_entry_dot(const ControlFlowGraphNode &node)
Definition: print.cpp:100
std::string to_dot(const ControlFlowGraph &cfg)
Definition: print.cpp:171
static std::string emit_data_node(const InterProceduralGraphNode &clg_node)
Definition: print.cpp:67
static std::string emit_tacs(const tacsvector_t &tacs)
Definition: print.cpp:24
std::vector< std::unique_ptr< llvm::ThreeAddressCode > > tacsvector_t
Definition: tac.hpp:202
void print(const AggregationNode &n, const AnnotationMap &dm, FILE *out)
Definition: print.cpp:255
static std::string emit_exit_dot(const ControlFlowGraphNode &node)
Definition: print.cpp:116
bool isPrivateOrInternal(const Linkage linkage)
Definition: Linkage.hpp:65
static std::string emit_header(const ControlFlowGraphNode &node)
Definition: print.cpp:145
static std::string emit_basic_block(const ControlFlowGraphNode &node)
Definition: print.cpp:132
std::string to_str(const InterProceduralGraph &clg)
Definition: print.cpp:80
static std::string emit_node(const ControlFlowGraphNode &node)
Definition: print.cpp:157
static std::string emit_function_node(const InterProceduralGraphNode &clg_node)
Definition: print.cpp:34
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
Definition: node.hpp:1049
static std::string strfmt(Args... args)
Definition: strfmt.hpp:35