1 /* Template classes for directed graphs.
2 Copyright (C) 2019-2020 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
24 #include "diagnostic.h"
25 #include "tree-diagnostic.h" /* for default_tree_printer. */
28 /* Templates for a family of classes: digraph, node, edge, and cluster.
29 This assumes a traits type with the following typedefs:
30 node_t: the node class
31 edge_t: the edge class
32 dump_args_t: additional args for dot-dumps
33 cluster_t: the cluster class (for use when generating .dot files).
35 Using a template allows for typesafe nodes and edges: a node's
36 predecessor and successor edges can be of a node-specific edge
37 subclass, without needing casting. */
39 /* Abstract base class for a node in a directed graph. */
41 template <typename GraphTraits
>
45 typedef typename
GraphTraits::edge_t edge_t
;
46 typedef typename
GraphTraits::dump_args_t dump_args_t
;
49 virtual void dump_dot (graphviz_out
*gv
, const dump_args_t
&args
) const = 0;
51 auto_vec
<edge_t
*> m_preds
;
52 auto_vec
<edge_t
*> m_succs
;
55 /* Abstract base class for an edge in a directed graph. */
57 template <typename GraphTraits
>
61 typedef typename
GraphTraits::node_t node_t
;
62 typedef typename
GraphTraits::dump_args_t dump_args_t
;
64 dedge (node_t
*src
, node_t
*dest
)
65 : m_src (src
), m_dest (dest
) {}
69 virtual void dump_dot (graphviz_out
*gv
, const dump_args_t
&args
) const = 0;
75 /* Abstract base class for a directed graph.
76 This class maintains the vectors of nodes and edges,
77 and owns the nodes and edges. */
79 template <typename GraphTraits
>
83 typedef typename
GraphTraits::node_t node_t
;
84 typedef typename
GraphTraits::edge_t edge_t
;
85 typedef typename
GraphTraits::dump_args_t dump_args_t
;
86 typedef typename
GraphTraits::cluster_t cluster_t
;
89 virtual ~digraph () {}
91 void dump_dot_to_pp (pretty_printer
*pp
,
92 cluster_t
*root_cluster
,
93 const dump_args_t
&args
) const;
94 void dump_dot_to_file (FILE *fp
,
95 cluster_t
*root_cluster
,
96 const dump_args_t
&args
) const;
97 void dump_dot (const char *path
,
98 cluster_t
*root_cluster
,
99 const dump_args_t
&args
) const;
101 void add_node (node_t
*node
);
102 void add_edge (edge_t
*edge
);
104 auto_delete_vec
<node_t
> m_nodes
;
105 auto_delete_vec
<edge_t
> m_edges
;
108 /* Abstract base class for splitting dnodes into hierarchical clusters
109 in the generated .dot file.
111 See "Subgraphs and Clusters" within
112 https://www.graphviz.org/doc/info/lang.html
114 https://graphviz.gitlab.io/_pages/Gallery/directed/cluster.html
116 If a root_cluster is passed to dump_dot*, then all nodes will be
117 added to it at the start of dumping, via calls to add_node.
119 The root cluster can organize the nodes into a hierarchy of
122 After all nodes are added to the root cluster, dump_dot will then
123 be called on it (and not on the nodes themselves). */
125 template <typename GraphTraits
>
129 typedef typename
GraphTraits::node_t node_t
;
130 typedef typename
GraphTraits::dump_args_t dump_args_t
;
132 virtual ~cluster () {}
134 virtual void add_node (node_t
*node
) = 0;
136 /* Recursively dump the cluster, all nodes, and child clusters. */
137 virtual void dump_dot (graphviz_out
*gv
, const dump_args_t
&) const = 0;
140 /* Write .dot information for this graph to PP, passing ARGS to the nodes
142 If ROOT_CLUSTER is non-NULL, use it to organize the nodes into clusters. */
144 template <typename GraphTraits
>
146 digraph
<GraphTraits
>::dump_dot_to_pp (pretty_printer
*pp
,
147 cluster_t
*root_cluster
,
148 const dump_args_t
&args
) const
150 graphviz_out
gv (pp
);
152 pp_string (pp
, "digraph \"");
153 pp_string (pp
, "base");
154 pp_string (pp
, "\" {\n");
158 pp_string (pp
, "overlap=false;\n");
159 pp_string (pp
, "compound=true;\n");
161 /* If using clustering, emit all nodes via clusters. */
166 FOR_EACH_VEC_ELT (m_nodes
, i
, n
)
167 root_cluster
->add_node (n
);
168 root_cluster
->dump_dot (&gv
, args
);
172 /* Otherwise, display all nodes at top level. */
175 FOR_EACH_VEC_ELT (m_nodes
, i
, n
)
176 n
->dump_dot (&gv
, args
);
182 FOR_EACH_VEC_ELT (m_edges
, i
, e
)
183 e
->dump_dot (&gv
, args
);
185 /* Terminate "digraph" */
191 /* Write .dot information for this graph to FP, passing ARGS to the nodes
193 If ROOT_CLUSTER is non-NULL, use it to organize the nodes into clusters. */
195 template <typename GraphTraits
>
197 digraph
<GraphTraits
>::dump_dot_to_file (FILE *fp
,
198 cluster_t
*root_cluster
,
199 const dump_args_t
&args
) const
203 pp_format_decoder (&pp
) = default_tree_printer
;
204 pp
.buffer
->stream
= fp
;
205 dump_dot_to_pp (&pp
, root_cluster
, args
);
209 /* Write .dot information for this graph to a file at PATH, passing ARGS
210 to the nodes and edges.
211 If ROOT_CLUSTER is non-NULL, use it to organize the nodes into clusters. */
213 template <typename GraphTraits
>
215 digraph
<GraphTraits
>::dump_dot (const char *path
,
216 cluster_t
*root_cluster
,
217 const dump_args_t
&args
) const
219 FILE *fp
= fopen (path
, "w");
220 dump_dot_to_file (fp
, root_cluster
, args
);
224 /* Add NODE to this DIGRAPH, taking ownership. */
226 template <typename GraphTraits
>
228 digraph
<GraphTraits
>::add_node (node_t
*node
)
230 m_nodes
.safe_push (node
);
233 /* Add EDGE to this digraph, and to the preds/succs of its endpoints.
234 Take ownership of EDGE. */
236 template <typename GraphTraits
>
238 digraph
<GraphTraits
>::add_edge (edge_t
*edge
)
240 m_edges
.safe_push (edge
);
241 edge
->m_dest
->m_preds
.safe_push (edge
);
242 edge
->m_src
->m_succs
.safe_push (edge
);
246 #endif /* GCC_DIGRAPH_H */