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. Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Pushed to master as dea4a32b24fb888532c47f3920f6910b3c94a8a0. 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 | 29 ++++++++++++++++++++++++++++- gcc/analyzer/exploded-graph.h | 4 ++++ gcc/analyzer/store.cc | 2 +- gcc/analyzer/supergraph.cc | 29 +++++++++++++++++++++++++++-- 4 files changed, 60 insertions(+), 4 deletions(-) diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 8bc9adf5ee6..fc81e7523fb 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -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; diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h index 84f8862fb96..7ce1e85800d 100644 --- a/gcc/analyzer/exploded-graph.h +++ b/gcc/analyzer/exploded-graph.h @@ -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 { diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc index bbd2e7c2d40..abdb336da91 100644 --- a/gcc/analyzer/store.cc +++ b/gcc/analyzer/store.cc @@ -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 diff --git a/gcc/analyzer/supergraph.cc b/gcc/analyzer/supergraph.cc index 40acfbd16a8..0c69f139334 100644 --- a/gcc/analyzer/supergraph.cc +++ b/gcc/analyzer/supergraph.cc @@ -679,8 +679,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]}. */ @@ -691,6 +692,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) { @@ -798,6 +801,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 @@ -900,7 +923,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. */ @@ -908,6 +932,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)); -- 2.26.2