diff options
Diffstat (limited to 'gcc/analyzer/store.cc')
-rw-r--r-- | gcc/analyzer/store.cc | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc index a36de13..d14cfa3 100644 --- a/gcc/analyzer/store.cc +++ b/gcc/analyzer/store.cc @@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #define INCLUDE_MEMORY +#define INCLUDE_VECTOR #include "system.h" #include "coretypes.h" #include "tree.h" @@ -54,6 +55,7 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/call-summary.h" #include "analyzer/analyzer-selftests.h" #include "stor-layout.h" +#include "text-art/tree-widget.h" #if ENABLE_ANALYZER @@ -810,6 +812,56 @@ binding_map::to_json () const return map_obj; } +/* Add a child to PARENT_WIDGET expressing a binding between + KEY and SVAL. */ + +static void +add_binding_to_tree_widget (text_art::tree_widget &parent_widget, + const text_art::dump_widget_info &dwi, + const binding_key *key, + const svalue *sval) +{ + pretty_printer the_pp; + pretty_printer * const pp = &the_pp; + pp_format_decoder (pp) = default_tree_printer; + pp_show_color (pp) = true; + const bool simple = true; + + key->dump_to_pp (pp, simple); + pp_string (pp, ": "); + if (tree t = sval->get_type ()) + dump_quoted_tree (pp, t); + pp_string (pp, " {"); + sval->dump_to_pp (pp, simple); + pp_string (pp, "}"); + + parent_widget.add_child (text_art::tree_widget::make (dwi, pp)); +} + +void +binding_map::add_to_tree_widget (text_art::tree_widget &parent_widget, + const text_art::dump_widget_info &dwi) const +{ + auto_vec <const binding_key *> binding_keys; + for (map_t::iterator iter = m_map.begin (); + iter != m_map.end (); ++iter) + { + const binding_key *key = (*iter).first; + binding_keys.safe_push (key); + } + binding_keys.qsort (binding_key::cmp_ptrs); + + const binding_key *key; + unsigned i; + FOR_EACH_VEC_ELT (binding_keys, i, key) + { + const svalue *sval = *const_cast <map_t &> (m_map).get (key); + add_binding_to_tree_widget (parent_widget, dwi, + key, sval); + } +} + + /* Comparator for imposing an order on binding_maps. */ int @@ -1399,6 +1451,48 @@ binding_cluster::to_json () const return cluster_obj; } +std::unique_ptr<text_art::widget> +binding_cluster::make_dump_widget (const text_art::dump_widget_info &dwi, + store_manager *mgr) const +{ + pretty_printer the_pp; + pretty_printer * const pp = &the_pp; + pp_format_decoder (pp) = default_tree_printer; + pp_show_color (pp) = true; + const bool simple = true; + + m_base_region->dump_to_pp (pp, simple); + pp_string (pp, ": "); + + if (const svalue *sval = maybe_get_simple_value (mgr)) + { + /* Special-case to simplify dumps for the common case where + we just have one value directly bound to the whole of a + region. */ + sval->dump_to_pp (pp, simple); + if (escaped_p ()) + pp_string (pp, " (ESCAPED)"); + if (touched_p ()) + pp_string (pp, " (TOUCHED)"); + + return text_art::tree_widget::make (dwi, pp); + } + else + { + if (escaped_p ()) + pp_string (pp, " (ESCAPED)"); + if (touched_p ()) + pp_string (pp, " (TOUCHED)"); + + std::unique_ptr<text_art::tree_widget> cluster_widget + (text_art::tree_widget::make (dwi, pp)); + + m_map.add_to_tree_widget (*cluster_widget, dwi); + + return cluster_widget; + } +} + /* Add a binding of SVAL of kind KIND to REG, unpacking SVAL if it is a compound_sval. */ @@ -2613,6 +2707,68 @@ store::to_json () const return store_obj; } +std::unique_ptr<text_art::widget> +store::make_dump_widget (const text_art::dump_widget_info &dwi, + store_manager *mgr) const +{ + std::unique_ptr<text_art::tree_widget> store_widget + (text_art::tree_widget::make (dwi, "Store")); + + store_widget->add_child + (text_art::tree_widget::from_fmt (dwi, nullptr, + "m_called_unknown_fn: %s", + m_called_unknown_fn ? "true" : "false")); + + /* Sort into some deterministic order. */ + auto_vec<const region *> base_regions; + for (cluster_map_t::iterator iter = m_cluster_map.begin (); + iter != m_cluster_map.end (); ++iter) + { + const region *base_reg = (*iter).first; + base_regions.safe_push (base_reg); + } + base_regions.qsort (region::cmp_ptr_ptr); + + /* Gather clusters, organize by parent region, so that we can group + together locals, globals, etc. */ + auto_vec<const region *> parent_regions; + get_sorted_parent_regions (&parent_regions, base_regions); + + const region *parent_reg; + unsigned i; + FOR_EACH_VEC_ELT (parent_regions, i, parent_reg) + { + gcc_assert (parent_reg); + + pretty_printer the_pp; + pretty_printer * const pp = &the_pp; + pp_format_decoder (pp) = default_tree_printer; + pp_show_color (pp) = true; + const bool simple = true; + + parent_reg->dump_to_pp (pp, simple); + + std::unique_ptr<text_art::tree_widget> parent_reg_widget + (text_art::tree_widget::make (dwi, pp)); + + const region *base_reg; + unsigned j; + FOR_EACH_VEC_ELT (base_regions, j, base_reg) + { + /* This is O(N * M), but N ought to be small. */ + if (base_reg->get_parent_region () != parent_reg) + continue; + binding_cluster *cluster + = *const_cast<cluster_map_t &> (m_cluster_map).get (base_reg); + parent_reg_widget->add_child + (cluster->make_dump_widget (dwi, mgr)); + } + store_widget->add_child (std::move (parent_reg_widget)); + } + + return store_widget; +} + /* Get any svalue bound to REG, or NULL. */ const svalue * |