LCOV - code coverage report
Current view: top level - gcc/analyzer - supergraph.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 86.2 % 152 131
Test Date: 2025-06-21 16:26:05 Functions: 57.6 % 33 19
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* "Supergraph" classes that combine CFGs and callgraph into one digraph.
       2                 :             :    Copyright (C) 2019-2025 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_ANALYZER_SUPERGRAPH_H
      22                 :             : #define GCC_ANALYZER_SUPERGRAPH_H
      23                 :             : 
      24                 :             : #include "ordered-hash-map.h"
      25                 :             : #include "cfg.h"
      26                 :             : #include "basic-block.h"
      27                 :             : #include "gimple.h"
      28                 :             : #include "gimple-iterator.h"
      29                 :             : #include "digraph.h"
      30                 :             : #include "except.h"
      31                 :             : 
      32                 :             : using namespace ana;
      33                 :             : 
      34                 :             : namespace ana {
      35                 :             : 
      36                 :             : /* Forward decls, using indentation to show inheritance.  */
      37                 :             : 
      38                 :             : class supergraph;
      39                 :             : class supernode;
      40                 :             : class superedge;
      41                 :             :   class callgraph_superedge;
      42                 :             :     class call_superedge;
      43                 :             :     class return_superedge;
      44                 :             :   class cfg_superedge;
      45                 :             :     class switch_cfg_superedge;
      46                 :             :     class eh_dispatch_cfg_superedge;
      47                 :             :       class eh_dispatch_try_cfg_superedge;
      48                 :             :       class eh_dispatch_allowed_cfg_superedge;
      49                 :             : class supercluster;
      50                 :             : class dot_annotator;
      51                 :             : 
      52                 :             : class logger;
      53                 :             : 
      54                 :             : /* An enum for discriminating between superedge subclasses.  */
      55                 :             : 
      56                 :             : enum edge_kind
      57                 :             : {
      58                 :             :   SUPEREDGE_CFG_EDGE,
      59                 :             :   SUPEREDGE_CALL,
      60                 :             :   SUPEREDGE_RETURN,
      61                 :             :   SUPEREDGE_INTRAPROCEDURAL_CALL
      62                 :             : };
      63                 :             : 
      64                 :             : /* Flags for controlling the appearance of .dot dumps.  */
      65                 :             : 
      66                 :             : enum supergraph_dot_flags
      67                 :             : {
      68                 :             :   SUPERGRAPH_DOT_SHOW_BBS = (1 << 0)
      69                 :             : };
      70                 :             : 
      71                 :             : /* A traits struct describing the family of node, edge and digraph
      72                 :             :    classes for supergraphs.  */
      73                 :             : 
      74                 :             : struct supergraph_traits
      75                 :             : {
      76                 :             :   typedef supernode node_t;
      77                 :             :   typedef superedge edge_t;
      78                 :             :   typedef supergraph graph_t;
      79                 :             :   struct dump_args_t
      80                 :             :   {
      81                 :          12 :     dump_args_t (enum supergraph_dot_flags flags,
      82                 :             :                  const dot_annotator *node_annotator)
      83                 :          12 :     : m_flags (flags),
      84                 :          12 :       m_node_annotator (node_annotator)
      85                 :             :     {}
      86                 :             : 
      87                 :             :     enum supergraph_dot_flags m_flags;
      88                 :             :     const dot_annotator *m_node_annotator;
      89                 :             :   };
      90                 :             :   typedef supercluster cluster_t;
      91                 :             : };
      92                 :             : 
      93                 :             : /* A class to manage the setting and restoring of statement uids.  */
      94                 :             : 
      95                 :        6626 : class saved_uids
      96                 :             : {
      97                 :             : public:
      98                 :             :   void make_uid_unique (gimple *stmt);
      99                 :             :   void restore_uids () const;
     100                 :             : 
     101                 :             : private:
     102                 :             :   auto_vec<std::pair<gimple *, unsigned> > m_old_stmt_uids;
     103                 :             : };
     104                 :             : 
     105                 :             : /* A "supergraph" is a directed graph formed by joining together all CFGs,
     106                 :             :    linking them via interprocedural call and return edges.
     107                 :             : 
     108                 :             :    Basic blocks are split at callsites, so that a call statement occurs
     109                 :             :    twice: once at the end of a supernode, and a second instance at the
     110                 :             :    start of the next supernode (to handle the return).  */
     111                 :             : 
     112                 :             : class supergraph : public digraph<supergraph_traits>
     113                 :             : {
     114                 :             : public:
     115                 :             :   supergraph (logger *logger);
     116                 :             :   ~supergraph ();
     117                 :             : 
     118                 :       10088 :   supernode *get_node_for_function_entry (const function &fun) const
     119                 :             :   {
     120                 :       20176 :     return get_node_for_block (ENTRY_BLOCK_PTR_FOR_FN (&fun));
     121                 :             :   }
     122                 :             : 
     123                 :         150 :   supernode *get_node_for_function_exit (const function &fun) const
     124                 :             :   {
     125                 :         300 :     return get_node_for_block (EXIT_BLOCK_PTR_FOR_FN (&fun));
     126                 :             :   }
     127                 :             : 
     128                 :       10238 :   supernode *get_node_for_block (basic_block bb) const
     129                 :             :   {
     130                 :       10238 :     return *const_cast <bb_to_node_t &> (m_bb_to_initial_node).get (bb);
     131                 :             :   }
     132                 :             : 
     133                 :             :   /* Get the supernode containing the second half of the gcall &
     134                 :             :      at an interprocedural call, within the caller.  */
     135                 :             :   supernode *get_caller_next_node (cgraph_edge *edge) const
     136                 :             :   {
     137                 :             :     return (*const_cast <cgraph_edge_to_node_t &>
     138                 :             :               (m_cgraph_edge_to_caller_next_node).get (edge));
     139                 :             :   }
     140                 :             : 
     141                 :             :   call_superedge *get_edge_for_call (cgraph_edge *edge) const
     142                 :             :   {
     143                 :             :     return (*const_cast <cgraph_edge_to_call_superedge_t &>
     144                 :             :               (m_cgraph_edge_to_call_superedge).get (edge));
     145                 :             :   }
     146                 :             : 
     147                 :        6690 :   return_superedge *get_edge_for_return (cgraph_edge *edge) const
     148                 :             :   {
     149                 :        6690 :     return (*const_cast <cgraph_edge_to_return_superedge_t &>
     150                 :       13380 :               (m_cgraph_edge_to_return_superedge).get (edge));
     151                 :             :   }
     152                 :             : 
     153                 :        5022 :   superedge *get_intraprocedural_edge_for_call (cgraph_edge *edge) const
     154                 :             :   {
     155                 :        5022 :     return (*const_cast <cgraph_edge_to_intraproc_superedge_t &>
     156                 :        5022 :               (m_cgraph_edge_to_intraproc_superedge).get (edge));
     157                 :             :   }
     158                 :             : 
     159                 :       10430 :   cfg_superedge *get_edge_for_cfg_edge (edge e) const
     160                 :             :   {
     161                 :       10430 :     return (*const_cast <cfg_edge_to_cfg_superedge_t &>
     162                 :       10430 :               (m_cfg_edge_to_cfg_superedge).get (e));
     163                 :             :   }
     164                 :             : 
     165                 :      498560 :   supernode *get_supernode_for_stmt (const gimple *stmt) const
     166                 :             :   {
     167                 :      498560 :     return (*const_cast <stmt_to_node_t &>(m_stmt_to_node_t).get
     168                 :      498560 :             (const_cast <gimple *> (stmt)));
     169                 :             :   }
     170                 :             : 
     171                 :             :   void dump_dot_to_pp (pretty_printer *pp, const dump_args_t &) const;
     172                 :             :   void dump_dot_to_file (FILE *fp, const dump_args_t &) const;
     173                 :             :   void dump_dot (const char *path, const dump_args_t &) const;
     174                 :             : 
     175                 :             :   std::unique_ptr<json::object> to_json () const;
     176                 :             : 
     177                 :     1117789 :   int num_nodes () const { return m_nodes.length (); }
     178                 :             :   int num_edges () const { return m_edges.length (); }
     179                 :             : 
     180                 :       61747 :   supernode *get_node_by_index (int idx) const
     181                 :             :   {
     182                 :       61747 :     return m_nodes[idx];
     183                 :             :   }
     184                 :             : 
     185                 :        8365 :   unsigned get_num_snodes (const function *fun) const
     186                 :             :   {
     187                 :        8365 :     function_to_num_snodes_t &map
     188                 :             :       = const_cast <function_to_num_snodes_t &>(m_function_to_num_snodes);
     189                 :        8365 :     return *map.get (fun);
     190                 :             :   }
     191                 :             : 
     192                 :             : private:
     193                 :             :   supernode *add_node (function *fun, basic_block bb, gcall *returning_call,
     194                 :             :                        gimple_seq phi_nodes);
     195                 :             :   cfg_superedge *add_cfg_edge (supernode *src, supernode *dest, ::edge e);
     196                 :             :   call_superedge *add_call_superedge (supernode *src, supernode *dest,
     197                 :             :                                       cgraph_edge *cedge);
     198                 :             :   return_superedge *add_return_superedge (supernode *src, supernode *dest,
     199                 :             :                                           cgraph_edge *cedge);
     200                 :             : 
     201                 :             :   /* Data.  */
     202                 :             : 
     203                 :             :   typedef ordered_hash_map<basic_block, supernode *> bb_to_node_t;
     204                 :             :   bb_to_node_t m_bb_to_initial_node;
     205                 :             :   bb_to_node_t m_bb_to_final_node;
     206                 :             : 
     207                 :             :   typedef ordered_hash_map<cgraph_edge *, supernode *> cgraph_edge_to_node_t;
     208                 :             :   cgraph_edge_to_node_t m_cgraph_edge_to_caller_prev_node;
     209                 :             :   cgraph_edge_to_node_t m_cgraph_edge_to_caller_next_node;
     210                 :             : 
     211                 :             :   typedef ordered_hash_map< ::edge, cfg_superedge *>
     212                 :             :     cfg_edge_to_cfg_superedge_t;
     213                 :             :   cfg_edge_to_cfg_superedge_t m_cfg_edge_to_cfg_superedge;
     214                 :             : 
     215                 :             :   typedef ordered_hash_map<cgraph_edge *, call_superedge *>
     216                 :             :     cgraph_edge_to_call_superedge_t;
     217                 :             :   cgraph_edge_to_call_superedge_t m_cgraph_edge_to_call_superedge;
     218                 :             : 
     219                 :             :   typedef ordered_hash_map<cgraph_edge *, return_superedge *>
     220                 :             :     cgraph_edge_to_return_superedge_t;
     221                 :             :   cgraph_edge_to_return_superedge_t m_cgraph_edge_to_return_superedge;
     222                 :             : 
     223                 :             :   typedef ordered_hash_map<cgraph_edge *, superedge *>
     224                 :             :     cgraph_edge_to_intraproc_superedge_t;
     225                 :             :   cgraph_edge_to_intraproc_superedge_t m_cgraph_edge_to_intraproc_superedge;
     226                 :             : 
     227                 :             :   typedef ordered_hash_map<gimple *, supernode *> stmt_to_node_t;
     228                 :             :   stmt_to_node_t m_stmt_to_node_t;
     229                 :             : 
     230                 :             :   typedef hash_map<const function *, unsigned> function_to_num_snodes_t;
     231                 :             :   function_to_num_snodes_t m_function_to_num_snodes;
     232                 :             : 
     233                 :             :   saved_uids m_stmt_uids;
     234                 :             : };
     235                 :             : 
     236                 :             : /* A node within a supergraph.  */
     237                 :             : 
     238                 :             : class supernode : public dnode<supergraph_traits>
     239                 :             : {
     240                 :             :  public:
     241                 :       61734 :   supernode (function *fun, basic_block bb, gcall *returning_call,
     242                 :             :              gimple_seq phi_nodes, int index)
     243                 :       61734 :   : m_fun (fun), m_bb (bb), m_returning_call (returning_call),
     244                 :       61734 :     m_phi_nodes (phi_nodes), m_index (index)
     245                 :             :   {}
     246                 :             : 
     247                 :     2337445 :   function *get_function () const { return m_fun; }
     248                 :             : 
     249                 :      175298 :   bool entry_p () const
     250                 :             :   {
     251                 :      175298 :     return m_bb == ENTRY_BLOCK_PTR_FOR_FN (m_fun);
     252                 :             :   }
     253                 :             : 
     254                 :      135541 :   bool return_p () const
     255                 :             :   {
     256                 :      135541 :     return m_bb == EXIT_BLOCK_PTR_FOR_FN (m_fun);
     257                 :             :   }
     258                 :             : 
     259                 :             :   void dump_dot (graphviz_out *gv, const dump_args_t &args) const override;
     260                 :             :   void dump_dot_id (pretty_printer *pp) const;
     261                 :             : 
     262                 :             :   std::unique_ptr<json::object> to_json () const;
     263                 :             : 
     264                 :             :   location_t get_start_location () const;
     265                 :             :   location_t get_end_location () const;
     266                 :             : 
     267                 :             :   /* Returns iterator at the start of the list of phi nodes, if any.  */
     268                 :      256710 :   gphi_iterator start_phis ()
     269                 :             :   {
     270                 :      256710 :     gimple_seq *pseq = &m_phi_nodes;
     271                 :             : 
     272                 :             :     /* Adapted from gsi_start_1. */
     273                 :      256710 :     gphi_iterator i;
     274                 :             : 
     275                 :      256710 :     i.ptr = gimple_seq_first (*pseq);
     276                 :      256710 :     i.seq = pseq;
     277                 :      256710 :     i.bb = i.ptr ? gimple_bb (i.ptr) : NULL;
     278                 :             : 
     279                 :      256710 :     return i;
     280                 :             :   }
     281                 :             : 
     282                 :          67 :   gcall *get_returning_call () const
     283                 :             :   {
     284                 :          67 :     return m_returning_call;
     285                 :             :   }
     286                 :             : 
     287                 :      493803 :   gimple *get_last_stmt () const
     288                 :             :   {
     289                 :      493803 :     if (m_stmts.length () == 0)
     290                 :             :       return NULL;
     291                 :      384311 :     return m_stmts[m_stmts.length () - 1];
     292                 :             :   }
     293                 :             : 
     294                 :        1403 :   gcall *get_final_call () const
     295                 :             :   {
     296                 :        1403 :     gimple *stmt = get_last_stmt ();
     297                 :        1403 :     if (stmt == NULL)
     298                 :             :       return NULL;
     299                 :        1403 :     return dyn_cast<gcall *> (stmt);
     300                 :             :   }
     301                 :             : 
     302                 :             :   unsigned int get_stmt_index (const gimple *stmt) const;
     303                 :             : 
     304                 :             :   tree get_label () const;
     305                 :             : 
     306                 :             :   function * const m_fun; // alternatively could be stored as runs of indices within the supergraph
     307                 :             :   const basic_block m_bb;
     308                 :             :   gcall * const m_returning_call; // for handling the result of a returned call
     309                 :             :   gimple_seq m_phi_nodes; // ptr to that of the underlying BB, for the first supernode for the BB
     310                 :             :   auto_vec<gimple *> m_stmts;
     311                 :             :   const int m_index; /* unique within the supergraph as a whole.  */
     312                 :             : };
     313                 :             : 
     314                 :             : /* An abstract base class encapsulating an edge within a supergraph.
     315                 :             :    Edges can be CFG edges, or calls/returns for callgraph edges.  */
     316                 :             : 
     317                 :             : class superedge : public dedge<supergraph_traits>
     318                 :             : {
     319                 :             :  public:
     320                 :             :   virtual ~superedge () {}
     321                 :             : 
     322                 :             :   void dump (pretty_printer *pp) const;
     323                 :             :   void dump () const;
     324                 :             :   void dump_dot (graphviz_out *gv, const dump_args_t &args)
     325                 :             :     const final override;
     326                 :             : 
     327                 :             :   virtual void dump_label_to_pp (pretty_printer *pp,
     328                 :             :                                  bool user_facing) const = 0;
     329                 :             : 
     330                 :             :   std::unique_ptr<json::object> to_json () const;
     331                 :             : 
     332                 :      754893 :   enum edge_kind get_kind () const { return m_kind; }
     333                 :             : 
     334                 :       34976 :   virtual cfg_superedge *dyn_cast_cfg_superedge () { return NULL; }
     335                 :       15332 :   virtual const cfg_superedge *dyn_cast_cfg_superedge () const { return NULL; }
     336                 :         129 :   virtual const switch_cfg_superedge *dyn_cast_switch_cfg_superedge () const { return NULL; }
     337                 :           0 :   virtual const eh_dispatch_cfg_superedge *dyn_cast_eh_dispatch_cfg_superedge () const { return nullptr; }
     338                 :       10782 :   virtual const eh_dispatch_try_cfg_superedge *dyn_cast_eh_dispatch_try_cfg_superedge () const { return nullptr; }
     339                 :           0 :   virtual const eh_dispatch_allowed_cfg_superedge *dyn_cast_eh_dispatch_allowed_cfg_superedge () const { return nullptr; }
     340                 :           0 :   virtual callgraph_superedge *dyn_cast_callgraph_superedge () { return NULL; }
     341                 :           0 :   virtual const callgraph_superedge *dyn_cast_callgraph_superedge () const { return NULL; }
     342                 :          80 :   virtual call_superedge *dyn_cast_call_superedge () { return NULL; }
     343                 :           0 :   virtual const call_superedge *dyn_cast_call_superedge () const { return NULL; }
     344                 :           0 :   virtual return_superedge *dyn_cast_return_superedge () { return NULL; }
     345                 :           0 :   virtual const return_superedge *dyn_cast_return_superedge () const { return NULL; }
     346                 :             : 
     347                 :             :   ::edge get_any_cfg_edge () const;
     348                 :             :   cgraph_edge *get_any_callgraph_edge () const;
     349                 :             : 
     350                 :             :   label_text get_description (bool user_facing) const;
     351                 :             : 
     352                 :             :  protected:
     353                 :       69809 :   superedge (supernode *src, supernode *dest, enum edge_kind kind)
     354                 :       69809 :   : dedge<supergraph_traits> (src, dest),
     355                 :       69809 :     m_kind (kind)
     356                 :             :   {}
     357                 :             : 
     358                 :             :  public:
     359                 :             :   const enum edge_kind m_kind;
     360                 :             : };
     361                 :             : 
     362                 :             : /* An ID representing an expression at a callsite:
     363                 :             :    either a parameter index, or the return value (or unknown).  */
     364                 :             : 
     365                 :             : class callsite_expr
     366                 :             : {
     367                 :             :  public:
     368                 :        1697 :   callsite_expr () : m_val (-1) {}
     369                 :             : 
     370                 :         280 :   static callsite_expr from_zero_based_param (int idx)
     371                 :             :   {
     372                 :         280 :     return callsite_expr (idx + 1);
     373                 :             :   }
     374                 :             : 
     375                 :          69 :   static callsite_expr from_return_value ()
     376                 :             :   {
     377                 :          69 :     return callsite_expr (0);
     378                 :             :   }
     379                 :             : 
     380                 :         230 :   bool param_p () const
     381                 :             :   {
     382                 :         230 :     return m_val > 0;
     383                 :             :   }
     384                 :             : 
     385                 :         166 :   bool return_value_p () const
     386                 :             :   {
     387                 :         166 :     return m_val == 0;
     388                 :             :   }
     389                 :             : 
     390                 :             :  private:
     391                 :         349 :   callsite_expr (int val) : m_val (val) {}
     392                 :             : 
     393                 :             :   int m_val; /* 1-based parm, 0 for return value, or -1 for "unknown".  */
     394                 :             : };
     395                 :             : 
     396                 :             : /* A subclass of superedge with an associated callgraph edge (either a
     397                 :             :    call or a return).  */
     398                 :             : 
     399                 :             : class callgraph_superedge : public superedge
     400                 :             : {
     401                 :             :  public:
     402                 :       11539 :   callgraph_superedge (supernode *src, supernode *dst, enum edge_kind kind,
     403                 :             :                        cgraph_edge *cedge)
     404                 :       11539 :   : superedge (src, dst, kind),
     405                 :        4343 :     m_cedge (cedge)
     406                 :             :   {}
     407                 :             : 
     408                 :             :   void dump_label_to_pp (pretty_printer *pp, bool user_facing) const
     409                 :             :     final override;
     410                 :             : 
     411                 :           0 :   callgraph_superedge *dyn_cast_callgraph_superedge () final override
     412                 :             :   {
     413                 :           0 :     return this;
     414                 :             :   }
     415                 :       10669 :   const callgraph_superedge *dyn_cast_callgraph_superedge () const
     416                 :             :     final override
     417                 :             :   {
     418                 :       10669 :     return this;
     419                 :             :   }
     420                 :             : 
     421                 :             :   function *get_callee_function () const;
     422                 :             :   function *get_caller_function () const;
     423                 :             :   tree get_callee_decl () const;
     424                 :             :   tree get_caller_decl () const;
     425                 :             :   const gcall &get_call_stmt () const;
     426                 :             :   tree get_arg_for_parm (tree parm, callsite_expr *out) const;
     427                 :             :   tree get_parm_for_arg (tree arg, callsite_expr *out) const;
     428                 :             :   tree map_expr_from_caller_to_callee (tree caller_expr,
     429                 :             :                                        callsite_expr *out) const;
     430                 :             :   tree map_expr_from_callee_to_caller (tree callee_expr,
     431                 :             :                                        callsite_expr *out) const;
     432                 :             : 
     433                 :             :   cgraph_edge *const m_cedge;
     434                 :             : };
     435                 :             : 
     436                 :             : } // namespace ana
     437                 :             : 
     438                 :             : template <>
     439                 :             : template <>
     440                 :             : inline bool
     441                 :        9023 : is_a_helper <const callgraph_superedge *>::test (const superedge *sedge)
     442                 :             : {
     443                 :        9023 :   return (sedge->get_kind () == SUPEREDGE_INTRAPROCEDURAL_CALL
     444                 :           0 :           || sedge->get_kind () == SUPEREDGE_CALL
     445                 :        9023 :           || sedge->get_kind () == SUPEREDGE_RETURN);
     446                 :             : }
     447                 :             : 
     448                 :             : namespace ana {
     449                 :             : 
     450                 :             : /* A subclass of superedge representing an interprocedural call.  */
     451                 :             : 
     452                 :             : class call_superedge : public callgraph_superedge
     453                 :             : {
     454                 :             :  public:
     455                 :        3598 :   call_superedge (supernode *src, supernode *dst, cgraph_edge *cedge)
     456                 :        3598 :   : callgraph_superedge (src, dst, SUPEREDGE_CALL, cedge)
     457                 :             :   {}
     458                 :             : 
     459                 :           4 :   call_superedge *dyn_cast_call_superedge () final override
     460                 :             :   {
     461                 :           4 :     return this;
     462                 :             :   }
     463                 :           0 :   const call_superedge *dyn_cast_call_superedge () const final override
     464                 :             :   {
     465                 :           0 :     return this;
     466                 :             :   }
     467                 :             : 
     468                 :        6690 :   return_superedge *get_edge_for_return (const supergraph &sg) const
     469                 :             :   {
     470                 :        6690 :     return sg.get_edge_for_return (m_cedge);
     471                 :             :   }
     472                 :             : };
     473                 :             : 
     474                 :             : } // namespace ana
     475                 :             : 
     476                 :             : template <>
     477                 :             : template <>
     478                 :             : inline bool
     479                 :       17704 : is_a_helper <const call_superedge *>::test (const superedge *sedge)
     480                 :             : {
     481                 :       17704 :   return sedge->get_kind () == SUPEREDGE_CALL;
     482                 :             : }
     483                 :             : 
     484                 :             : namespace ana {
     485                 :             : 
     486                 :             : /* A subclass of superedge represesnting an interprocedural return.  */
     487                 :             : 
     488                 :             : class return_superedge : public callgraph_superedge
     489                 :             : {
     490                 :             :  public:
     491                 :        3598 :   return_superedge (supernode *src, supernode *dst, cgraph_edge *cedge)
     492                 :        3598 :   : callgraph_superedge (src, dst, SUPEREDGE_RETURN, cedge)
     493                 :             :   {}
     494                 :             : 
     495                 :           0 :   return_superedge *dyn_cast_return_superedge () final override { return this; }
     496                 :           0 :   const return_superedge *dyn_cast_return_superedge () const final override
     497                 :             :   {
     498                 :           0 :     return this;
     499                 :             :   }
     500                 :             : 
     501                 :             :   call_superedge *get_edge_for_call (const supergraph &sg) const
     502                 :             :   {
     503                 :             :     return sg.get_edge_for_call (m_cedge);
     504                 :             :   }
     505                 :             : };
     506                 :             : 
     507                 :             : } // namespace ana
     508                 :             : 
     509                 :             : template <>
     510                 :             : template <>
     511                 :             : inline bool
     512                 :        8431 : is_a_helper <const return_superedge *>::test (const superedge *sedge)
     513                 :             : {
     514                 :        8431 :   return sedge->get_kind () == SUPEREDGE_RETURN;
     515                 :             : }
     516                 :             : 
     517                 :             : namespace ana {
     518                 :             : 
     519                 :             : /* A subclass of superedge that corresponds to a CFG edge.  */
     520                 :             : 
     521                 :             : class cfg_superedge : public superedge
     522                 :             : {
     523                 :             :  public:
     524                 :       58270 :   cfg_superedge (supernode *src, supernode *dst, ::edge e)
     525                 :       58270 :   : superedge (src, dst, SUPEREDGE_CFG_EDGE),
     526                 :        3223 :     m_cfg_edge (e)
     527                 :             :   {}
     528                 :             : 
     529                 :             :   void dump_label_to_pp (pretty_printer *pp, bool user_facing) const override;
     530                 :      115735 :   cfg_superedge *dyn_cast_cfg_superedge () final override { return this; }
     531                 :      333234 :   const cfg_superedge *dyn_cast_cfg_superedge () const final override { return this; }
     532                 :             : 
     533                 :       71847 :   ::edge get_cfg_edge () const { return m_cfg_edge; }
     534                 :      344162 :   int get_flags () const { return m_cfg_edge->flags; }
     535                 :       23573 :   int true_value_p () const { return get_flags () & EDGE_TRUE_VALUE; }
     536                 :       22611 :   int false_value_p () const { return get_flags () & EDGE_FALSE_VALUE; }
     537                 :      106709 :   int back_edge_p () const { return get_flags () & EDGE_DFS_BACK; }
     538                 :             : 
     539                 :             :   size_t get_phi_arg_idx () const;
     540                 :             :   tree get_phi_arg (const gphi *phi) const;
     541                 :             : 
     542                 :         478 :   location_t get_goto_locus () const { return m_cfg_edge->goto_locus; }
     543                 :             : 
     544                 :             :  private:
     545                 :             :   const ::edge m_cfg_edge;
     546                 :             : };
     547                 :             : 
     548                 :             : } // namespace ana
     549                 :             : 
     550                 :             : template <>
     551                 :             : template <>
     552                 :             : inline bool
     553                 :      177004 : is_a_helper <const cfg_superedge *>::test (const superedge *sedge)
     554                 :             : {
     555                 :      177004 :   return sedge->get_kind () == SUPEREDGE_CFG_EDGE;
     556                 :             : }
     557                 :             : 
     558                 :             : namespace ana {
     559                 :             : 
     560                 :             : /* A subclass for edges from switch statements, retaining enough
     561                 :             :    information to identify the pertinent cases, and for adding labels
     562                 :             :    when rendering via graphviz.  */
     563                 :             : 
     564                 :             : class switch_cfg_superedge : public cfg_superedge {
     565                 :             :  public:
     566                 :             :   switch_cfg_superedge (supernode *src, supernode *dst, ::edge e);
     567                 :             : 
     568                 :        7914 :   const switch_cfg_superedge *dyn_cast_switch_cfg_superedge () const
     569                 :             :     final override
     570                 :             :   {
     571                 :        7914 :     return this;
     572                 :             :   }
     573                 :             : 
     574                 :             :   void dump_label_to_pp (pretty_printer *pp, bool user_facing) const
     575                 :             :     final override;
     576                 :             : 
     577                 :        3031 :   gswitch *get_switch_stmt () const
     578                 :             :   {
     579                 :        3031 :     return as_a <gswitch *> (m_src->get_last_stmt ());
     580                 :             :   }
     581                 :             : 
     582                 :        2974 :   const vec<tree> &get_case_labels () const { return m_case_labels; }
     583                 :             : 
     584                 :             :   bool implicitly_created_default_p () const;
     585                 :             : 
     586                 :             : private:
     587                 :             :   auto_vec<tree> m_case_labels;
     588                 :             : };
     589                 :             : 
     590                 :             : } // namespace ana
     591                 :             : 
     592                 :             : template <>
     593                 :             : template <>
     594                 :             : inline bool
     595                 :        7907 : is_a_helper <const switch_cfg_superedge *>::test (const superedge *sedge)
     596                 :             : {
     597                 :        7907 :   return sedge->dyn_cast_switch_cfg_superedge () != NULL;
     598                 :             : }
     599                 :             : 
     600                 :             : namespace ana {
     601                 :             : 
     602                 :             : /* A subclass for edges from eh_dispatch statements, retaining enough
     603                 :             :    information to identify the various types being caught, vs the
     604                 :             :    "unhandled type" case, and for adding labels when rendering
     605                 :             :    via graphviz.
     606                 :             :    This is abstract; there are concrete subclasses based on the type
     607                 :             :    of the eh_region.  */
     608                 :             : 
     609                 :             : class eh_dispatch_cfg_superedge : public cfg_superedge
     610                 :             : {
     611                 :             :  public:
     612                 :             :   static std::unique_ptr<eh_dispatch_cfg_superedge>
     613                 :             :   make (supernode *src,
     614                 :             :         supernode *dest,
     615                 :             :         ::edge e,
     616                 :             :         const geh_dispatch *eh_dispatch_stmt);
     617                 :             : 
     618                 :         355 :   const eh_dispatch_cfg_superedge *dyn_cast_eh_dispatch_cfg_superedge () const
     619                 :             :     final override
     620                 :             :   {
     621                 :         355 :     return this;
     622                 :             :   }
     623                 :             : 
     624                 :             :   const geh_dispatch *
     625                 :             :   get_eh_dispatch_stmt () const
     626                 :             :   {
     627                 :             :     return m_eh_dispatch_stmt;
     628                 :             :   }
     629                 :             : 
     630                 :             :   const eh_status &get_eh_status () const;
     631                 :          13 :   eh_region get_eh_region () const { return m_eh_region; }
     632                 :             : 
     633                 :             :   virtual bool
     634                 :             :   apply_constraints (region_model *model,
     635                 :             :                      region_model_context *ctxt,
     636                 :             :                      tree exception_type,
     637                 :             :                      std::unique_ptr<rejected_constraint> *out) const = 0;
     638                 :             : 
     639                 :             : protected:
     640                 :             :   eh_dispatch_cfg_superedge (supernode *src, supernode *dst, ::edge e,
     641                 :             :                              const geh_dispatch *eh_dispatch_stmt,
     642                 :             :                              eh_region eh_reg);
     643                 :             : 
     644                 :             : private:
     645                 :             :   const geh_dispatch *m_eh_dispatch_stmt;
     646                 :             :   eh_region m_eh_region;
     647                 :             : };
     648                 :             : 
     649                 :             : } // namespace ana
     650                 :             : 
     651                 :             : template <>
     652                 :             : template <>
     653                 :             : inline bool
     654                 :         355 : is_a_helper <const eh_dispatch_cfg_superedge *>::test (const superedge *sedge)
     655                 :             : {
     656                 :         355 :   return sedge->dyn_cast_eh_dispatch_cfg_superedge () != NULL;
     657                 :             : }
     658                 :             : 
     659                 :             : namespace ana {
     660                 :             : 
     661                 :             : /* A concrete subclass for edges from an eh_dispatch statements
     662                 :             :    for ERT_TRY regions.  */
     663                 :             : 
     664                 :             : class eh_dispatch_try_cfg_superedge : public eh_dispatch_cfg_superedge
     665                 :             : {
     666                 :             :  public:
     667                 :         180 :   eh_dispatch_try_cfg_superedge (supernode *src, supernode *dst, ::edge e,
     668                 :             :                                  const geh_dispatch *eh_dispatch_stmt,
     669                 :             :                                  eh_region eh_reg,
     670                 :             :                                  eh_catch ehc)
     671                 :         180 :   : eh_dispatch_cfg_superedge (src, dst, e, eh_dispatch_stmt, eh_reg),
     672                 :         180 :     m_eh_catch (ehc)
     673                 :             :   {
     674                 :         180 :     gcc_assert (eh_reg->type == ERT_TRY);
     675                 :         180 :   }
     676                 :             : 
     677                 :             :   const eh_dispatch_try_cfg_superedge *
     678                 :         210 :   dyn_cast_eh_dispatch_try_cfg_superedge () const final override
     679                 :             :   {
     680                 :         210 :     return this;
     681                 :             :   }
     682                 :             : 
     683                 :             :   void dump_label_to_pp (pretty_printer *pp,
     684                 :             :                          bool user_facing) const final override;
     685                 :             : 
     686                 :         387 :   eh_catch get_eh_catch () const { return m_eh_catch; }
     687                 :             : 
     688                 :             :   bool
     689                 :             :   apply_constraints (region_model *model,
     690                 :             :                      region_model_context *ctxt,
     691                 :             :                      tree exception_type,
     692                 :             :                      std::unique_ptr<rejected_constraint> *out)
     693                 :             :     const final override;
     694                 :             : 
     695                 :             : private:
     696                 :             :   eh_catch m_eh_catch;
     697                 :             : };
     698                 :             : 
     699                 :             : } // namespace ana
     700                 :             : 
     701                 :             : template <>
     702                 :             : template <>
     703                 :             : inline bool
     704                 :         144 : is_a_helper <const eh_dispatch_try_cfg_superedge *>::test (const superedge *sedge)
     705                 :             : {
     706                 :         144 :   return sedge->dyn_cast_eh_dispatch_try_cfg_superedge () != NULL;
     707                 :             : }
     708                 :             : 
     709                 :             : namespace ana {
     710                 :             : 
     711                 :             : /* A concrete subclass for edges from an eh_dispatch statements
     712                 :             :    for ERT_ALLOWED_EXCEPTIONS regions.  */
     713                 :             : 
     714                 :             : class eh_dispatch_allowed_cfg_superedge : public eh_dispatch_cfg_superedge
     715                 :             : {
     716                 :             :  public:
     717                 :             :   enum eh_kind
     718                 :             :   {
     719                 :             :     expected,
     720                 :             :     unexpected
     721                 :             :   };
     722                 :             : 
     723                 :             :   eh_dispatch_allowed_cfg_superedge (supernode *src, supernode *dst, ::edge e,
     724                 :             :                                      const geh_dispatch *eh_dispatch_stmt,
     725                 :             :                                      eh_region eh_reg);
     726                 :             : 
     727                 :             :   const eh_dispatch_allowed_cfg_superedge *
     728                 :           0 :   dyn_cast_eh_dispatch_allowed_cfg_superedge () const final override
     729                 :             :   {
     730                 :           0 :     return this;
     731                 :             :   }
     732                 :             : 
     733                 :             :   void dump_label_to_pp (pretty_printer *pp,
     734                 :             :                          bool user_facing) const final override;
     735                 :             : 
     736                 :             :   bool
     737                 :             :   apply_constraints (region_model *model,
     738                 :             :                      region_model_context *ctxt,
     739                 :             :                      tree exception_type,
     740                 :             :                      std::unique_ptr<rejected_constraint> *out)
     741                 :             :     const final override;
     742                 :             : 
     743                 :          13 :   enum eh_kind get_eh_kind () const { return m_kind; }
     744                 :             : 
     745                 :             : private:
     746                 :             :   enum eh_kind m_kind;
     747                 :             : };
     748                 :             : 
     749                 :             : } // namespace ana
     750                 :             : 
     751                 :             : template <>
     752                 :             : template <>
     753                 :             : inline bool
     754                 :             : is_a_helper <const eh_dispatch_allowed_cfg_superedge *>::test (const superedge *sedge)
     755                 :             : {
     756                 :             :   return sedge->dyn_cast_eh_dispatch_allowed_cfg_superedge () != NULL;
     757                 :             : }
     758                 :             : 
     759                 :             : namespace ana {
     760                 :             : /* Base class for adding additional content to the .dot output
     761                 :             :    for a supergraph.  */
     762                 :             : 
     763                 :           8 : class dot_annotator
     764                 :             : {
     765                 :             :  public:
     766                 :           8 :   virtual ~dot_annotator () {}
     767                 :           0 :   virtual bool add_node_annotations (graphviz_out *gv ATTRIBUTE_UNUSED,
     768                 :             :                                      const supernode &n ATTRIBUTE_UNUSED,
     769                 :             :                                      bool within_table ATTRIBUTE_UNUSED)
     770                 :             :     const
     771                 :             :   {
     772                 :           0 :     return false;
     773                 :             :   }
     774                 :           0 :   virtual void add_stmt_annotations (graphviz_out *gv ATTRIBUTE_UNUSED,
     775                 :             :                                      const gimple *stmt ATTRIBUTE_UNUSED,
     776                 :             :                                      bool within_row ATTRIBUTE_UNUSED)
     777                 :           0 :     const {}
     778                 :          76 :   virtual bool add_after_node_annotations (graphviz_out *gv ATTRIBUTE_UNUSED,
     779                 :             :                                            const supernode &n ATTRIBUTE_UNUSED)
     780                 :             :     const
     781                 :             :   {
     782                 :          76 :     return false;
     783                 :             :   }
     784                 :             : };
     785                 :             : 
     786                 :             : extern cgraph_edge *supergraph_call_edge (function *fun, const gimple *stmt);
     787                 :             : extern function *get_ultimate_function_for_cgraph_edge (cgraph_edge *edge);
     788                 :             : 
     789                 :             : } // namespace ana
     790                 :             : 
     791                 :             : #endif /* GCC_ANALYZER_SUPERGRAPH_H */
        

Generated by: LCOV version 2.1-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.