analyzer: fixes to -fdump-analyzer-json
authorDavid Malcolm <dmalcolm@redhat.com>
Thu, 14 Jan 2021 20:39:14 +0000 (15:39 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Thu, 14 Jan 2021 20:39:14 +0000 (15:39 -0500)
I've been implementing a PyGTK viewer for the output of
-fdump-analyzer-json, to help me debug analyzer issues:
  https://github.com/davidmalcolm/gcc-analyzer-viewer
The viewer is very much just a work in progress.

This patch adds some fields that were missing from the dump, and
fixes some mistakes I spotted whilst working on the viewer.

gcc/analyzer/ChangeLog:
* engine.cc (strongly_connected_components::to_json): New.
(worklist::to_json): New.
(exploded_graph::to_json): JSON-ify the worklist.
* exploded-graph.h (strongly_connected_components::to_json): New
decl.
(worklist::to_json): New decl.
* store.cc (store::to_json): Fix comment.
* supergraph.cc (supernode::to_json): Fix reference to
"returning_call" in comment.  Add optional "fun" to JSON.
(edge_kind_to_string): New.
(superedge::to_json): Add "kind" to JSON.

gcc/analyzer/engine.cc
gcc/analyzer/exploded-graph.h
gcc/analyzer/store.cc
gcc/analyzer/supergraph.cc

index 8bc9adf5ee6fc5479710f6dbe38767138af78ca9..fc81e7523fbaf427f0eb1cd028eaf06129c2c5c6 100644 (file)
@@ -1772,6 +1772,17 @@ strongly_connected_components::dump () const
     }
 }
 
+/* Return a new json::array of per-snode SCC ids.  */
+
+json::array *
+strongly_connected_components::to_json () const
+{
+  json::array *scc_arr = new json::array ();
+  for (int i = 0; i < m_sg.num_nodes (); i++)
+    scc_arr->append (new json::integer_number (get_scc_id (i)));
+  return scc_arr;
+}
+
 /* Subroutine of strongly_connected_components's ctor, part of Tarjan's
    SCC algorithm.  */
 
@@ -1968,6 +1979,22 @@ worklist::key_t::cmp (const worklist::key_t &ka, const worklist::key_t &kb)
   return ka.m_enode->m_index - kb.m_enode->m_index;
 }
 
+/* Return a new json::object of the form
+   {"scc" : [per-snode-IDs]},  */
+
+json::object *
+worklist::to_json () const
+{
+  json::object *worklist_obj = new json::object ();
+
+  worklist_obj->set ("scc", m_scc.to_json ());
+
+  /* The following field isn't yet being JSONified:
+     queue_t m_queue;  */
+
+  return worklist_obj;
+}
+
 /* exploded_graph's ctor.  */
 
 exploded_graph::exploded_graph (const supergraph &sg, logger *logger,
@@ -3315,10 +3342,10 @@ exploded_graph::to_json () const
   /* m_sg is JSONified at the top-level.  */
 
   egraph_obj->set ("ext_state", m_ext_state.to_json ());
+  egraph_obj->set ("worklist", m_worklist.to_json ());
   egraph_obj->set ("diagnostic_manager", m_diagnostic_manager.to_json ());
 
   /* The following fields aren't yet being JSONified:
-     worklist m_worklist;
      const state_purge_map *const m_purge_map;
      const analysis_plan &m_plan;
      stats m_global_stats;
index 84f8862fb9640da9e6d3b49a06593744a8ba7f6b..7ce1e85800d625678c59a30c3a64a85db9a46db0 100644 (file)
@@ -622,6 +622,8 @@ public:
 
   void dump () const;
 
+  json::array *to_json () const;
+
 private:
   struct per_node_data
   {
@@ -664,6 +666,8 @@ public:
     return m_scc.get_scc_id (snode.m_index);
   }
 
+  json::object *to_json () const;
+
 private:
   class key_t
   {
index bbd2e7c2d40cac79377094e993960a6d397a7aca..abdb336da91d249489f4516a1de17d3bef93553e 100644 (file)
@@ -1740,7 +1740,7 @@ store::dump (bool simple) const
    {PARENT_REGION_DESC: {BASE_REGION_DESC: object for binding_map,
                         ... for each cluster within parent region},
     ...for each parent region,
-    "called_unknown_function": true/false}.  */
+    "called_unknown_fn": true/false}.  */
 
 json::object *
 store::to_json () const
index 419f6424f76be2e3893aafdc0c8ca9d6b11c0790..4b934568db62da2a5f389aaee662b00185da88eb 100644 (file)
@@ -634,8 +634,9 @@ supernode::dump_dot_id (pretty_printer *pp) const
 
 /* Return a new json::object of the form
    {"idx": int,
+    "fun": optional str
     "bb_idx": int,
-    "m_returning_call": optional str,
+    "returning_call": optional str,
     "phis": [str],
     "stmts" : [str]}.  */
 
@@ -646,6 +647,8 @@ supernode::to_json () const
 
   snode_obj->set ("idx", new json::integer_number (m_index));
   snode_obj->set ("bb_idx", new json::integer_number (m_bb->index));
+  if (function *fun = get_function ())
+    snode_obj->set ("fun", new json::string (function_name (fun)));
 
   if (m_returning_call)
     {
@@ -753,6 +756,26 @@ supernode::get_stmt_index (const gimple *stmt) const
   gcc_unreachable ();
 }
 
+/* Get a string for PK.  */
+
+static const char *
+edge_kind_to_string (enum edge_kind kind)
+{
+  switch (kind)
+    {
+    default:
+      gcc_unreachable ();
+    case SUPEREDGE_CFG_EDGE:
+      return "SUPEREDGE_CFG_EDGE";
+    case SUPEREDGE_CALL:
+      return "SUPEREDGE_CALL";
+    case SUPEREDGE_RETURN:
+      return "SUPEREDGE_RETURN";
+    case SUPEREDGE_INTRAPROCEDURAL_CALL:
+      return "SUPEREDGE_INTRAPROCEDURAL_CALL";
+    }
+};
+
 /* Dump this superedge to PP.  */
 
 void
@@ -855,7 +878,8 @@ superedge::dump_dot (graphviz_out *gv, const dump_args_t &) const
 }
 
 /* Return a new json::object of the form
-   {"src_idx": int, the index of the source supernode,
+   {"kind"   : str,
+    "src_idx": int, the index of the source supernode,
     "dst_idx": int, the index of the destination supernode,
     "desc"   : str.  */
 
@@ -863,6 +887,7 @@ json::object *
 superedge::to_json () const
 {
   json::object *sedge_obj = new json::object ();
+  sedge_obj->set ("kind", new json::string (edge_kind_to_string (m_kind)));
   sedge_obj->set ("src_idx", new json::integer_number (m_src->m_index));
   sedge_obj->set ("dst_idx", new json::integer_number (m_dest->m_index));