Jlm
GraphWriter.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2024 HÃ¥vard Krogstie <krogstie.havard@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
6 #ifndef JLM_UTIL_GRAPHWRITER_HPP
7 #define JLM_UTIL_GRAPHWRITER_HPP
8 
9 #include <jlm/util/common.hpp>
10 
11 #include <cstdint>
12 #include <memory>
13 #include <optional>
14 #include <unordered_map>
15 #include <variant>
16 #include <vector>
17 
18 namespace jlm::util::graph
19 {
20 
21 enum class OutputFormat
22 {
23  Dot, // prints the graphs in the GraphViz dot format
24  Json, // prints a json object containing all the graphs
25  ASCII, // Textual output format that makes edges implicit when possible
26 };
27 
29 {
30  SpaceSeparatedList, // printed on the form attr=value other="value 2"
31  HTMLAttributes, // adds extra restrictions on attribute names
32  JSON // outputs a comma separated list of "name": "value" pairs
33 };
34 
35 class Writer;
36 class Node;
37 class Edge;
38 class Port;
39 class Graph;
40 
42 {
43 public:
44  virtual ~GraphElement() = default;
45 
49  GraphElement();
50 
51  GraphElement(const GraphElement & other) = delete;
52 
53  GraphElement(GraphElement && other) = delete;
54 
55  GraphElement &
56  operator=(const GraphElement & other) = delete;
57 
58  GraphElement &
59  operator=(GraphElement && other) = delete;
60 
66  [[nodiscard]] virtual const char *
67  GetIdPrefix() const = 0;
68 
74  void
75  PrintFullId(std::ostream & out) const;
76 
83  [[nodiscard]] std::string
84  GetFullId() const;
85 
89  [[nodiscard]] virtual Graph &
90  GetGraph() = 0;
91 
92  [[nodiscard]] const Graph &
93  GetGraph() const;
94 
101  void
102  SetLabel(std::string label);
103 
108  void
109  AppendToLabel(std::string_view text, std::string_view sep = "\n");
110 
114  [[nodiscard]] bool
115  HasLabel() const;
116 
120  [[nodiscard]] const std::string &
121  GetLabel() const;
122 
126  [[nodiscard]] std::string_view
127  GetLabelOr(std::string_view otherwise) const;
128 
133  [[nodiscard]] size_t
134  GetUniqueIdSuffix() const;
135 
145  template<typename T>
146  void
147  SetProgramObject(const T & object)
148  {
149  SetProgramObjectUintptr(reinterpret_cast<uintptr_t>(&object));
150  }
151 
155  void
157 
161  [[nodiscard]] bool
162  HasProgramObject() const noexcept;
163 
167  [[nodiscard]] uintptr_t
168  GetProgramObject() const noexcept;
169 
175  void
176  SetAttribute(const std::string & attribute, std::string value);
177 
185  void
186  SetAttributeObject(const std::string & attribute, uintptr_t object);
187 
191  template<typename T>
192  void
193  SetAttributeObject(const std::string & attribute, const T & object)
194  {
195  SetAttributeObject(attribute, reinterpret_cast<uintptr_t>(&object));
196  }
197 
205  void
206  SetAttributeGraphElement(const std::string & attribute, const GraphElement & element);
207 
211  [[nodiscard]] bool
212  HasAttribute(const std::string & attribute) const;
213 
218  [[nodiscard]] std::optional<std::string_view>
219  GetAttributeString(const std::string & attribute) const;
220 
226  [[nodiscard]] std::optional<uintptr_t>
227  GetAttributeObject(const std::string & attribute) const;
228 
235  [[nodiscard]] const GraphElement *
236  GetAttributeGraphElement(const std::string & attribute) const;
237 
242  bool
243  RemoveAttribute(const std::string & attribute);
244 
248  virtual void
249  Finalize();
250 
254  [[nodiscard]] bool
255  IsFinalized() const;
256 
262  void
263  OutputAttributes(std::ostream & out, AttributeOutputFormat format) const;
264 
281  void
282  outputJsonObjectOpening(std::ostream & out, size_t indent, bool & firstField) const;
283 
284 private:
285  // The types an attribute can have. Its value can be a string, a reference to a
286  // GraphElement, or a reference to a program object.
287  using AttributeValue = std::variant<std::string, const GraphElement *, uintptr_t>;
288 
289  void
290  SetProgramObjectUintptr(uintptr_t object);
291 
292  void
293  OutputAttribute(std::ostream & out, const std::string & name, AttributeOutputFormat format) const;
294 
295  // A human-readable piece of text that should be rendered with the element
296  std::string Label_;
297 
298  // A number added to the end of the id stub to make it globally unique
299  std::optional<size_t> UniqueIdSuffix_;
300 
301  // The object in the program this graph object corresponds to, or 0 if none
302  uintptr_t ProgramObject_;
303 
304  // All other attributes
305  std::unordered_map<std::string, AttributeValue> AttributeMap_;
306 };
307 
311 class Port : public GraphElement
312 {
313  friend Edge;
314 
315 protected:
316  Port();
317 
318 public:
319  ~Port() override = default;
320 
321  virtual Node &
322  GetNode() = 0;
323 
324  Graph &
325  GetGraph() override;
326 
330  [[nodiscard]] virtual bool
331  CanBeEdgeHead() const;
332 
336  [[nodiscard]] virtual bool
337  CanBeEdgeTail() const;
338 
342  [[nodiscard]] const std::vector<Edge *> &
343  GetConnections() const;
344 
348  [[nodiscard]] bool
349  HasOutgoingEdges() const;
350 
354  [[nodiscard]] bool
355  HasIncomingEdges() const;
356 
362  virtual void
363  SetFillColor(std::string color) = 0;
364 
369  virtual void
370  OutputDotPortId(std::ostream & out) const = 0;
371 
378  void
379  OutputIncomingEdgesASCII(std::ostream & out) const;
380 
381 private:
386  void
387  OnEdgeAdded(Edge & edge);
388 
389  std::vector<Edge *> Connections_;
390 };
391 
396 class Node : public Port
397 {
398  friend Graph;
399 
400 protected:
401  explicit Node(Graph & graph);
402 
403 public:
404  ~Node() override = default;
405 
406  const char *
407  GetIdPrefix() const override;
408 
409  Node &
410  GetNode() override;
411 
415  Graph &
416  GetGraph() override;
417 
422  virtual void
423  SetShape(std::string shape);
424 
429  struct Shape
430  {
431  static inline const char * const Rectangle = "rect";
432  static inline const char * const Circle = "circle";
433  static inline const char * const Oval = "oval";
434  static inline const char * const Point = "point";
435  static inline const char * const Plain = "plain";
436  static inline const char * const Plaintext = "plaintext";
437  static inline const char * const Triangle = "triangle";
438  static inline const char * const DoubleCircle = "doublecircle";
439  };
440 
441  void
442  SetFillColor(std::string color) override;
443 
444  void
445  OutputDotPortId(std::ostream & out) const override;
446 
452  virtual void
453  OutputSubgraphs(std::ostream & out, OutputFormat format, size_t indent) const;
454 
460  virtual void
461  OutputASCII(std::ostream & out, size_t indent) const;
462 
467  virtual void
468  OutputDot(std::ostream & out, size_t indent) const;
469 
474  virtual void
475  outputJson(std::ostream & out, size_t indent) const;
476 
477 private:
479 };
480 
481 class InOutNode;
482 class InputPort;
483 class OutputPort;
484 
488 class InputPort final : public Port
489 {
490  friend InOutNode;
491 
492  explicit InputPort(InOutNode & node);
493 
494 public:
495  ~InputPort() override = default;
496 
497  const char *
498  GetIdPrefix() const override;
499 
500  Node &
501  GetNode() override;
502 
503  bool
504  CanBeEdgeTail() const override;
505 
506  void
507  SetFillColor(std::string color) override;
508 
509  void
510  OutputDotPortId(std::ostream & out) const override;
511 
512  void
513  outputJson(std::ostream & out, size_t indent) const;
514 
515 private:
517 };
518 
522 class OutputPort final : public Port
523 {
524  friend InOutNode;
525 
526  explicit OutputPort(InOutNode & node);
527 
528 public:
529  ~OutputPort() override = default;
530 
531  const char *
532  GetIdPrefix() const override;
533 
534  Node &
535  GetNode() override;
536 
537  bool
538  CanBeEdgeHead() const override;
539 
540  void
541  SetFillColor(std::string color) override;
542 
543  void
544  OutputDotPortId(std::ostream & out) const override;
545 
546  void
547  outputJson(std::ostream & out, size_t indent) const;
548 
549 private:
551 };
552 
558 class InOutNode final : public Node
559 {
560  friend Graph;
561 
562  InOutNode(Graph & graph, size_t inputPorts, size_t outputPorts);
563 
564 public:
565  ~InOutNode() override = default;
566 
570  void SetShape(std::string) override;
571 
572  InputPort &
573  CreateInputPort();
574 
575  size_t
576  NumInputPorts() const;
577 
578  InputPort &
579  GetInputPort(size_t index);
580 
581  OutputPort &
583 
584  size_t
585  NumOutputPorts() const;
586 
587  OutputPort &
588  GetOutputPort(size_t index);
589 
594  Graph &
595  CreateSubgraph();
596 
600  size_t
601  NumSubgraphs() const;
602 
606  Graph &
607  GetSubgraph(size_t index);
608 
617  void
618  SetHtmlTableAttribute(std::string name, std::string value);
619 
620  void
621  SetFillColor(std::string color) override;
622 
623  void
624  Finalize() override;
625 
626  void
627  OutputSubgraphs(std::ostream & out, OutputFormat format, size_t indent) const override;
628 
629  void
630  OutputASCII(std::ostream & out, size_t indent) const override;
631 
632  void
633  OutputDot(std::ostream & out, size_t indent) const override;
634 
635  void
636  outputJson(std::ostream & out, size_t indent) const override;
637 
638 private:
639  // Attributes that need to be placed on the HTML table in the dot output, and not on the node.
640  std::unordered_map<std::string, std::string> HtmlTableAttributes_;
641 
642  std::vector<std::unique_ptr<InputPort>> InputPorts_;
643  std::vector<std::unique_ptr<OutputPort>> OutputPorts_;
644  std::vector<Graph *> SubGraphs_;
645 };
646 
651 class ArgumentNode : public Node
652 {
653  friend Graph;
654 
655  explicit ArgumentNode(Graph & graph);
656 
657 public:
658  ~ArgumentNode() override = default;
659 
660  const char *
661  GetIdPrefix() const override;
662 
663  bool
664  CanBeEdgeHead() const override;
665 
670  void
671  SetOutsideSource(const Port & outsideSource);
672 
673 protected:
674  void
675  OutputASCII(std::ostream & out, size_t indent) const override;
676 
677 private:
678  // Optional reference to a Port outside of this graph from which this argument came
680 };
681 
686 class ResultNode : public Node
687 {
688  friend Graph;
689 
690  explicit ResultNode(Graph & graph);
691 
692 public:
693  ~ResultNode() override = default;
694 
695  const char *
696  GetIdPrefix() const override;
697 
698  bool
699  CanBeEdgeTail() const override;
700 
705  void
706  SetOutsideDestination(const Port & outsideSource);
707 
708 protected:
709  void
710  OutputASCII(std::ostream & out, size_t indent) const override;
711 
712 private:
713  // Optional reference to a Port outside of this graph representing where the result ends up
715 };
716 
717 class Edge : public GraphElement
718 {
719  friend Graph;
720 
721  Edge(Port & from, Port & to, bool directed);
722 
723 public:
724  ~Edge() override = default;
725 
726  const char *
727  GetIdPrefix() const override;
728 
729  Graph &
730  GetGraph() override;
731 
736  [[nodiscard]] Port &
737  GetFrom();
738 
743  [[nodiscard]] Port &
744  GetTo();
745 
749  [[nodiscard]] bool
750  IsDirected() const;
751 
755  [[nodiscard]] Port &
756  GetOtherEnd(const Port & end);
757 
762  void
763  SetStyle(std::string style);
764 
768  struct Style
769  {
770  static inline const char * const Solid = "solid";
771  static inline const char * const Dashed = "dashed";
772  static inline const char * const Dotted = "dotted";
773  static inline const char * const Invisible = "invis";
774  static inline const char * const Bold = "bold";
775  static inline const char * const Tapered = "tapered";
776  };
777 
786  void
787  SetArrowHead(std::string arrow);
788 
794  void
795  SetArrowTail(std::string arrow);
796 
803  std::string_view
804  getDirection() const;
805 
809  void
810  OutputDot(std::ostream & out, size_t indent) const;
811 
815  void
816  outputJson(std::ostream & out, size_t indent) const;
817 
818 private:
821  bool Directed_;
822 };
823 
824 class Graph : public GraphElement
825 {
826  friend Writer;
827  friend GraphElement;
828 
829  explicit Graph(Writer & writer);
830 
831  Graph(Writer & writer, Node & parentNode);
832 
833 public:
834  ~Graph() override = default;
835 
836  const char *
837  GetIdPrefix() const override;
838 
839  Graph &
840  GetGraph() override;
841 
842  [[nodiscard]] Writer &
843  GetWriter();
844 
845  [[nodiscard]] const Writer &
846  GetWriter() const;
847 
851  [[nodiscard]] bool
852  IsSubgraph() const;
853 
858  [[nodiscard]] Node &
859  CreateNode();
860 
867  [[nodiscard]] InOutNode &
868  CreateInOutNode(size_t inputPorts, size_t outputPorts);
869 
873  [[nodiscard]] size_t
874  NumNodes() const noexcept;
875 
881  [[nodiscard]] Node &
882  GetNode(size_t index);
883 
888  [[nodiscard]] ArgumentNode &
890 
894  [[nodiscard]] size_t
895  NumArgumentNodes() const noexcept;
896 
901  [[nodiscard]] Node &
902  GetArgumentNode(size_t index);
903 
908  [[nodiscard]] ResultNode &
910 
914  [[nodiscard]] size_t
915  NumResultNodes() const noexcept;
916 
921  [[nodiscard]] Node &
922  GetResultNode(size_t index);
923 
932  Edge &
933  CreateEdge(Port & from, Port & to, bool directed);
934 
940  Edge &
942  {
943  return CreateEdge(from, to, true);
944  }
945 
952  Edge &
954  {
955  return CreateEdge(a, b, false);
956  }
957 
961  [[nodiscard]] size_t
962  NumEdges() const noexcept;
963 
968  [[nodiscard]] Edge &
969  GetEdge(size_t index);
970 
977  [[nodiscard]] Edge *
978  GetEdgeBetween(Port & a, Port & b);
979 
986  [[nodiscard]] GraphElement *
987  GetElementFromProgramObject(uintptr_t object) const;
988 
989  template<typename T>
990  [[nodiscard]] GraphElement *
991  GetElementFromProgramObject(const T & object) const
992  {
993  // Check that object is not a reference to a pointer.
994  // If the user truly wants to use the address of a pointer, they can cast it to uintptr_t.
995  static_assert(!std::is_pointer_v<T>);
996  return GetElementFromProgramObject(reinterpret_cast<uintptr_t>(&object));
997  }
998 
1006  template<typename Element, typename ProgramObject>
1007  Element &
1008  GetFromProgramObject(const ProgramObject & object) const
1009  {
1010  static_assert(std::is_base_of_v<GraphElement, Element>);
1011  GraphElement * element = GetElementFromProgramObject(object);
1012  auto result = dynamic_cast<Element *>(element);
1013  JLM_ASSERT(result);
1014  return *result;
1015  }
1016 
1021  void
1022  Finalize() override;
1023 
1031  void
1032  Output(std::ostream & out, OutputFormat format, size_t indent) const;
1033 
1034 private:
1035  void
1036  OutputASCII(std::ostream & out, size_t indent) const;
1037 
1038  void
1039  OutputDot(std::ostream & out, size_t indent) const;
1040 
1041  void
1042  outputJson(std::ostream & out, size_t indent) const;
1043 
1049  void
1051 
1056  void
1057  RemoveProgramObjectMapping(uintptr_t object);
1058 
1059  // The GraphWriter this graph was created by, and belongs to
1061 
1062  // If this graph is a subgraph, this is its parent node in the parent graph.
1063  // For top level graphs, this field is nullptr
1065 
1066  // The set of nodes in the graph. Finalizing the graph may re-order this list.
1067  std::vector<std::unique_ptr<Node>> Nodes_;
1068 
1069  // Argument nodes and result nodes are kept in separate lists
1070  std::vector<std::unique_ptr<ArgumentNode>> ArgumentNodes_;
1071  std::vector<std::unique_ptr<ResultNode>> ResultNodes_;
1072 
1073  std::vector<std::unique_ptr<Edge>> Edges_;
1074 
1075  // A mapping from pointers to program objects, to the GraphElement representing the program object
1076  std::unordered_map<uintptr_t, GraphElement *> ProgramObjectMapping_;
1077 };
1078 
1083 class Writer
1084 {
1085 public:
1086  ~Writer() = default;
1087 
1088  Writer() = default;
1089 
1090  Writer(const Writer & other) = delete;
1091 
1092  Writer(Writer && other) = delete;
1093 
1094  Writer &
1095  operator=(const Writer & other) = delete;
1096 
1097  Writer &
1098  operator=(Writer && other) = delete;
1099 
1104  [[nodiscard]] Graph &
1105  CreateGraph();
1106 
1110  [[nodiscard]] size_t
1111  NumGraphs() const noexcept;
1112 
1116  [[nodiscard]] Graph &
1117  GetGraph(size_t index);
1118 
1123  [[nodiscard]] GraphElement *
1124  GetElementFromProgramObject(uintptr_t object) const;
1125 
1126  template<typename T>
1127  [[nodiscard]] GraphElement *
1128  GetElementFromProgramObject(const T & object) const
1129  {
1130  // Check that object is not a reference to a pointer.
1131  // If the user truly wants to use the address of a pointer, they can cast it to uintptr_t.
1132  static_assert(!std::is_pointer_v<T>);
1133  return GetElementFromProgramObject(reinterpret_cast<uintptr_t>(&object));
1134  }
1135 
1140  void
1141  Finalize();
1142 
1148  void
1149  outputAllGraphs(std::ostream & out, OutputFormat format);
1150 
1151 private:
1152  [[nodiscard]] Graph &
1153  CreateSubGraph(Node & parentNode);
1154 
1155  friend Graph &
1157 
1162  [[nodiscard]] size_t
1163  GetNextUniqueIdStubSuffix(const char * idStub);
1164 
1165  friend void
1167 
1168  // All graphs being worked on by the GraphWriter
1169  // Edges can not go across graphs.
1170  // IDs are however unique across graphs allowing semantic connections.
1171  std::vector<std::unique_ptr<Graph>> Graphs_;
1172 
1173  // Tracks the next integer to be used when assigning a unique suffix to a given id stub
1174  std::unordered_map<std::string, size_t> NextUniqueIdStubSuffix_;
1175 };
1176 
1181 namespace Colors
1182 {
1183 inline const char * const Black = "#000000";
1184 inline const char * const Blue = "#0000FF";
1185 inline const char * const Coral = "#FF7F50";
1186 inline const char * const CornflowerBlue = "#6495ED";
1187 inline const char * const Firebrick = " #B22222";
1188 inline const char * const Gold = "#FFD700";
1189 inline const char * const Gray = "#BEBEBE";
1190 inline const char * const Green = "#00FF00";
1191 inline const char * const Orange = "#FFA500";
1192 inline const char * const Purple = "#A020F0";
1193 inline const char * const Red = "#FF0000";
1194 inline const char * const Brown = "#8B4513"; // X11's Saddle Brown
1195 inline const char * const SkyBlue = "#87CEEB";
1196 inline const char * const White = "#FFFFFF";
1197 inline const char * const Yellow = "#FFFF00";
1198 }
1199 
1200 }
1201 #endif // JLM_UTIL_GRAPHWRITER_HPP
bool CanBeEdgeHead() const override
void SetOutsideSource(const Port &outsideSource)
const char * GetIdPrefix() const override
~ArgumentNode() override=default
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)
~Edge() override=default
void outputJson(std::ostream &out, size_t indent) const
void outputJsonObjectOpening(std::ostream &out, size_t indent, bool &firstField) const
void SetProgramObject(const T &object)
GraphElement & operator=(GraphElement &&other)=delete
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)
virtual ~GraphElement()=default
std::variant< std::string, const GraphElement *, uintptr_t > AttributeValue
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
GraphElement(const GraphElement &other)=delete
const std::string & GetLabel() const
void PrintFullId(std::ostream &out) const
bool RemoveAttribute(const std::string &attribute)
GraphElement(GraphElement &&other)=delete
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
GraphElement & operator=(const GraphElement &other)=delete
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
Edge & CreateUndirectedEdge(Port &a, Port &b)
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 Finalize() override
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)
Edge & CreateDirectedEdge(Port &from, Port &to)
size_t NumArgumentNodes() const noexcept
void outputJson(std::ostream &out, size_t indent) const
std::vector< std::unique_ptr< Node > > Nodes_
Element & GetFromProgramObject(const ProgramObject &object) const
Edge & CreateEdge(Port &from, Port &to, bool directed)
void MapProgramObjectToElement(GraphElement &element)
~Graph() override=default
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
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)
~InOutNode() override=default
Graph & GetSubgraph(size_t index)
void OutputASCII(std::ostream &out, size_t indent) const override
void SetHtmlTableAttribute(std::string name, std::string value)
OutputPort & CreateOutputPort()
const char * GetIdPrefix() const override
bool CanBeEdgeTail() const override
void SetFillColor(std::string color) override
~InputPort() override=default
void outputJson(std::ostream &out, size_t indent) const
void OutputDotPortId(std::ostream &out) const override
InputPort(InOutNode &node)
Node & GetNode() override
Node & GetNode() override
~Node() override=default
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
void SetFillColor(std::string color) override
void outputJson(std::ostream &out, size_t indent) const
~OutputPort() override=default
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
virtual void SetFillColor(std::string color)=0
std::vector< Edge * > Connections_
bool HasIncomingEdges() const
~Port() override=default
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
void SetOutsideDestination(const Port &outsideSource)
void OutputASCII(std::ostream &out, size_t indent) const override
const char * GetIdPrefix() const override
~ResultNode() override=default
bool CanBeEdgeTail() const override
GraphElement * GetElementFromProgramObject(uintptr_t object) const
size_t GetNextUniqueIdStubSuffix(const char *idStub)
std::unordered_map< std::string, size_t > NextUniqueIdStubSuffix_
Writer(Writer &&other)=delete
size_t NumGraphs() const noexcept
Graph & CreateSubGraph(Node &parentNode)
std::vector< std::unique_ptr< Graph > > Graphs_
void outputAllGraphs(std::ostream &out, OutputFormat format)
Writer & operator=(Writer &&other)=delete
Writer(const Writer &other)=delete
Writer & operator=(const Writer &other)=delete
Graph & GetGraph(size_t index)
#define JLM_ASSERT(x)
Definition: common.hpp:16
std::string Edge(jlm::rvsdg::Output *output, jlm::rvsdg::Input *input, std::unordered_map< rvsdg::Output *, ViewColors > &tailLabel, bool back_edge=false)
Definition: view.cpp:172
static std::string indent(size_t depth)
Definition: view.cpp:22
const char *const Purple
const char *const White
const char *const Firebrick
const char *const Red
const char *const Brown
const char *const Yellow
const char *const Black
const char *const Gold
const char *const Blue
const char *const CornflowerBlue
const char *const Green
const char *const Orange
const char *const Coral
const char *const SkyBlue
const char *const Gray
static const char *const Dashed
static const char *const Bold
static const char *const Invisible
static const char *const Tapered
static const char *const Solid
static const char *const Dotted
static const char *const Plain
static const char *const Plaintext
static const char *const Point
static const char *const Triangle
static const char *const Rectangle
static const char *const Oval
static const char *const DoubleCircle
static const char *const Circle