10 #include <string_view>
56 auto isAlpha = [](
char c)
58 return (c >=
'a' && c <=
'z') || (c >=
'A' && c <=
'Z');
60 auto isDigit = [](
char c)
62 return (c >=
'0' && c <=
'9');
65 char firstChar =
string[0];
66 if (!isAlpha(firstChar) && firstChar !=
'_')
70 if (!isAlpha(c) && !isDigit(c) && c !=
'_')
99 else if (c < ' ' || c >= 127)
103 snprintf(tmpStr,
sizeof(tmpStr),
"%02X", c);
104 out <<
"\\x" << tmpStr;
121 for (
char c :
string)
131 else if (c ==
'\n' && replaceNewlines)
145 for (
char c :
string)
147 if (c <= ' ' || c >= 127 || c ==
'<' || c ==
'>' || c ==
'"' || c ==
'\'' || c ==
'/'
163 for (
char c :
string)
186 for (
size_t i = 0; i <
indent; i++)
193 UniqueIdSuffix_(std::nullopt),
208 std::ostringstream ss;
222 Label_ = std::move(label);
230 Label_.append(sep).append(text);
320 std::optional<std::string_view>
325 if (
auto stringValue = std::get_if<std::string>(&it->second))
333 std::optional<uintptr_t>
338 if (
auto uintptrValue = std::get_if<uintptr_t>(&it->second))
340 return *uintptrValue;
351 if (
auto graphElementValue = std::get_if<const GraphElement *>(&it->second))
353 return *graphElementValue;
358 if (
auto ptr = std::get_if<uintptr_t>(&it->second))
360 if (
auto gElement =
GetGraph().GetElementFromProgramObject(*ptr))
364 if (
auto gwElement =
GetGraph().GetWriter().GetElementFromProgramObject(*ptr))
401 std::string_view name,
402 std::string_view value,
434 const std::string & name,
459 const auto next = [&]()
494 static std::ostream &
513 for (
auto & element : elements)
520 element->outputJson(out,
indent + 1);
595 const std::vector<Edge *> &
606 else if (
this == &edge.
GetTo())
619 if (&edge->GetFrom() ==
this || !edge->IsDirected())
630 if (&edge->GetTo() ==
this || !edge->IsDirected())
639 std::ostringstream text;
640 size_t numIncomingEdges = 0;
644 if (&edge->GetTo() !=
this && edge->IsDirected())
647 Port & otherEnd = edge->GetOtherEnd(*
this);
648 if (numIncomingEdges == 0)
656 if (numIncomingEdges == 1)
659 out <<
"[" << text.str() <<
"]";
736 out <<
"];" << std::endl;
742 bool firstField =
true;
791 bool firstField =
true;
834 bool firstField =
true;
842 for (
size_t i = 0; i < inputPorts; i++)
845 for (
size_t i = 0; i < outputPorts; i++)
852 throw Error(
"InOutNodes can not have custom shapes set");
936 inputPort->Finalize();
938 outputPort->Finalize();
950 graph->Output(out, format,
indent);
998 out <<
"label=<" << std::endl;
1001 out <<
"<TABLE BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">" << std::endl;
1004 auto PrintPortList = [&out](
auto & ports)
1009 out <<
"\t<TR><TD>" << std::endl;
1010 out <<
"\t\t<TABLE BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\"><TR>" << std::endl;
1011 out <<
"\t\t\t<TD WIDTH=\"20\"></TD>" << std::endl;
1012 for (
size_t i = 0; i < ports.size(); i++)
1016 out <<
"\t\t\t<TD WIDTH=\"10\"></TD>" << std::endl;
1018 auto & port = *ports[i];
1019 out <<
"\t\t\t<TD BORDER=\"1\" CELLPADDING=\"1\" ";
1020 out <<
"PORT=\"" << port.GetFullId() <<
"\" ";
1027 if (port.HasLabel())
1029 out <<
"><FONT POINT-SIZE=\"10\">";
1036 out <<
" WIDTH=\"8\" HEIGHT=\"5\" FIXEDSIZE=\"true\">";
1038 out <<
"</TD>" << std::endl;
1040 out <<
"\t\t\t<TD WIDTH=\"20\"></TD>" << std::endl;
1041 out <<
"\t\t</TR></TABLE>" << std::endl;
1042 out <<
"\t</TD></TR>" << std::endl;
1049 out <<
"\t<TR><TD>" << std::endl;
1050 out <<
"\t\t<TABLE BORDER=\"1\" STYLE=\"ROUNDED\" CELLBORDER=\"0\" ";
1051 out <<
"CELLSPACING=\"0\" CELLPADDING=\"0\" ";
1064 out <<
">" << std::endl;
1065 out <<
"\t\t\t<TR><TD CELLPADDING=\"1\">";
1067 out <<
"</TD></TR>" << std::endl;
1072 out <<
"\t\t\t<TR><TD>" << std::endl;
1073 out <<
"\t\t\t\t<TABLE BORDER=\"0\" CELLSPACING=\"4\" CELLPADDING=\"2\"><TR>" << std::endl;
1076 out <<
"\t\t\t\t\t<TD BORDER=\"1\" STYLE=\"ROUNDED\" WIDTH=\"40\" BGCOLOR=\"white\" ";
1077 out <<
"_SUBGRAPH=\"" << graph->GetFullId() <<
"\">";
1079 out <<
"</TD>" << std::endl;
1081 out <<
"\t\t\t\t</TR></TABLE>" << std::endl;
1082 out <<
"\t\t\t</TD></TR>" << std::endl;
1086 out <<
"\t\t</TABLE>" << std::endl;
1087 out <<
"\t</TD></TR>" << std::endl;
1091 out <<
"</TABLE>" << std::endl;
1094 out <<
"];" << std::endl;
1100 bool firstField =
true;
1132 subgraph->PrintFullId(out);
1160 OutsideSource_(nullptr)
1201 OutsideDestination_(nullptr)
1282 else if (&end == &
To_)
1312 if (hasHeadArrow && hasTailArrow)
1314 else if (hasHeadArrow)
1316 else if (hasTailArrow)
1349 out <<
"];" << std::endl;
1355 bool firstField =
true;
1380 ParentNode_(nullptr)
1386 ParentNode_(&parentNode)
1422 auto node =
new Node(*
this);
1423 Nodes_.emplace_back(node);
1430 auto node =
new InOutNode(*
this, inputPorts, outputPorts);
1431 Nodes_.emplace_back(node);
1498 auto edge =
new Edge(from, to, directed);
1499 Edges_.emplace_back(edge);
1521 if (edge->IsDirected() && &edge->GetFrom() != &a)
1523 if (&edge->GetOtherEnd(a) == &b)
1546 JLM_ASSERT(slot ==
nullptr &&
"Trying to map a GraphElement to an already mapped program object");
1565 for (
auto & node :
Nodes_)
1569 for (
auto & edge :
Edges_)
1580 bool anyArguments =
false;
1587 anyArguments =
true;
1588 arg->OutputASCII(out,
indent);
1594 for (
auto & node :
Nodes_)
1597 node->OutputASCII(out,
indent);
1601 bool anyResults =
false;
1609 res->OutputASCII(out,
indent);
1626 <<
"node[shape=box style=filled fillcolor=white width=0.1 height=0.1 margin=0.05];"
1640 auto PrintOrderedSubgraph = [&out](
auto & nodes,
const char * rank,
size_t indent)
1646 for (
size_t i = 0; i < nodes.size(); i++)
1648 nodes[i]->OutputDot(out,
indent);
1652 withIndent(out,
indent) << nodes[i - 1]->GetFullId() <<
" -> " << nodes[i]->GetFullId()
1653 <<
"[style=invis];" << std::endl;
1660 for (
auto & node :
Nodes_)
1662 node->OutputDot(out,
indent);
1667 for (
auto & edge :
Edges_)
1669 edge->OutputDot(out,
indent);
1679 bool firstField =
true;
1753 auto graph =
new Graph(*
this);
1774 auto graph =
new Graph(*
this, parentNode);
1783 if (
auto found = graph->GetElementFromProgramObject(
object))
1800 if (!graph->IsSubgraph())
1816 if (!graph->IsSubgraph())
1817 graph->Output(out, format, 0);
1824 graph->Output(out, format, 0);
1830 out <<
"{" << std::endl;
1837 out <<
"," << std::endl;
1838 graph->Output(out, format, 1);
1840 out << std::endl <<
"}" << std::endl;
bool CanBeEdgeHead() const override
void SetOutsideSource(const Port &outsideSource)
const char * GetIdPrefix() const override
const Port * OutsideSource_
ArgumentNode(Graph &graph)
void OutputASCII(std::ostream &out, size_t indent) const override
void SetStyle(std::string style)
void SetArrowTail(std::string arrow)
Port & GetOtherEnd(const Port &end)
const char * GetIdPrefix() const override
Graph & GetGraph() override
std::string_view getDirection() const
Edge(Port &from, Port &to, bool directed)
void OutputDot(std::ostream &out, size_t indent) const
void SetArrowHead(std::string arrow)
void outputJson(std::ostream &out, size_t indent) const
size_t GetUniqueIdSuffix() const
void outputJsonObjectOpening(std::ostream &out, size_t indent, bool &firstField) const
virtual Graph & GetGraph()=0
void SetLabel(std::string label)
uintptr_t GetProgramObject() const noexcept
std::string GetFullId() const
void SetAttributeObject(const std::string &attribute, uintptr_t object)
void RemoveProgramObject()
void AppendToLabel(std::string_view text, std::string_view sep="\n")
void SetAttribute(const std::string &attribute, std::string value)
virtual const char * GetIdPrefix() const =0
std::string_view GetLabelOr(std::string_view otherwise) const
const std::string & GetLabel() const
void PrintFullId(std::ostream &out) const
bool RemoveAttribute(const std::string &attribute)
std::optional< uintptr_t > GetAttributeObject(const std::string &attribute) const
std::unordered_map< std::string, AttributeValue > AttributeMap_
void OutputAttribute(std::ostream &out, const std::string &name, AttributeOutputFormat format) const
void OutputAttributes(std::ostream &out, AttributeOutputFormat format) const
bool HasAttribute(const std::string &attribute) const
const GraphElement * GetAttributeGraphElement(const std::string &attribute) const
std::optional< size_t > UniqueIdSuffix_
std::optional< std::string_view > GetAttributeString(const std::string &attribute) const
void SetProgramObjectUintptr(uintptr_t object)
void SetAttributeGraphElement(const std::string &attribute, const GraphElement &element)
bool HasProgramObject() const noexcept
std::vector< std::unique_ptr< ArgumentNode > > ArgumentNodes_
ArgumentNode & CreateArgumentNode()
Node & GetNode(size_t index)
void Output(std::ostream &out, OutputFormat format, size_t indent) const
GraphElement * GetElementFromProgramObject(uintptr_t object) const
std::unordered_map< uintptr_t, GraphElement * > ProgramObjectMapping_
Node & GetResultNode(size_t index)
Edge & GetEdge(size_t index)
Edge * GetEdgeBetween(Port &a, Port &b)
void OutputASCII(std::ostream &out, size_t indent) const
const char * GetIdPrefix() const override
void RemoveProgramObjectMapping(uintptr_t object)
std::vector< std::unique_ptr< Edge > > Edges_
Graph & GetGraph() override
ResultNode & CreateResultNode()
size_t NumResultNodes() const noexcept
std::vector< std::unique_ptr< ResultNode > > ResultNodes_
void OutputDot(std::ostream &out, size_t indent) const
size_t NumEdges() const noexcept
size_t NumNodes() const noexcept
Node & GetArgumentNode(size_t index)
InOutNode & CreateInOutNode(size_t inputPorts, size_t outputPorts)
size_t NumArgumentNodes() const noexcept
void outputJson(std::ostream &out, size_t indent) const
std::vector< std::unique_ptr< Node > > Nodes_
Edge & CreateEdge(Port &from, Port &to, bool directed)
void MapProgramObjectToElement(GraphElement &element)
size_t NumInputPorts() const
void OutputSubgraphs(std::ostream &out, OutputFormat format, size_t indent) const override
std::unordered_map< std::string, std::string > HtmlTableAttributes_
std::vector< std::unique_ptr< OutputPort > > OutputPorts_
void OutputDot(std::ostream &out, size_t indent) const override
InOutNode(Graph &graph, size_t inputPorts, size_t outputPorts)
void outputJson(std::ostream &out, size_t indent) const override
void SetFillColor(std::string color) override
size_t NumOutputPorts() const
OutputPort & GetOutputPort(size_t index)
std::vector< Graph * > SubGraphs_
std::vector< std::unique_ptr< InputPort > > InputPorts_
void SetShape(std::string) override
InputPort & GetInputPort(size_t index)
size_t NumSubgraphs() const
Graph & GetSubgraph(size_t index)
InputPort & CreateInputPort()
void OutputASCII(std::ostream &out, size_t indent) const override
void SetHtmlTableAttribute(std::string name, std::string value)
OutputPort & CreateOutputPort()
Node & GetNode() override
const char * GetIdPrefix() const override
Graph & GetGraph() override
virtual void OutputDot(std::ostream &out, size_t indent) const
virtual void OutputSubgraphs(std::ostream &out, OutputFormat format, size_t indent) const
void OutputDotPortId(std::ostream &out) const override
virtual void OutputASCII(std::ostream &out, size_t indent) const
virtual void outputJson(std::ostream &out, size_t indent) const
virtual void SetShape(std::string shape)
void SetFillColor(std::string color) override
Node & GetNode() override
void SetFillColor(std::string color) override
void outputJson(std::ostream &out, size_t indent) const
OutputPort(InOutNode &node)
bool CanBeEdgeHead() const override
void OutputDotPortId(std::ostream &out) const override
const char * GetIdPrefix() const override
const std::vector< Edge * > & GetConnections() const
virtual bool CanBeEdgeTail() const
virtual bool CanBeEdgeHead() const
std::vector< Edge * > Connections_
bool HasIncomingEdges() const
void OutputIncomingEdgesASCII(std::ostream &out) const
Graph & GetGraph() override
void OnEdgeAdded(Edge &edge)
bool HasOutgoingEdges() const
virtual void OutputDotPortId(std::ostream &out) const =0
virtual Node & GetNode()=0
const Port * OutsideDestination_
void SetOutsideDestination(const Port &outsideSource)
void OutputASCII(std::ostream &out, size_t indent) const override
const char * GetIdPrefix() const override
bool CanBeEdgeTail() const override
GraphElement * GetElementFromProgramObject(uintptr_t object) const
size_t GetNextUniqueIdStubSuffix(const char *idStub)
std::unordered_map< std::string, size_t > NextUniqueIdStubSuffix_
size_t NumGraphs() const noexcept
Graph & CreateSubGraph(Node &parentNode)
std::vector< std::unique_ptr< Graph > > Graphs_
void outputAllGraphs(std::ostream &out, OutputFormat format)
Graph & GetGraph(size_t index)
#define JLM_UNREACHABLE(msg)
std::string Edge(jlm::rvsdg::Output *output, jlm::rvsdg::Input *input, std::unordered_map< rvsdg::Output *, ViewColors > &tailLabel, bool back_edge=false)
static bool empty(const rvsdg::GammaNode *gamma)
static std::string indent(size_t depth)
static void printJsonString(std::ostream &out, std::string_view string)
static const char *const JSON_PARENT_NODE_FIELD
static void printStringAsHtmlAttributeName(std::ostream &out, std::string_view string)
static void outputJsonObjectClosing(std::ostream &out, size_t indent, bool firstField)
static const char *const JSON_NODES_FIELD
static const char *const DOT_EDGE_ID_ATTRIBUTE
std::ostream & withIndent(std::ostream &out, size_t indent)
static const char *const JSON_LABEL_FIELD
static const char *const JSON_SUBGRAPHS_FIELD
static void printIdentifierSafe(std::ostream &out, std::string_view string)
static const char *const DOT_TOOLTIP_ATTRIBUTE
static void printJsonElementMap(std::ostream &out, size_t indent, const T &elements)
static const char *const DOT_HTML_TABLE_BGCOLOR_ATTRIBUTE
static const char *const JSON_HTML_TABLE_ATTRIBUTES_FIELD
static bool looksLikeIdentifier(std::string_view string)
static const char *const JSON_ATTRIBUTE_FIELD
static const char *const JSON_NODE_TYPE_FIELD
static std::ostream & printNextJsonField(std::ostream &out, std::string_view name, size_t indent, bool &firstField)
static const char *const JSON_OBJECT_POINTER_FIELD
static const char *const JSON_IN_PORTS_FIELD
static const char *const JSON_OUT_PORTS_FIELD
static const char *const JSON_PARENT_GRAPH_FIELD
static const char *const JSON_ARGUMENTS_FIELD
static void outputKeyValuePair(std::ostream &out, std::string_view name, std::string_view value, AttributeOutputFormat format)
static void printStringAsHtmlText(std::ostream &out, std::string_view string, bool replaceNewlines)
static const char *const JSON_EDGES_FIELD
static const char *const JSON_RESULTS_FIELD
static std::string strfmt(Args... args)