From 40b14a2a6868ed0faaf3bd5db7e12e4dae4d66c3 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 6 Apr 2020 17:10:17 -0400
Subject: [PATCH 008/315] FIXME: begin using uniq_manager in revamp-state.h/cc

---
 gcc/analyzer/analyzer-selftests.cc |   1 +
 gcc/analyzer/analyzer-selftests.h  |   1 +
 gcc/analyzer/analyzer.h            |   2 +
 gcc/analyzer/engine.cc             |   7 +-
 gcc/analyzer/program-state.cc      |   2 +-
 gcc/analyzer/program-state.h       |   8 +-
 gcc/analyzer/revamp-state.cc       | 132 +++++++++++++++++++++++++++--
 gcc/analyzer/revamp-state.h        |  62 +++++++++++++-
 gcc/analyzer/uniq-manager.h        |   1 +
 9 files changed, 204 insertions(+), 12 deletions(-)

diff --git a/gcc/analyzer/analyzer-selftests.cc b/gcc/analyzer/analyzer-selftests.cc
index c157bda3bff..30f83c215c4 100644
--- a/gcc/analyzer/analyzer-selftests.cc
+++ b/gcc/analyzer/analyzer-selftests.cc
@@ -56,6 +56,7 @@ run_analyzer_selftests ()
   analyzer_program_point_cc_tests ();
   analyzer_program_state_cc_tests ();
   analyzer_region_model_cc_tests ();
+  analyzer_revamp_state_cc_tests ();
   analyzer_sm_file_cc_tests ();
   analyzer_sm_signal_cc_tests ();
   analyzer_uniq_manager_cc_tests ();
diff --git a/gcc/analyzer/analyzer-selftests.h b/gcc/analyzer/analyzer-selftests.h
index 29c2aeae120..cca462e4cc2 100644
--- a/gcc/analyzer/analyzer-selftests.h
+++ b/gcc/analyzer/analyzer-selftests.h
@@ -39,6 +39,7 @@ extern void analyzer_function_set_cc_tests ();
 extern void analyzer_program_point_cc_tests ();
 extern void analyzer_program_state_cc_tests ();
 extern void analyzer_region_model_cc_tests ();
+extern void analyzer_revamp_state_cc_tests ();
 extern void analyzer_sm_file_cc_tests ();
 extern void analyzer_sm_signal_cc_tests ();
 extern void analyzer_uniq_manager_cc_tests ();
diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h
index a7401128517..95cec3fdad1 100644
--- a/gcc/analyzer/analyzer.h
+++ b/gcc/analyzer/analyzer.h
@@ -73,6 +73,8 @@ class state_purge_per_ssa_name;
 class state_change;
 class rewind_info_t;
 
+class engine;
+
 /* Forward decls of functions.  */
 
 extern void dump_quoted_tree (pretty_printer *pp, tree t);
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 8108ec9f0e9..08c67aa5f1c 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -3988,6 +3988,10 @@ impl_run_checkers (logger *logger)
   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
     node->get_untransformed_body ();
 
+  engine *eng = NULL;
+  if (getenv ("REVAMP"))
+    eng = new engine ();
+
   /* Create the supergraph.  */
   supergraph sg (logger);
 
@@ -4028,7 +4032,7 @@ impl_run_checkers (logger *logger)
     }
 
   /* Extrinsic state shared by nodes in the graph.  */
-  const extrinsic_state ext_state (checkers, logger);
+  const extrinsic_state ext_state (checkers, logger, eng);
 
   const analysis_plan plan (sg, logger);
 
@@ -4075,6 +4079,7 @@ impl_run_checkers (logger *logger)
     }
 
   delete purge_map;
+  delete eng;
 }
 
 /* External entrypoint to the analysis "engine".
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index 813cd38b422..858c7b2006f 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -600,7 +600,7 @@ program_state::program_state (const extrinsic_state &ext_state)
   m_checker_states (ext_state.get_num_checkers ()),
   m_valid (true)
 {
-  if (getenv ("REVAMP"))
+  if (ext_state.get_engine ())
     m_revamp_state = new revamp_state (ext_state);
   else
     m_region_model = new region_model ();
diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h
index 60c9e975ed1..b1f43ef7b02 100644
--- a/gcc/analyzer/program-state.h
+++ b/gcc/analyzer/program-state.h
@@ -29,8 +29,9 @@ class extrinsic_state
 {
 public:
   extrinsic_state (auto_delete_vec <state_machine> &checkers,
-		   logger *logger = NULL)
-  : m_checkers (checkers), m_logger (logger)
+		   logger *logger = NULL,
+		   engine *eng = NULL)
+  : m_checkers (checkers), m_logger (logger), m_engine (eng)
   {
   }
 
@@ -52,11 +53,14 @@ public:
   void dump_to_file (FILE *outf) const;
   void dump () const;
 
+  engine *get_engine () const { return m_engine; }
+
 private:
   /* The state machines.  */
   auto_delete_vec <state_machine> &m_checkers;
 
   logger *m_logger;
+  engine *m_engine;
 };
 
 } // namespace ana
diff --git a/gcc/analyzer/revamp-state.cc b/gcc/analyzer/revamp-state.cc
index 5641692c3d1..bccd4a61992 100644
--- a/gcc/analyzer/revamp-state.cc
+++ b/gcc/analyzer/revamp-state.cc
@@ -68,6 +68,22 @@ namespace ana {
 
 /* class sval.  */
 
+hashval_t
+sval::hash () const
+{
+  inchash::hash hstate;
+  hstate.add_int (get_kind ());
+  return hstate.end ();
+}
+
+bool
+sval::operator== (const sval &other) const
+{
+  if (get_kind () != other.get_kind ())
+    return false;
+  return cmp_fields (other);
+}
+
 DEBUG_FUNCTION void
 sval::dump ()
 {
@@ -79,6 +95,49 @@ sval::dump ()
   pp_flush (&pp);
 }
 
+/* hash implementations.  */
+
+void
+cst_sval::add_to_hash (inchash::hash &hstate) const
+{
+  inchash::add_expr (m_cst, hstate);
+}
+
+void
+var_decl_region::add_to_hash (inchash::hash &hstate) const
+{
+  inchash::add_expr (m_decl, hstate);
+}
+
+void
+ssa_name_region::add_to_hash (inchash::hash &hstate) const
+{
+  inchash::add_expr (m_name, hstate);
+}
+
+/* cmp_fields implementations.  */
+
+bool
+cst_sval::cmp_fields (const sval &base_other) const
+{
+  const cst_sval &sub_other = (const cst_sval &)base_other;
+  return m_cst == sub_other.m_cst;
+}
+
+bool
+var_decl_region::cmp_fields (const sval &base_other) const
+{
+  const var_decl_region &sub_other = (const var_decl_region &)base_other;
+  return m_decl == sub_other.m_decl;
+}
+
+bool
+ssa_name_region::cmp_fields (const sval &base_other) const
+{
+  const ssa_name_region &sub_other = (const ssa_name_region &)base_other;
+  return m_name == sub_other.m_name;
+}
+
 /* dump_to_pp implementations.  */
 
 void
@@ -102,7 +161,7 @@ ssa_name_region::dump_to_pp (pretty_printer *pp) const
 /* class store.  */
 
 void
-store::bind (region_val *dst, sval *val)
+store::bind (const region_val *dst, const sval *val)
 {
   m_map.put (dst, val);
   dump ();
@@ -116,8 +175,8 @@ store::to_json () const
        iter != m_map.end ();
        ++iter)
     {
-      region_val *reg = (*iter).first;
-      sval *val = (*iter).second;
+      const region_val *reg = (*iter).first;
+      const sval *val = (*iter).second;
       json::object *item_obj = new json::object ();
       // TODO
       store_arr->append (item_obj);
@@ -146,8 +205,8 @@ store::dump_to_pp (pretty_printer *pp) const
     {
       if (iter != m_map.begin ())
 	pp_string (pp, ", ");
-      region_val *reg = (*iter).first;
-      sval *val = (*iter).second;
+      const region_val *reg = (*iter).first;
+      const sval *val = (*iter).second;
       reg->dump_to_pp (pp);
       pp_string (pp, ": ");
       val->dump_to_pp (pp);
@@ -378,6 +437,69 @@ revamp_state::to_json () const
   return state_obj;
 }
 
+/* class engine.  */
+
+engine::engine ()
+{
+  m_sval_mgr = new uniq_manager<sval> ();
+}
+
+engine::~engine ()
+{
+  delete m_sval_mgr;
+}
+
+const sval *
+engine::consolidate_sval (sval *s)
+{
+  return m_sval_mgr->consolidate (s);
+}
+
+size_t
+engine::get_num_svals () const
+{
+  return m_sval_mgr->get_count ();
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+static void
+test_consolidation ()
+{
+  engine eng;
+  ASSERT_EQ (eng.get_num_svals (), 0);
+
+  tree int_17 = build_int_cst (integer_type_node, 17);
+  const sval *cst17_0 = eng.consolidate_sval (new cst_sval (int_17));
+  ASSERT_EQ (eng.get_num_svals (), 1);
+  const sval *cst17_1 = eng.consolidate_sval (new cst_sval (int_17));
+  ASSERT_EQ (eng.get_num_svals (), 1);
+  ASSERT_EQ (cst17_0, cst17_1);
+
+  tree int_42 = build_int_cst (integer_type_node, 42);
+  const sval *cst42_0 = eng.consolidate_sval (new cst_sval (int_42));
+  ASSERT_EQ (eng.get_num_svals (), 2);
+  const sval *cst42_1 = eng.consolidate_sval (new cst_sval (int_42));
+  ASSERT_EQ (eng.get_num_svals (), 2);
+  ASSERT_EQ (cst42_0, cst42_1);
+
+  ASSERT_NE (cst17_0, cst42_0);
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+analyzer_revamp_state_cc_tests ()
+{
+  test_consolidation ();
+}
+
+} // namespace selftest
+
+#endif /* CHECKING_P */
+
 } // namespace ana
 
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/revamp-state.h b/gcc/analyzer/revamp-state.h
index 182d21cee11..a7a04f63761 100644
--- a/gcc/analyzer/revamp-state.h
+++ b/gcc/analyzer/revamp-state.h
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_ANALYZER_REVAMP_STATE_H
 
 #include "json.h"
+#include "uniq-manager.h"
 
 namespace ana {
 
@@ -31,9 +32,34 @@ class region_val;
 class sval
 {
 public:
+  enum kind
+  {
+   SK_cst_sval,
+   SK_var_decl_region,
+   SK_ssa_name_region
+  };
+  virtual ~sval () {}
+
+  virtual kind get_kind () const = 0;
+
+  /* For use with uniq_manager.  */
+  hashval_t hash () const;
+  bool operator== (const sval &other) const;
+
   void dump ();
   virtual void dump_to_pp (pretty_printer *pp) const = 0;
   virtual region_val *dyn_cast_region_val () { return NULL; }
+
+ protected:
+  virtual void add_to_hash (inchash::hash &hstate) const = 0;
+  virtual bool cmp_fields (const sval &other) const = 0;
+
+ private:
+#if 0
+  /* For implementing operator==.  */
+  bool template <typename Subclass>
+  compare_fields (const Subclass &other) const;
+#endif
 };
 
 class nonloc_val : public sval
@@ -48,8 +74,14 @@ public:
     gcc_assert (CONSTANT_CLASS_P (cst));
   }
 
+  kind get_kind () const FINAL OVERRIDE { return SK_cst_sval; }
+
   void dump_to_pp (pretty_printer *pp) const FINAL OVERRIDE;
 
+ protected:
+  void add_to_hash (inchash::hash &hstate) const FINAL OVERRIDE;
+  bool cmp_fields (const sval &other) const FINAL OVERRIDE;
+
 private:
   tree m_cst;
 };
@@ -76,8 +108,13 @@ public:
     gcc_assert (TREE_CODE (decl) == VAR_DECL);
   }
 
+  kind get_kind () const FINAL OVERRIDE { return SK_var_decl_region; }
   void dump_to_pp (pretty_printer *pp) const FINAL OVERRIDE;
 
+ protected:
+  void add_to_hash (inchash::hash &hstate) const FINAL OVERRIDE;
+  bool cmp_fields (const sval &other) const FINAL OVERRIDE;
+
 private:
   tree m_decl;
 };
@@ -90,19 +127,24 @@ public:
     gcc_assert (TREE_CODE (name) == SSA_NAME);
   }
 
+  kind get_kind () const FINAL OVERRIDE { return SK_ssa_name_region; }
   void dump_to_pp (pretty_printer *pp) const FINAL OVERRIDE;
 
-private:
+ protected:
+  void add_to_hash (inchash::hash &hstate) const FINAL OVERRIDE;
+  bool cmp_fields (const sval &other) const FINAL OVERRIDE;
+
+ private:
   tree m_name;
 };
 
 class store
 {
  public:
-  typedef hash_map <region_val *, sval *> map_t; // or region * ?
+  typedef hash_map <const region_val *, const sval *> map_t; // or region * ?
   typedef map_t::iterator iterator_t;
 
-  void bind (region_val *dst, sval *val);
+  void bind (const region_val *dst, const sval *val);
 
   json::value *to_json () const;
   void dump ();
@@ -153,6 +195,20 @@ private:
   store *m_store;
 };
 
+class engine
+{
+ public:
+  engine ();
+  ~engine ();
+
+  const sval *consolidate_sval (sval *s);
+  size_t get_num_svals () const;
+
+ private:
+  uniq_manager<sval> *m_sval_mgr;
+  //uniq_manager *m_sval_mgr;
+};
+
 } // namespace ana
 
 #endif /* GCC_ANALYZER_REVAMP_STATE_H */
diff --git a/gcc/analyzer/uniq-manager.h b/gcc/analyzer/uniq-manager.h
index c56630d7d61..bee9167f0e8 100644
--- a/gcc/analyzer/uniq-manager.h
+++ b/gcc/analyzer/uniq-manager.h
@@ -173,6 +173,7 @@ class uniq_manager
   size_t get_count () const { return m_map.elements (); }
 
  private:
+  // FIXME: should this just be a hash_set?
   map_t m_map;
 };
 
-- 
2.26.2

