From b89c930b8de11accf7a33195dfe3d050b51ff02a Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Mon, 13 Apr 2020 21:23:20 -0400 Subject: [PATCH 026/179] FIXME: start reworking region subclasses --- gcc/analyzer/region-model2.cc | 158 ++++++++++++++++++++++++++-------- gcc/analyzer/region-model2.h | 88 +++++++++++++++---- 2 files changed, 191 insertions(+), 55 deletions(-) diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc index 15e6302f5da..fbf29bce590 100644 --- a/gcc/analyzer/region-model2.cc +++ b/gcc/analyzer/region-model2.cc @@ -65,9 +65,11 @@ along with GCC; see the file COPYING3. If not see namespace ana { +#if 0 static region2 * make_region_for_type (region2 *parent_reg, tree type, region_model2_context *ctxt); +#endif /* Dump T to PP in language-independent form, for debugging/logging/dumping purposes. */ @@ -220,13 +222,13 @@ svalue2::dump_dot_to_pp (const region_model2 &model, /* FIXME. */ DEBUG_FUNCTION void -svalue2::dump () const +svalue2::dump (bool simple) const { pretty_printer pp; pp_format_decoder (&pp) = default_tree_printer; pp_show_color (&pp) = pp_show_color (global_dc->printer); pp.buffer->stream = stderr; - dump_to_pp (&pp); + dump_to_pp (&pp, simple); pp_newline (&pp); pp_flush (&pp); } @@ -248,13 +250,21 @@ svalue2::maybe_get_constant () const /* FIXME. */ void -region_svalue2::dump_to_pp (pretty_printer *pp) const +region_svalue2::dump_to_pp (pretty_printer *pp, bool simple) const { - pp_string (pp, "region_svalue2("); - print_quoted_type (pp, get_type ()); - pp_string (pp, ", "); - m_reg->dump_to_pp (pp); - pp_string (pp, ")"); + if (simple) + { + pp_string (pp, "&"); + m_reg->dump_to_pp (pp, simple); + } + else + { + pp_string (pp, "region_svalue2("); + print_quoted_type (pp, get_type ()); + pp_string (pp, ", "); + m_reg->dump_to_pp (pp, simple); + pp_string (pp, ")"); + } } /* Compare the fields of this region_svalue2 with OTHER, returning true @@ -466,13 +476,18 @@ region_svalue2::eval_condition (region_svalue2 *lhs, /* FIXME. */ void -constant_svalue2::dump_to_pp (pretty_printer *pp) const +constant_svalue2::dump_to_pp (pretty_printer *pp, bool simple) const { - pp_string (pp, "constant_svalue2("); - print_quoted_type (pp, get_type ()); - pp_string (pp, ", "); - dump_tree (pp, m_cst_expr); - pp_string (pp, ")"); + if (simple) + dump_tree (pp, m_cst_expr); + else + { + pp_string (pp, "constant_svalue2("); + print_quoted_type (pp, get_type ()); + pp_string (pp, ", "); + dump_tree (pp, m_cst_expr); + pp_string (pp, ")"); + } } /* Compare the fields of this constant_svalue2 with OTHER, returning true @@ -664,6 +679,7 @@ region2::kind_to_str (enum kind kind) { default: gcc_unreachable (); +#if 0 case RK_PRIMITIVE: return "primitive"; case RK_STRUCT: @@ -672,6 +688,7 @@ region2::kind_to_str (enum kind kind) return "union"; case RK_ARRAY: return "array"; +#endif case RK_FRAME: return "frame"; case RK_GLOBALS: @@ -686,8 +703,10 @@ region2::kind_to_str (enum kind kind) return "heap"; case RK_ROOT: return "root"; +#if 0 case RK_SYMBOLIC: return "symbolic"; +#endif } } @@ -826,6 +845,14 @@ region2::operator== (const region2 &other) const return this_sub.compare_fields (other_sub); } #endif + case RK_DECL: + { + const decl_region2 &this_sub + = (const decl_region2 &)*this; + const decl_region2 &other_sub + = (const decl_region2 &)other; + return this_sub.compare_fields (other_sub); + } case RK_FIELD: { const field_region2 &this_sub @@ -1308,20 +1335,14 @@ region2::dump_to_pp (const region_model2 &model, } #endif -void -region2::dump_to_pp (pretty_printer *pp) const -{ - pp_string (pp, "region2()"); // TODO: eliminate this base class impl -} - DEBUG_FUNCTION void -region2::dump () const +region2::dump (bool simple) const { pretty_printer pp; pp_format_decoder (&pp) = default_tree_printer; pp_show_color (&pp) = pp_show_color (global_dc->printer); pp.buffer->stream = stderr; - dump_to_pp (&pp); + dump_to_pp (&pp, simple); pp_newline (&pp); pp_flush (&pp); } @@ -1956,6 +1977,7 @@ map_region2::get_value_by_name (tree identifier, /* class struct_or_union_region2 : public map_region2. */ +#if 0 /* Implementation of map_region2::valid_key_p vfunc for struct_or_union_region2. */ @@ -2003,6 +2025,8 @@ union_region2::compare_fields (const union_region2 &other) const } #endif +#endif + /* class frame_region2 : public map_region2. */ /* Compare the fields of this frame_region2 with OTHER, returning true @@ -2069,6 +2093,15 @@ globals_region2::compare_fields (const globals_region2 &other) const } #endif +void +globals_region2::dump_to_pp (pretty_printer *pp, bool simple) const +{ + if (simple) + pp_string (pp, "::"); + else + pp_string (pp, "globals"); +} + /* Implementation of map_region2::valid_key_p vfunc for globals_region2. */ bool @@ -2100,6 +2133,8 @@ code_region2::valid_key_p (tree key) const /* class array_region2 : public region2. */ +#if 0 + /* array_region2's copy ctor. */ array_region2::array_region2 (const array_region2 &other) @@ -2354,6 +2389,8 @@ array_region2::constant_from_key (key_t key) return build_int_cst (index_type, key); } +#endif + /* class function_region2 : public map_region2. */ /* Compare the fields of this function_region2 with OTHER, returning true @@ -2684,6 +2721,12 @@ root_region2::compare_fields (const root_region2 &other) const } #endif +void +root_region2::dump_to_pp (pretty_printer *pp, bool simple) const +{ + gcc_unreachable (); +} + /* Implementation of region2::print_fields vfunc for root_region2. */ #if 0 void @@ -3079,6 +3122,38 @@ symbolic_region2::print_fields (const region_model2 &model, } #endif +/* class decl_region2 : public region2. */ + +void +decl_region2::add_to_hash (inchash::hash &hstate) const +{ + region2::add_to_hash (hstate); + hstate.add_ptr (m_decl); +} + +bool +decl_region2::compare_fields (const decl_region2 &other) const +{ + return m_decl == other.m_decl; +} + +void +decl_region2::dump_to_pp (pretty_printer *pp, bool simple) const +{ + if (simple) + pp_printf (pp, "%E", m_decl); + else + { + pp_string (pp, "decl_region2("); + get_parent_region ()->dump_to_pp (pp, simple); + pp_string (pp, ", "); + print_quoted_type (pp, get_type ()); + pp_printf (pp, ", %qE)", m_decl); + } +} + +/* class field_region2 : public region2. */ + void field_region2::add_to_hash (inchash::hash &hstate) const { @@ -3093,13 +3168,22 @@ field_region2::compare_fields (const field_region2 &other) const } void -field_region2::dump_to_pp (pretty_printer *pp) const +field_region2::dump_to_pp (pretty_printer *pp, bool simple) const { - pp_string (pp, "field_region2("); - get_parent_region ()->dump_to_pp (pp); - pp_string (pp, ", "); - print_quoted_type (pp, get_type ()); - pp_printf (pp, ", %qE)", m_field); + if (simple) + { + get_parent_region ()->dump_to_pp (pp, simple); + pp_string (pp, "."); + pp_printf (pp, "%E", m_field); + } + else + { + pp_string (pp, "field_region2("); + get_parent_region ()->dump_to_pp (pp, simple); + pp_string (pp, ", "); + print_quoted_type (pp, get_type ()); + pp_printf (pp, ", %qE)", m_field); + } } /* class region_model2_manager. */ @@ -3132,17 +3216,17 @@ region_model2_manager::get_or_create_constant_svalue2 (tree cst_expr) /* FIXME. */ -region2 * +decl_region2 * region_model2_manager::get_region_for_global (tree expr, region_model2_context *ctxt) { gcc_assert (TREE_CODE (expr) == VAR_DECL); - region2 **slot = m_globals_map.get (expr); + decl_region2 **slot = m_globals_map.get (expr); if (slot) return *slot; - region2 *reg = make_region_for_type (&m_globals_region, TREE_TYPE (expr), - ctxt); + decl_region2 *reg + = new decl_region2 (&m_globals_region, expr); m_globals_map.put (expr, reg); return reg; } @@ -3399,9 +3483,9 @@ region_model2::dump_to_pp (pretty_printer *pp, bool summarize) const pp_string (pp, ", "); region2 *reg = (*iter).first; svalue2 *sval = (*iter).second; - reg->dump_to_pp (pp); + reg->dump_to_pp (pp, summarize); pp_string (pp, ": "); - sval->dump_to_pp (pp); + sval->dump_to_pp (pp, summarize); } #if 0 if (summarize) @@ -3502,6 +3586,7 @@ region_model2::dump (FILE *fp, bool summarize) const pp_show_color (&pp) = pp_show_color (global_dc->printer); pp.buffer->stream = fp; dump_to_pp (&pp, summarize); + pp_newline (&pp); pp_flush (&pp); } @@ -6052,7 +6137,7 @@ region_model2::replace_svalue2 (svalue2 *sval, svalue2 *new_sval) /* Make a region2 of an appropriate subclass for TYPE, with parent PARENT_REG, or return NULL for types we don't yet know how to handle. */ - +#if 0 static region2 * make_region_for_type (region2 *parent_reg, tree type, region_model2_context *ctxt) @@ -6090,6 +6175,7 @@ make_region_for_type (region2 *parent_reg, tree type, dump_location_t ()); #endif } +#endif /* Helper class for region_model2::purge_unused_svalue2s. */ @@ -6658,7 +6744,7 @@ region_model2::get_fndecl_for_call (const gcall *call, /* Dump a multiline representation of this merger to PP. */ #if 0 void -model_merger::dump_to_pp (pretty_printer *pp) const +model_merger::dump_to_pp (pretty_printer *pp, bool simple) const { pp_string (pp, "model A:"); pp_newline (pp); diff --git a/gcc/analyzer/region-model2.h b/gcc/analyzer/region-model2.h index 69905fb9d94..81e8542c949 100644 --- a/gcc/analyzer/region-model2.h +++ b/gcc/analyzer/region-model2.h @@ -49,7 +49,12 @@ along with GCC; see the file COPYING3. If not see - should there still be a root_region? or should those things go in the ext_state (or something owned by ext_state: region_model2_manager) Hopefully this is a huge simplification, and (I hope) avoids lots of heap - churn as states are copied. */ + churn as states are copied. + + Other ideas: + - region subclasses no longer represent internal structure, but instead + represent how the regions are reached. So e.g. a global + "struct coord c;" is now a decl_region, rather than a struct_region. */ /* A tree, extended with stack frame information for locals, so that we can distinguish between different values of locals within a potentially @@ -169,8 +174,8 @@ public: pretty_printer *pp) const; #endif - virtual void dump_to_pp (pretty_printer *pp) const = 0; - void dump () const; + virtual void dump_to_pp (pretty_printer *pp, bool simple) const = 0; + void dump (bool simple=true) const; virtual region_svalue2 *dyn_cast_region_svalue2 () { return NULL; } virtual constant_svalue2 *dyn_cast_constant_svalue2 () { return NULL; } @@ -221,7 +226,7 @@ public: FINAL OVERRIDE; #endif - void dump_to_pp (pretty_printer *pp) const FINAL OVERRIDE; + void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE; region_svalue2 *dyn_cast_region_svalue2 () FINAL OVERRIDE { return this; } @@ -282,7 +287,7 @@ public: #endif enum kind get_kind () const FINAL OVERRIDE { return SK_CONSTANT; } - void dump_to_pp (pretty_printer *pp) const FINAL OVERRIDE; + void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE; #if 0 void add_to_hash (inchash::hash &hstate) const FINAL OVERRIDE; @@ -344,7 +349,7 @@ public: #endif enum kind get_kind () const FINAL OVERRIDE { return SK_UNKNOWN; } - void dump_to_pp (pretty_printer *pp) const FINAL OVERRIDE; + void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE; #if 0 void add_to_hash (inchash::hash &hstate) const FINAL OVERRIDE; @@ -391,7 +396,7 @@ public: #endif enum kind get_kind () const FINAL OVERRIDE { return SK_POISONED; } - void dump_to_pp (pretty_printer *pp) const FINAL OVERRIDE; + void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE; #if 0 void add_to_hash (inchash::hash &hstate) const FINAL OVERRIDE; @@ -462,7 +467,7 @@ public: #endif enum kind get_kind () const FINAL OVERRIDE { return SK_SETJMP; } - void dump_to_pp (pretty_printer *pp) const FINAL OVERRIDE; + void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE; #if 0 void add_to_hash (inchash::hash &hstate) const FINAL OVERRIDE; @@ -489,6 +494,10 @@ public: The class hierarchy looks like this (using indentation to show inheritance, and with region_kinds shown for the concrete subclasses): + FIXME: this needs a rewrite; reorganizing regions by identity, rather than + structure. So e.g. a global "struct coord c;" is now a decl_region, rather + than a struct_region. + region primitive_region (RK_PRIMITIVE) map_region @@ -528,18 +537,19 @@ public: of region2. */ enum kind { - RK_PRIMITIVE, - RK_STRUCT, - RK_UNION, + //RK_PRIMITIVE, + //RK_STRUCT, + //RK_UNION, RK_FRAME, RK_GLOBALS, RK_CODE, RK_FUNCTION, - RK_ARRAY, + //RK_ARRAY, RK_STACK, RK_HEAP, RK_ROOT, - RK_SYMBOLIC, + //RK_SYMBOLIC, + RK_DECL, RK_FIELD }; static const char *kind_to_str (enum kind); @@ -589,8 +599,8 @@ public: const char *prefix, bool is_last_child) const; - virtual void dump_to_pp (pretty_printer *pp) const; // = 0; - void dump () const; + virtual void dump_to_pp (pretty_printer *pp, bool simple) const = 0; + void dump (bool simple) const; #if 0 virtual void dump_child_label (const region_model2 &model, @@ -643,6 +653,8 @@ is_a_helper ::test (region *) namespace ana { +#if 0 + /* Concrete region subclass for storing "primitive" types (integral types, pointers, etc). */ @@ -660,6 +672,7 @@ public: enum region2::kind get_kind () const FINAL OVERRIDE { return RK_PRIMITIVE; } }; +#endif /* A region2 that has children identified by tree keys. For example a stack frame has subregion2s per local, and a region2 for a struct has subregion2s per field. */ @@ -742,6 +755,7 @@ is_a_helper ::test (region2 *reg) return (reg->dyn_cast_map_region2 () != NULL); } +#if 0 namespace ana { /* Abstract subclass representing a region2 with fields @@ -832,6 +846,8 @@ is_a_helper ::test (region2 *reg) return reg->get_kind () == region2::RK_UNION; } +#endif + namespace ana { /* Abstract map_region2 subclass for accessing decls, used as a base class @@ -925,6 +941,7 @@ class globals_region2 : public scope_region2 region2 *clone () const FINAL OVERRIDE; #endif enum kind get_kind () const FINAL OVERRIDE { return RK_GLOBALS; } + void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE; /* map_region2 vfuncs. */ bool valid_key_p (tree key) const FINAL OVERRIDE; @@ -1026,6 +1043,7 @@ is_a_helper ::test (region2 *reg) return reg->get_kind () == region2::RK_FUNCTION; } +#if 0 namespace ana { /* Concrete region2 subclass representing an array (or an array-like view @@ -1244,6 +1262,8 @@ is_a_helper ::test (region2 *reg) return reg->get_kind () == region2::RK_HEAP; } +#endif + namespace ana { /* Concrete region2 subclass. The root region2, containing all region2s @@ -1263,6 +1283,7 @@ public: #endif enum kind get_kind () const FINAL OVERRIDE { return RK_ROOT; } + void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE; #if 0 void dump_child_label (const region_model2 &model, @@ -1333,6 +1354,7 @@ is_a_helper ::test (region2 *reg) namespace ana { +#if 0 /* Concrete region2 subclass: a region2 to use when dereferencing an unknown pointer. */ @@ -1366,6 +1388,34 @@ public: bool m_possibly_null; }; +#endif + +/* FIXME. */ + +class decl_region2 : public region2 +{ +public: + decl_region2 (region2 *parent, tree decl) + : region2 (parent, TREE_TYPE (decl)), m_decl (decl) + {} + +#if 0 + region2 *clone () const FINAL OVERRIDE; +#endif + + bool compare_fields (const decl_region2 &other) const; + + enum region2::kind get_kind () const FINAL OVERRIDE { return RK_DECL; } + + void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE; + +protected: + void add_to_hash (inchash::hash &hstate) const OVERRIDE; + +private: + tree m_decl; +}; + /* FIXME. */ class field_region2 : public region2 @@ -1383,7 +1433,7 @@ public: enum region2::kind get_kind () const FINAL OVERRIDE { return RK_FIELD; } - void dump_to_pp (pretty_printer *pp) const FINAL OVERRIDE; + void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE; protected: void add_to_hash (inchash::hash &hstate) const OVERRIDE; @@ -1405,8 +1455,8 @@ public: region_model2_context *ctxt); region2 *get_region_for_label (tree label, region_model2_context *ctxt); - region2 *get_region_for_global (tree expr, - region_model2_context *ctxt); + decl_region2 *get_region_for_global (tree expr, + region_model2_context *ctxt); region2 *get_field_region (region2 *parent, tree field, region_model2_context *ctxt); @@ -1417,7 +1467,7 @@ private: constants_map_t m_constants_map; globals_region2 m_globals_region; - typedef hash_map globals_map_t; + typedef hash_map globals_map_t; typedef globals_map_t::iterator globals_iterator_t; globals_map_t m_globals_map; -- 2.21.0