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
24  ASCII, // output format that makes edges implicit when possible
25 };
26 
28 {
29  SpaceSeparatedList, // printed on the form attr=value other="value 2"
30  HTMLAttributes // adds extra restrictions on attribute names
31 };
32 
33 class Writer;
34 class Node;
35 class Edge;
36 class Port;
37 class Graph;
38 
40 {
41 public:
42  virtual ~GraphElement() = default;
43 
47  GraphElement();
48 
49  GraphElement(const GraphElement & other) = delete;
50 
51  GraphElement(GraphElement && other) = delete;
52 
53  GraphElement &
54  operator=(const GraphElement & other) = delete;
55 
56  GraphElement &
57  operator=(GraphElement && other) = delete;
58 
64  [[nodiscard]] virtual const char *
65  GetIdPrefix() const = 0;
66 
72  [[nodiscard]] std::string
73  GetFullId() const;
74 
78  [[nodiscard]] virtual Graph &
79  GetGraph() = 0;
80 
81  [[nodiscard]] const Graph &
82  GetGraph() const;
83 
90  void
91  SetLabel(std::string label);
92 
97  void
98  AppendToLabel(std::string_view text, std::string_view sep = "\n");
99 
103  [[nodiscard]] bool
104  HasLabel() const;
105 
109  [[nodiscard]] const std::string &
110  GetLabel() const;
111 
115  [[nodiscard]] std::string_view
116  GetLabelOr(std::string_view otherwise) const;
117 
122  [[nodiscard]] size_t
123  GetUniqueIdSuffix() const;
124 
134  template<typename T>
135  void
136  SetProgramObject(const T & object)
137  {
138  SetProgramObjectUintptr(reinterpret_cast<uintptr_t>(&object));
139  }
140 
144  void
146 
150  [[nodiscard]] bool
151  HasProgramObject() const noexcept;
152 
156  [[nodiscard]] uintptr_t
157  GetProgramObject() const noexcept;
158 
164  void
165  SetAttribute(const std::string & attribute, std::string value);
166 
174  void
175  SetAttributeObject(const std::string & attribute, uintptr_t object);
176 
180  template<typename T>
181  void
182  SetAttributeObject(const std::string & attribute, const T & object)
183  {
184  SetAttributeObject(attribute, reinterpret_cast<uintptr_t>(&object));
185  }
186 
194  void
195  SetAttributeGraphElement(const std::string & attribute, const GraphElement & element);
196 
200  [[nodiscard]] bool
201  HasAttribute(const std::string & attribute) const;
202 
207  [[nodiscard]] std::optional<std::string_view>
208  GetAttributeString(const std::string & attribute) const;
209 
215  [[nodiscard]] std::optional<uintptr_t>
216  GetAttributeObject(const std::string & attribute) const;
217 
224  [[nodiscard]] const GraphElement *
225  GetAttributeGraphElement(const std::string & attribute) const;
226 
231  bool
232  RemoveAttribute(const std::string & attribute);
233 
237  virtual void
238  Finalize();
239 
243  [[nodiscard]] bool
244  IsFinalized() const;
245 
251  void
252  OutputAttributes(std::ostream & out, AttributeOutputFormat format) const;
253 
254 private:
255  void
256  SetProgramObjectUintptr(uintptr_t object);
257 
258  // A human-readable piece of text that should be rendered with the element
259  std::string Label_;
260 
261  // A number added to the end of the id stub to make it globally unique
262  std::optional<size_t> UniqueIdSuffix_;
263 
264  // The object in the program this graph object corresponds to, or 0 if none
265  uintptr_t ProgramObject_;
266 
267  // Arbitrary collection of other attributes. The value can be a string, a reference to a
268  // GraphElement, or a reference to a program object.
269  using AttributeValue = std::variant<std::string, const GraphElement *, uintptr_t>;
270  std::unordered_map<std::string, AttributeValue> AttributeMap_;
271 };
272 
276 class Port : public GraphElement
277 {
278  friend Edge;
279 
280 protected:
281  Port();
282 
283 public:
284  ~Port() override = default;
285 
286  virtual Node &
287  GetNode() = 0;
288 
289  Graph &
290  GetGraph() override;
291 
295  [[nodiscard]] virtual bool
296  CanBeEdgeHead() const;
297 
301  [[nodiscard]] virtual bool
302  CanBeEdgeTail() const;
303 
307  [[nodiscard]] const std::vector<Edge *> &
308  GetConnections() const;
309 
313  [[nodiscard]] bool
314  HasOutgoingEdges() const;
315 
319  [[nodiscard]] bool
320  HasIncomingEdges() const;
321 
327  virtual void
328  SetFillColor(std::string color) = 0;
329 
334  virtual void
335  OutputDotPortId(std::ostream & out) const = 0;
336 
343  void
344  OutputIncomingEdgesASCII(std::ostream & out) const;
345 
346 private:
351  void
352  OnEdgeAdded(Edge & edge);
353 
354  std::vector<Edge *> Connections_;
355 };
356 
361 class Node : public Port
362 {
363  friend Graph;
364 
365 protected:
366  explicit Node(Graph & graph);
367 
368 public:
369  ~Node() override = default;
370 
371  const char *
372  GetIdPrefix() const override;
373 
374  Node &
375  GetNode() override;
376 
380  Graph &
381  GetGraph() override;
382 
387  virtual void
388  SetShape(std::string shape);
389 
394  struct Shape
395  {
396  static inline const char * const Rectangle = "rect";
397  static inline const char * const Circle = "circle";
398  static inline const char * const Oval = "oval";
399  static inline const char * const Point = "point";
400  static inline const char * const Plain = "plain";
401  static inline const char * const Plaintext = "plaintext";
402  static inline const char * const Triangle = "triangle";
403  static inline const char * const DoubleCircle = "doublecircle";
404  };
405 
406  void
407  SetFillColor(std::string color) override;
408 
409  void
410  OutputDotPortId(std::ostream & out) const override;
411 
417  void
418  Output(std::ostream & out, OutputFormat format, size_t indent) const;
419 
425  virtual void
426  OutputSubgraphs(std::ostream & out, OutputFormat format, size_t indent) const;
427 
428 protected:
434  virtual void
435  OutputASCII(std::ostream & out, size_t indent) const;
436 
441  virtual void
442  OutputDot(std::ostream & out, size_t indent) const;
443 
444 private:
446 };
447 
448 class InOutNode;
449 class InputPort;
450 class OutputPort;
451 
455 class InputPort final : public Port
456 {
457  friend InOutNode;
458 
459  explicit InputPort(InOutNode & node);
460 
461 public:
462  ~InputPort() override = default;
463 
464  const char *
465  GetIdPrefix() const override;
466 
467  Node &
468  GetNode() override;
469 
470  bool
471  CanBeEdgeTail() const override;
472 
473  void
474  SetFillColor(std::string color) override;
475 
476  void
477  OutputDotPortId(std::ostream & out) const override;
478 
479 private:
481 };
482 
486 class OutputPort final : public Port
487 {
488  friend InOutNode;
489 
490  explicit OutputPort(InOutNode & node);
491 
492 public:
493  ~OutputPort() override = default;
494 
495  const char *
496  GetIdPrefix() const override;
497 
498  Node &
499  GetNode() override;
500 
501  bool
502  CanBeEdgeHead() const override;
503 
504  void
505  SetFillColor(std::string color) override;
506 
507  void
508  OutputDotPortId(std::ostream & out) const override;
509 
510 private:
512 };
513 
519 class InOutNode final : public Node
520 {
521  friend Graph;
522 
523  InOutNode(Graph & graph, size_t inputPorts, size_t outputPorts);
524 
525 public:
526  ~InOutNode() override = default;
527 
531  void SetShape(std::string) override;
532 
533  InputPort &
534  CreateInputPort();
535 
536  size_t
537  NumInputPorts() const;
538 
539  InputPort &
540  GetInputPort(size_t index);
541 
542  OutputPort &
544 
545  size_t
546  NumOutputPorts() const;
547 
548  OutputPort &
549  GetOutputPort(size_t index);
550 
555  Graph &
556  CreateSubgraph();
557 
561  size_t
562  NumSubgraphs() const;
563 
567  Graph &
568  GetSubgraph(size_t index);
569 
578  void
579  SetHtmlTableAttribute(std::string name, std::string value);
580 
581  void
582  SetFillColor(std::string color) override;
583 
584  void
585  Finalize() override;
586 
587  void
588  OutputSubgraphs(std::ostream & out, OutputFormat format, size_t indent) const override;
589 
590 protected:
591  void
592  OutputASCII(std::ostream & out, size_t indent) const override;
593 
594  void
595  OutputDot(std::ostream & out, size_t indent) const override;
596 
597 private:
598  // Attributes that need to be placed on the HTML table in the dot output, and not on the node.
599  std::unordered_map<std::string, std::string> HtmlTableAttributes_;
600 
601  std::vector<std::unique_ptr<InputPort>> InputPorts_;
602  std::vector<std::unique_ptr<OutputPort>> OutputPorts_;
603  std::vector<Graph *> SubGraphs_;
604 };
605 
610 class ArgumentNode : public Node
611 {
612  friend Graph;
613 
614  explicit ArgumentNode(Graph & graph);
615 
616 public:
617  ~ArgumentNode() override = default;
618 
619  const char *
620  GetIdPrefix() const override;
621 
622  bool
623  CanBeEdgeHead() const override;
624 
629  void
630  SetOutsideSource(const Port & outsideSource);
631 
632 protected:
633  void
634  OutputASCII(std::ostream & out, size_t indent) const override;
635 
636 private:
637  // Optional reference to a Port outside of this graph from which this argument came
639 };
640 
645 class ResultNode : public Node
646 {
647  friend Graph;
648 
649  explicit ResultNode(Graph & graph);
650 
651 public:
652  ~ResultNode() override = default;
653 
654  const char *
655  GetIdPrefix() const override;
656 
657  bool
658  CanBeEdgeTail() const override;
659 
664  void
665  SetOutsideDestination(const Port & outsideSource);
666 
667 protected:
668  void
669  OutputASCII(std::ostream & out, size_t indent) const override;
670 
671 private:
672  // Optional reference to a Port outside of this graph representing where the result ends up
674 };
675 
676 class Edge : public GraphElement
677 {
678  friend Graph;
679 
680  Edge(Port & from, Port & to, bool directed);
681 
682 public:
683  ~Edge() override = default;
684 
685  const char *
686  GetIdPrefix() const override;
687 
688  Graph &
689  GetGraph() override;
690 
695  [[nodiscard]] Port &
696  GetFrom();
697 
702  [[nodiscard]] Port &
703  GetTo();
704 
708  [[nodiscard]] bool
709  IsDirected() const;
710 
714  [[nodiscard]] Port &
715  GetOtherEnd(const Port & end);
716 
721  void
722  SetStyle(std::string style);
723 
727  struct Style
728  {
729  static inline const char * const Solid = "solid";
730  static inline const char * const Dashed = "dashed";
731  static inline const char * const Dotted = "dotted";
732  static inline const char * const Invisible = "invis";
733  static inline const char * const Bold = "bold";
734  static inline const char * const Tapered = "tapered";
735  };
736 
745  void
746  SetArrowHead(std::string arrow);
747 
753  void
754  SetArrowTail(std::string arrow);
755 
759  void
760  OutputDot(std::ostream & out, size_t indent) const;
761 
762 private:
765  bool Directed_;
766 };
767 
768 class Graph : public GraphElement
769 {
770  friend Writer;
771  friend GraphElement;
772 
773  explicit Graph(Writer & writer);
774 
775  Graph(Writer & writer, Node & parentNode);
776 
777 public:
778  ~Graph() override = default;
779 
780  const char *
781  GetIdPrefix() const override;
782 
783  Graph &
784  GetGraph() override;
785 
786  [[nodiscard]] Writer &
787  GetWriter();
788 
789  [[nodiscard]] const Writer &
790  GetWriter() const;
791 
795  [[nodiscard]] bool
796  IsSubgraph() const;
797 
802  [[nodiscard]] Node &
803  CreateNode();
804 
811  [[nodiscard]] InOutNode &
812  CreateInOutNode(size_t inputPorts, size_t outputPorts);
813 
817  [[nodiscard]] size_t
818  NumNodes() const noexcept;
819 
825  [[nodiscard]] Node &
826  GetNode(size_t index);
827 
832  [[nodiscard]] ArgumentNode &
834 
838  [[nodiscard]] size_t
839  NumArgumentNodes() const noexcept;
840 
845  [[nodiscard]] Node &
846  GetArgumentNode(size_t index);
847 
852  [[nodiscard]] ResultNode &
854 
858  [[nodiscard]] size_t
859  NumResultNodes() const noexcept;
860 
865  [[nodiscard]] Node &
866  GetResultNode(size_t index);
867 
876  Edge &
877  CreateEdge(Port & from, Port & to, bool directed);
878 
884  Edge &
886  {
887  return CreateEdge(from, to, true);
888  }
889 
896  Edge &
898  {
899  return CreateEdge(a, b, false);
900  }
901 
905  [[nodiscard]] size_t
906  NumEdges() const noexcept;
907 
912  [[nodiscard]] Edge &
913  GetEdge(size_t index);
914 
921  [[nodiscard]] Edge *
922  GetEdgeBetween(Port & a, Port & b);
923 
930  [[nodiscard]] GraphElement *
931  GetElementFromProgramObject(uintptr_t object) const;
932 
933  template<typename T>
934  [[nodiscard]] GraphElement *
935  GetElementFromProgramObject(const T & object) const
936  {
937  // Check that object is not a reference to a pointer.
938  // If the user truly wants to use the address of a pointer, they can cast it to uintptr_t.
939  static_assert(!std::is_pointer_v<T>);
940  return GetElementFromProgramObject(reinterpret_cast<uintptr_t>(&object));
941  }
942 
950  template<typename Element, typename ProgramObject>
951  Element &
952  GetFromProgramObject(const ProgramObject & object) const
953  {
954  static_assert(std::is_base_of_v<GraphElement, Element>);
955  GraphElement * element = GetElementFromProgramObject(object);
956  auto result = dynamic_cast<Element *>(element);
957  JLM_ASSERT(result);
958  return *result;
959  }
960 
965  void
966  Finalize() override;
967 
975  void
976  Output(std::ostream & out, OutputFormat format, size_t indent = 0) const;
977 
978 private:
979  void
980  OutputASCII(std::ostream & out, size_t indent) const;
981 
982  void
983  OutputDot(std::ostream & out, size_t indent) const;
984 
990  void
992 
997  void
998  RemoveProgramObjectMapping(uintptr_t object);
999 
1000  // The GraphWriter this graph was created by, and belongs to
1002 
1003  // If this graph is a subgraph, this is its parent node in the parent graph.
1004  // For top level graphs, this field is nullptr
1006 
1007  // The set of nodes in the graph. Finalizing the graph may re-order this list.
1008  std::vector<std::unique_ptr<Node>> Nodes_;
1009 
1010  // Argument nodes and result nodes are kept in separate lists
1011  std::vector<std::unique_ptr<ArgumentNode>> ArgumentNodes_;
1012  std::vector<std::unique_ptr<ResultNode>> ResultNodes_;
1013 
1014  std::vector<std::unique_ptr<Edge>> Edges_;
1015 
1016  // A mapping from pointers to program objects, to the GraphElement representing the program object
1017  std::unordered_map<uintptr_t, GraphElement *> ProgramObjectMapping_;
1018 };
1019 
1024 class Writer
1025 {
1026 public:
1027  ~Writer() = default;
1028 
1029  Writer() = default;
1030 
1031  Writer(const Writer & other) = delete;
1032 
1033  Writer(Writer && other) = delete;
1034 
1035  Writer &
1036  operator=(const Writer & other) = delete;
1037 
1038  Writer &
1039  operator=(Writer && other) = delete;
1040 
1045  [[nodiscard]] Graph &
1046  CreateGraph();
1047 
1051  [[nodiscard]] size_t
1052  NumGraphs() const noexcept;
1053 
1057  [[nodiscard]] Graph &
1058  GetGraph(size_t index);
1059 
1064  [[nodiscard]] GraphElement *
1065  GetElementFromProgramObject(uintptr_t object) const;
1066 
1067  template<typename T>
1068  [[nodiscard]] GraphElement *
1069  GetElementFromProgramObject(const T & object) const
1070  {
1071  // Check that object is not a reference to a pointer.
1072  // If the user truly wants to use the address of a pointer, they can cast it to uintptr_t.
1073  static_assert(!std::is_pointer_v<T>);
1074  return GetElementFromProgramObject(reinterpret_cast<uintptr_t>(&object));
1075  }
1076 
1081  void
1082  Finalize();
1083 
1089  void
1090  outputAllGraphs(std::ostream & out, OutputFormat format);
1091 
1092 private:
1093  [[nodiscard]] Graph &
1094  CreateSubGraph(Node & parentNode);
1095 
1096  friend Graph &
1098 
1103  [[nodiscard]] size_t
1104  GetNextUniqueIdStubSuffix(const char * idStub);
1105 
1106  friend void
1108 
1109  // All graphs being worked on by the GraphWriter
1110  // Edges can not go across graphs.
1111  // IDs are however unique across graphs allowing semantic connections.
1112  std::vector<std::unique_ptr<Graph>> Graphs_;
1113 
1114  // Tracks the next integer to be used when assigning a unique suffix to a given id stub
1115  std::unordered_map<std::string, size_t> NextUniqueIdStubSuffix_;
1116 };
1117 
1122 namespace Colors
1123 {
1124 inline const char * const Black = "#000000";
1125 inline const char * const Blue = "#0000FF";
1126 inline const char * const Coral = "#FF7F50";
1127 inline const char * const CornflowerBlue = "#6495ED";
1128 inline const char * const Firebrick = " #B22222";
1129 inline const char * const Gold = "#FFD700";
1130 inline const char * const Gray = "#BEBEBE";
1131 inline const char * const Green = "#00FF00";
1132 inline const char * const Orange = "#FFA500";
1133 inline const char * const Purple = "#A020F0";
1134 inline const char * const Red = "#FF0000";
1135 inline const char * const Brown = "#8B4513"; // X11's Saddle Brown
1136 inline const char * const SkyBlue = "#87CEEB";
1137 inline const char * const White = "#FFFFFF";
1138 inline const char * const Yellow = "#FFFF00";
1139 }
1140 
1141 }
1142 #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
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 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
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_
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)
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
void Output(std::ostream &out, OutputFormat format, size_t indent=0) const
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
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 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 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
void Output(std::ostream &out, OutputFormat format, size_t indent) const
virtual void OutputASCII(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
~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