This patch extends -fdump-analyzer-supergraph so that rather than just dumping a DUMP_BASE_NAME.supergraph.dot at the start of analysis, it also dumps a DUMP_BASE_NAME.supergraph-eg.dot at the end. The new dump file contains a concise dump of the exploded_graph, organized with respect to the supergraph and its statements. The exploded nodes are colorized to show sm-state, but no other state is shown. Per exploded_node saved_diagnostics are also shown, along with feasibility of the paths to reach them. I've been finding this a useful way of tracking down issues in exploded_graphs that are sufficiently large that the output of -fdump-analyzer-exploded-graph becomes unwieldy. The patch extends feasiblity-testing so that if the exploded_path for a saved_diagnostic is found to be infeasible, the reason is saved and written into the saved_diagnostic, so it can be shown in the dump. I've found this very useful when tracking down feasibility issues. I'm keeping the initial dump file as it's useful when tracking down ICEs within the analyzer (which would stop the second dump file being written). gcc/analyzer/ChangeLog: * analyzer.h (class feasibility_problem): New forward decl. * diagnostic-manager.cc (saved_diagnostic::saved_diagnostic): Initialize new fields m_status, m_epath_length, and m_problem. (saved_diagnostic::~saved_diagnostic): Delete m_problem. (dedupe_candidate::dedupe_candidate): Convert "sd" param from a const ref to a mutable ptr. (dedupe_winners::add): Convert "sd" param from a const ref to a mutable ptr. Record the length of the exploded_path. Record the feasibility/infeasibility of sd into sd, capturing a feasibility_problem when feasible_p fails, and storing it in sd. (diagnostic_manager::emit_saved_diagnostics): Update for pass by ptr rather than by const ref. * diagnostic-manager.h (class saved_diagnostic): Add new enum status. Add fields m_status, m_epath_length and m_problem. (saved_diagnostic::set_feasible): New member function. (saved_diagnostic::set_infeasible): New member function. (saved_diagnostic::get_feasibility_problem): New accessor. (saved_diagnostic::get_status): New accessor. (saved_diagnostic::set_epath_length): New member function. (saved_diagnostic::get_epath_length): New accessor. * engine.cc: Include "gimple-pretty-print.h". (exploded_path::feasible_p): Add OUT param and, if non-NULL, write a new feasibility_problem to it on failure. (viz_callgraph_node::dump_dot): Convert begin_tr calls to begin_trtd. Convert end_tr calls to end_tdtr. (class exploded_graph_annotator): New subclass of dot_annotator. (impl_run_checkers): Add a second -fdump-analyzer-supergraph dump after the analysis runs, using exploded_graph_annotator. dumping to DUMP_BASE_NAME.supergraph-eg.dot. * exploded-graph.h (exploded_node::get_dot_fillcolor): Make public. (exploded_path::feasible_p): Add OUT param. (class feasibility_problem): New class. * state-purge.cc (state_purge_annotator::add_node_annotations): Return a bool, add a "within_table" param. (print_vec_of_names): Convert begin_tr calls to begin_trtd. Convert end_tr calls to end_tdtr. (state_purge_annotator::add_stmt_annotations): Add "within_row" param. * state-purge.h ((state_purge_annotator::add_node_annotations): Return a bool, add a "within_table" param. (state_purge_annotator::add_stmt_annotations): Add "within_row" param. * supergraph.cc (supernode::dump_dot): Call add_node_annotations twice: as before, passing false for "within_table", then again with true when within the TABLE element. Convert some begin_tr calls to begin_trtd, and some end_tr calls to end_tdtr. Repeat each add_stmt_annotations call, distinguishing between calls that add TRs and those that add TDs to an existing TR. Add a call to add_after_node_annotations. * supergraph.h (dot_annotator::add_node_annotations): Add a "within_table" param. (dot_annotator::add_stmt_annotations): Add a "within_row" param. (dot_annotator::add_after_node_annotations): New vfunc. gcc/ChangeLog: * doc/invoke.texi (-fdump-analyzer-supergraph): Document that this now emits two .dot files. * graphviz.cc (graphviz_out::begin_tr): Only emit a TR, not a TD. (graphviz_out::end_tr): Only close a TR, not a TD. (graphviz_out::begin_td): New. (graphviz_out::end_td): New. (graphviz_out::begin_trtd): New, replacing the old implementation of graphviz_out::begin_tr. (graphviz_out::end_tdtr): New, replacing the old implementation of graphviz_out::end_tr. * graphviz.h (graphviz_out::begin_td): New decl. (graphviz_out::end_td): New decl. (graphviz_out::begin_trtd): New decl. (graphviz_out::end_tdtr): New decl. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/dot-output.c: Check that dot-output.c.supergraph-eg.dot is valid.
141 lines
3.1 KiB
C++
141 lines
3.1 KiB
C++
/* Helper code for graphviz output.
|
|
Copyright (C) 2019-2020 Free Software Foundation, Inc.
|
|
Contributed by David Malcolm <dmalcolm@redhat.com>.
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3, or (at your option)
|
|
any later version.
|
|
|
|
GCC is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GCC; see the file COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#include "config.h"
|
|
#include "system.h"
|
|
#include "coretypes.h"
|
|
#include "graphviz.h"
|
|
|
|
/* graphviz_out's ctor, wrapping PP. */
|
|
|
|
graphviz_out::graphviz_out (pretty_printer *pp)
|
|
: m_pp (pp),
|
|
m_indent (0)
|
|
{
|
|
}
|
|
|
|
/* Formatted print of FMT. */
|
|
|
|
void
|
|
graphviz_out::print (const char *fmt, ...)
|
|
{
|
|
text_info text;
|
|
va_list ap;
|
|
|
|
va_start (ap, fmt);
|
|
text.err_no = errno;
|
|
text.args_ptr = ≈
|
|
text.format_spec = fmt;
|
|
pp_format (m_pp, &text);
|
|
pp_output_formatted_text (m_pp);
|
|
va_end (ap);
|
|
}
|
|
|
|
/* Formatted print of FMT. The text is indented by the current
|
|
indent, and a newline is added. */
|
|
|
|
void
|
|
graphviz_out::println (const char *fmt, ...)
|
|
{
|
|
text_info text;
|
|
va_list ap;
|
|
|
|
write_indent ();
|
|
|
|
va_start (ap, fmt);
|
|
text.err_no = errno;
|
|
text.args_ptr = ≈
|
|
text.format_spec = fmt;
|
|
pp_format (m_pp, &text);
|
|
pp_output_formatted_text (m_pp);
|
|
va_end (ap);
|
|
|
|
pp_newline (m_pp);
|
|
}
|
|
|
|
/* Print the current indent to the underlying pp. */
|
|
|
|
void
|
|
graphviz_out::write_indent ()
|
|
{
|
|
for (int i = 0; i < m_indent * 2; ++i)
|
|
pp_space (m_pp);
|
|
}
|
|
|
|
/* Write the start of an HTML-like row via <TR>, writing to the stream
|
|
so that followup text can be escaped. */
|
|
|
|
void
|
|
graphviz_out::begin_tr ()
|
|
{
|
|
pp_string (m_pp, "<TR>");
|
|
pp_write_text_to_stream (m_pp);
|
|
}
|
|
|
|
/* Write the end of an HTML-like row via </TR>, writing to the stream
|
|
so that followup text can be escaped. */
|
|
|
|
void
|
|
graphviz_out::end_tr ()
|
|
{
|
|
pp_string (m_pp, "</TR>");
|
|
pp_write_text_to_stream (m_pp);
|
|
}
|
|
|
|
/* Write the start of an HTML-like <TD>, writing to the stream
|
|
so that followup text can be escaped. */
|
|
|
|
void
|
|
graphviz_out::begin_td ()
|
|
{
|
|
pp_string (m_pp, "<TD ALIGN=\"LEFT\">");
|
|
pp_write_text_to_stream (m_pp);
|
|
}
|
|
|
|
/* Write the end of an HTML-like </TD>, writing to the stream
|
|
so that followup text can be escaped. */
|
|
|
|
void
|
|
graphviz_out::end_td ()
|
|
{
|
|
pp_string (m_pp, "</TD>");
|
|
pp_write_text_to_stream (m_pp);
|
|
}
|
|
|
|
/* Write the start of an HTML-like row via <TR><TD>, writing to the stream
|
|
so that followup text can be escaped. */
|
|
|
|
void
|
|
graphviz_out::begin_trtd ()
|
|
{
|
|
pp_string (m_pp, "<TR><TD ALIGN=\"LEFT\">");
|
|
pp_write_text_to_stream (m_pp);
|
|
}
|
|
|
|
/* Write the end of an HTML-like row via </TD></TR>, writing to the stream
|
|
so that followup text can be escaped. */
|
|
|
|
void
|
|
graphviz_out::end_tdtr ()
|
|
{
|
|
pp_string (m_pp, "</TD></TR>");
|
|
pp_write_text_to_stream (m_pp);
|
|
}
|