Jlm
Loading...
Searching...
No Matches
DotWriter.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2025 Nico Reißmann <nico.reissmann@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
9#include <jlm/util/strfmt.hpp>
10
11namespace jlm::rvsdg
12{
13
15
16void
17DotWriter::AnnotateTypeGraphNode(const Type & type, util::graph::Node & node)
18{}
19
20void
26
27void
30
31void
37
44{
45 // If the type already has a corresponding node, return it
46 if (auto * graphElement = typeGraph.GetElementFromProgramObject(type))
47 {
48 auto * node = reinterpret_cast<util::graph::Node *>(graphElement);
49 JLM_ASSERT(node);
50 return *node;
51 }
52
53 auto & node = typeGraph.CreateNode();
54 node.SetProgramObject(type);
55 node.SetLabel(type.debug_string());
56
57 AnnotateTypeGraphNode(type, node);
58
59 return node;
60}
61
68void
70{
71 auto & graph = inputPort.GetGraph();
72 inputPort.SetProgramObject(rvsdgInput);
73 inputPort.SetLabel(util::strfmt(rvsdgInput.index()));
74
75 // nodes are visited in topological order, so if the origin is an output, it will already exist
76 if (auto originPort = reinterpret_cast<util::graph::Port *>(
77 graph.GetElementFromProgramObject(*rvsdgInput.origin())))
78 {
79 auto & edge = graph.CreateDirectedEdge(*originPort, inputPort);
81 }
82}
83
91void
96{
97 outputPort.SetProgramObject(rvsdgOutput);
98 outputPort.SetLabel(util::strfmt(rvsdgOutput.index()));
99
100 if (typeGraph)
101 outputPort.SetAttributeGraphElement(
102 "type",
104}
105
111void
113 util::graph::Graph & graph,
114 const Region & region,
116 const bool traverseRecursively)
117{
118 graph.SetProgramObject(region);
119
120 // Start by creating nodes for all the region arguments, and attaching them to the RVSDG outputs.
121 for (size_t n = 0; n < region.narguments(); n++)
122 {
123 auto & node = graph.CreateArgumentNode();
124 auto & argument = *region.argument(n);
125 AttachNodeOutput(node, argument, typeGraph);
126
127 // Include the index among the region's attributes
128 node.SetAttribute("index", std::to_string(n));
129
130 // Use the debug string as the label
131 node.SetLabel(argument.debug_string());
132
133 // If this argument corresponds to one of the structural node's inputs, reference it
134 if (argument.input())
135 {
136 node.SetAttributeObject("input", *argument.input());
137 // Include the local index of the node's input in the label
138 node.AppendToLabel(util::strfmt("<- ", argument.input()->debug_string()), " ");
139 }
140
141 AnnotateRegionArgument(argument, node, typeGraph);
142 }
143
144 // Create a node for each node in the region in topological order.
145 // Inputs expect the node representing their origin to exist before being visited.
147 for (const auto rvsdgNode : traverser)
148 {
149 auto & node = graph.CreateInOutNode(rvsdgNode->ninputs(), rvsdgNode->noutputs());
150 node.SetLabel(rvsdgNode->DebugString());
151 node.SetProgramObject(*rvsdgNode);
152
153 for (size_t i = 0; i < rvsdgNode->ninputs(); i++)
154 AttachNodeInput(node.GetInputPort(i), *rvsdgNode->input(i));
155
156 for (size_t i = 0; i < rvsdgNode->noutputs(); i++)
157 AttachNodeOutput(node.GetOutputPort(i), *rvsdgNode->output(i), typeGraph);
158
159 // Structural nodes also have subgraphs
160 const auto structuralNode = dynamic_cast<const StructuralNode *>(rvsdgNode);
162 {
163 for (auto & subregion : structuralNode->Subregions())
164 {
165 auto & subGraph = node.CreateSubgraph();
166 subGraph.SetLabel(util::strfmt("RegionID: ", subregion.getRegionId()));
168 }
169 }
170
172 }
173
174 // Create result nodes for the region's results, and attach them to their origins
175 for (size_t n = 0; n < region.nresults(); n++)
176 {
177 auto & node = graph.CreateResultNode();
178 auto & result = *region.result(n);
179 AttachNodeInput(node, result);
180
181 // Include the index among the region's results
182 node.SetAttribute("index", std::to_string(n));
183
184 // Use the debug string as the label
185 node.SetLabel(result.debug_string());
186
187 // If this result corresponds to one of the structural node's outputs, reference it
188 if (result.output())
189 {
190 node.SetAttributeObject("output", *result.output());
191 // Include the local index of the node's output in the label
192 node.AppendToLabel(util::strfmt("-> ", result.output()->debug_string()), " ");
193 }
194 }
195}
196
200 const Region & region,
201 const bool emitTypeGraph)
202{
203 util::graph::Graph * typeGraph = nullptr;
204 if (emitTypeGraph)
205 {
206 typeGraph = &writer.CreateGraph();
207 typeGraph->SetLabel("Type graph");
208 }
209 util::graph::Graph & rootGraph = writer.CreateGraph();
210 rootGraph.SetLabel(util::strfmt("RegionID: ", region.getRegionId()));
211 CreateGraphNodes(rootGraph, region, typeGraph, true);
212
213 return rootGraph;
214}
215
218{
219 util::graph::Graph & graph = writer.CreateGraph();
220 CreateGraphNodes(graph, region, nullptr, false);
221 return graph;
222}
223
224}
void AttachNodeOutput(util::graph::Port &outputPort, const Output &rvsdgOutput, util::graph::Graph *typeGraph)
Definition DotWriter.cpp:92
virtual void AnnotateGraphNode(const Node &rvsdgNode, util::graph::Node &node, util::graph::Graph *typeGraph)
Definition DotWriter.cpp:21
virtual ~DotWriter() noexcept
virtual void AnnotateTypeGraphNode(const Type &type, util::graph::Node &node)
Definition DotWriter.cpp:17
util::graph::Graph & WriteGraphs(util::graph::Writer &writer, const Region &region, bool emitTypeGraph)
util::graph::Graph & WriteGraph(util::graph::Writer &writer, const Region &region)
void AttachNodeInput(util::graph::Port &inputPort, const Input &rvsdgInput)
Definition DotWriter.cpp:69
virtual void AnnotateRegionArgument(const RegionArgument &regionArgument, util::graph::Node &node, util::graph::Graph *typeGraph)
Definition DotWriter.cpp:32
virtual void AnnotateEdge(const Input &rvsdgInput, util::graph::Edge &edge)
Definition DotWriter.cpp:28
void CreateGraphNodes(util::graph::Graph &graph, const Region &region, util::graph::Graph *typeGraph, bool traverseRecursively)
util::graph::Node & GetOrCreateTypeGraphNode(const Type &type, util::graph::Graph &typeGraph)
Definition DotWriter.cpp:43
Represents the argument of a region.
Definition region.hpp:41
Represent acyclic RVSDG subgraphs.
Definition region.hpp:213
RegionArgument * argument(size_t index) const noexcept
Definition region.hpp:466
size_t nresults() const noexcept
Definition region.hpp:494
Id getRegionId() const noexcept
Definition region.hpp:278
RegionResult * result(size_t index) const noexcept
Definition region.hpp:500
size_t narguments() const noexcept
Definition region.hpp:460
virtual std::string debug_string() const =0
void SetProgramObject(const T &object)
void SetLabel(std::string label)
ArgumentNode & CreateArgumentNode()
ResultNode & CreateResultNode()
InOutNode & CreateInOutNode(size_t inputPorts, size_t outputPorts)
#define JLM_ASSERT(x)
Definition common.hpp:16
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872
static std::string strfmt(Args... args)
Definition strfmt.hpp:35