diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index bf7c8fc5147ca82f384a6a538fdd3ff29fc58e82..5bd4cd49cac2a658603fa726d1d6e445deddd0f6 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -112,6 +112,10 @@ private: void dump_feasible_graph (const exploded_node *target_enode, const char *desc, unsigned diag_idx, const feasible_graph &fg); + void dump_feasible_path (const exploded_node *target_enode, + unsigned diag_idx, + const feasible_graph &fg, + const feasible_node &fnode) const; const exploded_graph &m_eg; shortest_exploded_paths *m_sep; @@ -510,6 +514,9 @@ epath_finder::process_worklist_item (feasible_worklist *worklist, target_enode->m_index, diag_idx, succ_fnode->get_path_length ()); *out_best_path = fg->make_epath (succ_fnode); + if (flag_dump_analyzer_feasibility) + dump_feasible_path (target_enode, diag_idx, *fg, *succ_fnode); + /* Success: stop the worklist iteration. */ return false; } @@ -608,6 +615,23 @@ epath_finder::dump_feasible_graph (const exploded_node *target_enode, free (filename); } +/* Dump the path to FNODE to "BASE_NAME.DIAG_IDX.to-enN.fpath.txt". */ + +void +epath_finder::dump_feasible_path (const exploded_node *target_enode, + unsigned diag_idx, + const feasible_graph &fg, + const feasible_node &fnode) const +{ + auto_timevar tv (TV_ANALYZER_DUMP); + pretty_printer pp; + pp_printf (&pp, "%s.%i.to-en%i.fpath.txt", + dump_base_name, diag_idx, target_enode->m_index); + char *filename = xstrdup (pp_formatted_text (&pp)); + fg.dump_feasible_path (fnode, filename); + free (filename); +} + /* class saved_diagnostic. */ /* saved_diagnostic's ctor. diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index d8b61955aa64a16e3be4b811da36bfd21a8181f0..e43406e35562e9af7df53b417b4255c53054f2d5 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -4605,6 +4605,15 @@ feasibility_state::maybe_update_for_edge (logger *logger, return true; } +/* Dump this object to PP. */ + +void +feasibility_state::dump_to_pp (pretty_printer *pp, + bool simple, bool multiline) const +{ + m_model.dump_to_pp (pp, simple, multiline); +} + /* A family of cluster subclasses for use when generating .dot output for exploded graphs (-fdump-analyzer-exploded-graph), for grouping the enodes into hierarchical boxes. diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h index af0ab8d42c82182fe94017cea33f4f5ab03193ec..2dcdcc55b2a2f6ca6dfe8fd962dbd39fa1322c9a 100644 --- a/gcc/analyzer/exploded-graph.h +++ b/gcc/analyzer/exploded-graph.h @@ -1001,6 +1001,8 @@ public: const region_model &get_model () const { return m_model; } const auto_sbitmap &get_snodes_visited () const { return m_snodes_visited; } + void dump_to_pp (pretty_printer *pp, bool simple, bool multiline) const; + private: region_model m_model; auto_sbitmap m_snodes_visited; diff --git a/gcc/analyzer/feasible-graph.cc b/gcc/analyzer/feasible-graph.cc index 0ac8484a7e431052e4ccb36df2b9ea99ee9bc61a..fe7e79fe90229b7c9dc122d3f1e38ace37f9e8f3 100644 --- a/gcc/analyzer/feasible-graph.cc +++ b/gcc/analyzer/feasible-graph.cc @@ -218,6 +218,71 @@ feasible_graph::make_epath (feasible_node *fnode) const return epath; } +/* Dump the path to DST_FNODE in textual form to PP. */ + +void +feasible_graph::dump_feasible_path (const feasible_node &dst_fnode, + pretty_printer *pp) const +{ + const feasible_node *fnode = &dst_fnode; + + auto_vec<const feasible_edge *> fpath; + + /* FG is actually a tree. Built the path backwards, by walking + backwards from FNODE until we reach the origin. */ + while (fnode->get_inner_node ()->m_index != 0) + { + gcc_assert (fnode->m_preds.length () == 1); + feasible_edge *pred_fedge + = static_cast <feasible_edge *> (fnode->m_preds[0]); + fpath.safe_push (pred_fedge); + fnode = static_cast <const feasible_node *> (pred_fedge->m_src); + } + + /* Now reverse it. */ + fpath.reverse (); + + for (unsigned i = 0; i < fpath.length (); i++) + { + const feasible_edge *fedge = fpath[i]; + const feasible_node *src_fnode + = static_cast <const feasible_node *> (fedge->m_src); + const feasible_node *dest_fnode + = static_cast <const feasible_node *> (fedge->m_dest); + + pp_printf (pp, "fpath[%i]: FN %i (EN %i) -> FN %i (EN %i)", + i, + src_fnode->get_index (), + src_fnode->get_inner_node ()->m_index, + dest_fnode->get_index (), + dest_fnode->get_inner_node ()->m_index); + pp_newline (pp); + pp_printf (pp, " FN %i (EN %i):", + dest_fnode->get_index (), + dest_fnode->get_inner_node ()->m_index); + pp_newline (pp); + const program_point &point = dest_fnode->get_inner_node ()->get_point (); + point.print (pp, format (true)); + dest_fnode->get_state ().dump_to_pp (pp, true, true); + pp_newline (pp); + } +} + +/* Dump the path to DST_FNODE in textual form to FILENAME. */ + +void +feasible_graph::dump_feasible_path (const feasible_node &dst_fnode, + const char *filename) const +{ + FILE *fp = fopen (filename, "w"); + pretty_printer pp; + pp_format_decoder (&pp) = default_tree_printer; + pp.buffer->stream = fp; + dump_feasible_path (dst_fnode, &pp); + pp_flush (&pp); + fclose (fp); +} + /* Dump stats about this graph to LOGGER. */ void diff --git a/gcc/analyzer/feasible-graph.h b/gcc/analyzer/feasible-graph.h index d10a28d4f902ccf9af513514a34395d8e63e6b5b..f1868af3cf8cead6b557738ab549ca0c2a90c9e6 100644 --- a/gcc/analyzer/feasible-graph.h +++ b/gcc/analyzer/feasible-graph.h @@ -197,11 +197,17 @@ class feasible_graph : public digraph <fg_traits> exploded_path *make_epath (feasible_node *fnode) const; + void dump_feasible_path (const feasible_node &dst_fnode, + const char *filename) const; + unsigned get_num_infeasible () const { return m_num_infeasible; } void log_stats (logger *logger) const; private: + void dump_feasible_path (const feasible_node &dst_fnode, + pretty_printer *pp) const; + unsigned m_num_infeasible; }; diff --git a/gcc/analyzer/program-point.cc b/gcc/analyzer/program-point.cc index 61cea8a10768221d3c450765291b1d3820af1bf2..8fa7066fea5a4ca75020483a145848d856505fd0 100644 --- a/gcc/analyzer/program-point.cc +++ b/gcc/analyzer/program-point.cc @@ -114,6 +114,8 @@ function_point::print (pretty_printer *pp, const format &f) const case PK_ORIGIN: pp_printf (pp, "origin"); + if (f.m_newlines) + pp_newline (pp); break; case PK_BEFORE_SUPERNODE: @@ -156,6 +158,8 @@ function_point::print (pretty_printer *pp, const format &f) const case PK_AFTER_SUPERNODE: pp_printf (pp, "after SN: %i", m_supernode->m_index); + if (f.m_newlines) + pp_newline (pp); break; } } diff --git a/gcc/analyzer/program-point.h b/gcc/analyzer/program-point.h index 4b1c733d7106f62552e0387fbf62c02e06fa42d0..6084c9e3004d9398e19dc772ec5891a7af03c603 100644 --- a/gcc/analyzer/program-point.h +++ b/gcc/analyzer/program-point.h @@ -179,7 +179,6 @@ public: } void print (pretty_printer *pp, const format &f) const; - void print_source_line (pretty_printer *pp) const; void dump () const; json::object *to_json () const; diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 07b440190c3aabc6b1caee675c0f35c5628f2184..b2d2cea455731f643a8257cc1eb6805b99937206 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -10198,8 +10198,8 @@ diagnostic to @file{@var{file}.@var{idx}.@var{kind}.epath.txt}. @opindex dump-analyzer-feasibility Dump internal details about the analyzer's search for feasible paths. The details are written in a form suitable for viewing with GraphViz -to filenames of the form @file{@var{file}.*.fg.dot} and -@file{@var{file}.*.tg.dot}. +to filenames of the form @file{@var{file}.*.fg.dot}, +@file{@var{file}.*.tg.dot}, and @file{@var{file}.*.fpath.txt}. @item -fdump-analyzer-json @opindex fdump-analyzer-json