LCOV - code coverage report
Current view: top level - gcc - digraph.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 98.6 % 71 70
Test Date: 2026-02-28 14:20:25 Functions: 75.0 % 44 33
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Template classes for directed graphs.
       2              :    Copyright (C) 2019-2026 Free Software Foundation, Inc.
       3              :    Contributed by David Malcolm <dmalcolm@redhat.com>.
       4              : 
       5              : This file is part of GCC.
       6              : 
       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)
      10              : any later version.
      11              : 
      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.
      16              : 
      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/>.  */
      20              : 
      21              : #ifndef GCC_DIGRAPH_H
      22              : #define GCC_DIGRAPH_H
      23              : 
      24              : #include "diagnostic.h"
      25              : #include "tree-diagnostic.h" /* for default_tree_printer.  */
      26              : #include "graphviz.h"
      27              : 
      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).
      34              : 
      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.  */
      38              : 
      39              : /* Abstract base class for a node in a directed graph.  */
      40              : 
      41              : template <typename GraphTraits>
      42       879820 : class dnode
      43              : {
      44              :  public:
      45              :   typedef typename GraphTraits::edge_t edge_t;
      46              :   typedef typename GraphTraits::dump_args_t dump_args_t;
      47              : 
      48       879820 :   virtual ~dnode () {}
      49              :   virtual void dump_dot (graphviz_out *gv, const dump_args_t &args) const = 0;
      50              : 
      51         5812 :   void add_in_edge (edge_t *e)
      52              :   {
      53         5812 :     m_preds.safe_push (e);
      54              :   }
      55        11126 :   void remove_in_edge (edge_t *e)
      56              :   {
      57        11126 :     m_preds.unordered_remove (find_edge_idx (m_preds, e));
      58        11126 :   }
      59              :   void add_out_edge (edge_t *e)
      60              :   {
      61              :     m_succs.safe_push (e);
      62              :   }
      63         5314 :   void remove_out_edge (edge_t *e)
      64              :   {
      65         5314 :     m_succs.unordered_remove (find_edge_idx (m_succs, e));
      66         5314 :   }
      67              : 
      68              : public:
      69              :   auto_vec<edge_t *> m_preds;
      70              :   auto_vec<edge_t *> m_succs;
      71              : 
      72              : private:
      73              :   static unsigned
      74        16440 :   find_edge_idx (auto_vec<edge_t *> &edges, edge_t *e)
      75              :   {
      76        17018 :     for (unsigned i = 0; i < edges.length (); ++i)
      77        17018 :       if (edges[i] == e)
      78        16440 :         return i;
      79            0 :     gcc_unreachable ();
      80              :   }
      81              : };
      82              : 
      83              : /* Abstract base class for an edge in a directed graph.  */
      84              : 
      85              : template <typename GraphTraits>
      86              : class dedge
      87              : {
      88              :  public:
      89              :   typedef typename GraphTraits::node_t node_t;
      90              :   typedef typename GraphTraits::edge_t edge_t;
      91              :   typedef typename GraphTraits::dump_args_t dump_args_t;
      92              : 
      93       886916 :   dedge (node_t *src, node_t *dest)
      94       886916 :   : m_src (src), m_dest (dest) {}
      95              : 
      96       187243 :   virtual ~dedge () {}
      97              : 
      98              :   virtual void dump_dot (graphviz_out *gv, const dump_args_t &args) const = 0;
      99              : 
     100         5812 :   void set_dest (node_t *new_dest)
     101              :   {
     102         5812 :     node_t *old_dest = m_dest;
     103         5812 :     if (new_dest != old_dest)
     104              :       {
     105         5812 :         old_dest->remove_in_edge (static_cast<edge_t *> (this));
     106         5812 :         m_dest = new_dest;
     107         5812 :         new_dest->add_in_edge (static_cast<edge_t *> (this));
     108              :       }
     109         5812 :   }
     110              : 
     111              :   node_t *m_src;
     112              :   node_t *m_dest;
     113              : };
     114              : 
     115              : /* Abstract base class for a directed graph.
     116              :    This class maintains the vectors of nodes and edges,
     117              :    and owns the nodes and edges.  */
     118              : 
     119              : template <typename GraphTraits>
     120              : class digraph
     121              : {
     122              :  public:
     123              :   typedef typename GraphTraits::node_t node_t;
     124              :   typedef typename GraphTraits::edge_t edge_t;
     125              :   typedef typename GraphTraits::dump_args_t dump_args_t;
     126              :   typedef typename GraphTraits::cluster_t cluster_t;
     127              : 
     128        19504 :   digraph () {}
     129        19504 :   virtual ~digraph () {}
     130              : 
     131              :   void dump_dot_to_pp (pretty_printer *pp,
     132              :                        cluster_t *root_cluster,
     133              :                        const dump_args_t &args) const;
     134              :   void dump_dot_to_file (FILE *fp,
     135              :                          cluster_t *root_cluster,
     136              :                          const dump_args_t &args) const;
     137              :   void dump_dot (const char *path,
     138              :                  cluster_t *root_cluster,
     139              :                  const dump_args_t &args) const;
     140              : 
     141              :   void add_node (node_t *node);
     142              :   void add_edge (edge_t *edge);
     143              : 
     144              :   virtual void
     145           16 :   add_any_extra_stmts (graphviz_out &) const
     146              :   {
     147              :     // no-op hook
     148           16 :   }
     149              : 
     150              :   auto_delete_vec<node_t> m_nodes;
     151              :   auto_delete_vec<edge_t> m_edges;
     152              : };
     153              : 
     154              : /* Abstract base class for splitting dnodes into hierarchical clusters
     155              :    in the generated .dot file.
     156              : 
     157              :    See "Subgraphs and Clusters" within
     158              :      https://www.graphviz.org/doc/info/lang.html
     159              :    and e.g.
     160              :      https://graphviz.gitlab.io/_pages/Gallery/directed/cluster.html
     161              : 
     162              :    If a root_cluster is passed to dump_dot*, then all nodes will be
     163              :    added to it at the start of dumping, via calls to add_node.
     164              : 
     165              :    The root cluster can organize the nodes into a hierarchy of
     166              :    child clusters.
     167              : 
     168              :    After all nodes are added to the root cluster, dump_dot will then
     169              :    be called on it (and not on the nodes themselves).  */
     170              : 
     171              : template <typename GraphTraits>
     172          858 : class cluster
     173              : {
     174              :  public:
     175              :   typedef typename GraphTraits::node_t node_t;
     176              :   typedef typename GraphTraits::dump_args_t dump_args_t;
     177              : 
     178            4 :   virtual ~cluster () {}
     179              : 
     180              :   virtual void add_node (node_t *node) = 0;
     181              : 
     182              :   /* Recursively dump the cluster, all nodes, and child clusters.  */
     183              :   virtual void dump_dot (graphviz_out *gv, const dump_args_t &) const = 0;
     184              : };
     185              : 
     186              : /* Write .dot information for this graph to PP, passing ARGS to the nodes
     187              :    and edges.
     188              :    If ROOT_CLUSTER is non-NULL, use it to organize the nodes into clusters.  */
     189              : 
     190              : template <typename GraphTraits>
     191              : inline void
     192           16 : digraph<GraphTraits>::dump_dot_to_pp (pretty_printer *pp,
     193              :                                       cluster_t *root_cluster,
     194              :                                       const dump_args_t &args) const
     195              : {
     196           16 :   graphviz_out gv (pp);
     197              : 
     198           16 :   pp_string (pp, "digraph \"");
     199           16 :   pp_string (pp, "base");
     200           16 :   pp_string (pp, "\" {\n");
     201              : 
     202           16 :   gv.indent ();
     203              : 
     204           16 :   pp_string (pp, "overlap=false;\n");
     205           16 :   pp_string (pp, "compound=true;\n");
     206              : 
     207              :   /* If using clustering, emit all nodes via clusters.  */
     208           16 :   if (root_cluster)
     209              :     {
     210              :       int i;
     211              :       node_t *n;
     212          437 :       FOR_EACH_VEC_ELT (m_nodes, i, n)
     213          433 :         root_cluster->add_node (n);
     214            4 :       root_cluster->dump_dot (&gv, args);
     215              :     }
     216              :   else
     217              :     {
     218              :       /* Otherwise, display all nodes at top level.  */
     219              :       int i;
     220              :       node_t *n;
     221          168 :       FOR_EACH_VEC_ELT (m_nodes, i, n)
     222          156 :         n->dump_dot (&gv, args);
     223              :     }
     224              : 
     225              :   /* Edges.  */
     226              :   int i;
     227              :   edge_t *e;
     228          605 :   FOR_EACH_VEC_ELT (m_edges, i, e)
     229          589 :     e->dump_dot (&gv, args);
     230              : 
     231           16 :   add_any_extra_stmts (gv);
     232              : 
     233              :   /* Terminate "digraph" */
     234           16 :   gv.outdent ();
     235           16 :   pp_string (pp, "}");
     236           16 :   pp_newline (pp);
     237           16 : }
     238              : 
     239              : /* Write .dot information for this graph to FP, passing ARGS to the nodes
     240              :    and edges.
     241              :    If ROOT_CLUSTER is non-NULL, use it to organize the nodes into clusters.  */
     242              : 
     243              : template <typename GraphTraits>
     244              : inline void
     245           12 : digraph<GraphTraits>::dump_dot_to_file (FILE *fp,
     246              :                                         cluster_t *root_cluster,
     247              :                                         const dump_args_t &args) const
     248              : {
     249           12 :   pretty_printer pp;
     250              :   // TODO:
     251           12 :   pp_format_decoder (&pp) = default_tree_printer;
     252           12 :   pp.set_output_stream (fp);
     253           12 :   dump_dot_to_pp (&pp, root_cluster, args);
     254           12 :   pp_flush (&pp);
     255           12 : }
     256              : 
     257              : /* Write .dot information for this graph to a file at PATH, passing ARGS
     258              :    to the nodes and edges.
     259              :    If ROOT_CLUSTER is non-NULL, use it to organize the nodes into clusters.  */
     260              : 
     261              : template <typename GraphTraits>
     262              : inline void
     263           12 : digraph<GraphTraits>::dump_dot (const char *path,
     264              :                                 cluster_t *root_cluster,
     265              :                                 const dump_args_t &args) const
     266              : {
     267           12 :   FILE *fp = fopen (path, "w");
     268           12 :   dump_dot_to_file (fp, root_cluster, args);
     269           12 :   fclose (fp);
     270           12 : }
     271              : 
     272              : /* Add NODE to this DIGRAPH, taking ownership.  */
     273              : 
     274              : template <typename GraphTraits>
     275              : inline void
     276       692166 : digraph<GraphTraits>::add_node (node_t *node)
     277              : {
     278       692166 :   m_nodes.safe_push (node);
     279              : }
     280              : 
     281              : /* Add EDGE to this digraph, and to the preds/succs of its endpoints.
     282              :    Take ownership of EDGE.  */
     283              : 
     284              : template <typename GraphTraits>
     285              : inline void
     286       886916 : digraph<GraphTraits>::add_edge (edge_t *edge)
     287              : {
     288       886916 :   m_edges.safe_push (edge);
     289       886916 :   edge->m_dest->m_preds.safe_push (edge);
     290       886916 :   edge->m_src->m_succs.safe_push (edge);
     291              : 
     292       886916 : }
     293              : 
     294              : #endif /* GCC_DIGRAPH_H */
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.