From 810af56fea898e0d0b55417750c8c14a75e7b125 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 16 Apr 2020 15:01:54 -0400
Subject: [PATCH 49/96] FIXME: introduce store2 and store2_manager classes

---
 gcc/analyzer/analyzer.h       |   1 +
 gcc/analyzer/region-model2.cc | 119 +++++++++++++++++++++-------------
 gcc/analyzer/region-model2.h  |  80 ++++++++++++++---------
 3 files changed, 123 insertions(+), 77 deletions(-)

diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h
index a85edb99db0..ed81438a411 100644
--- a/gcc/analyzer/analyzer.h
+++ b/gcc/analyzer/analyzer.h
@@ -66,6 +66,7 @@ class region2;
   class symbolic_region2;
   class field_region2;
 class region_model2_manager;
+class store2_manager;
 class region_model2;
 class region_model2_context;
 
diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc
index 0e3aa2f7c63..d541a57cc18 100644
--- a/gcc/analyzer/region-model2.cc
+++ b/gcc/analyzer/region-model2.cc
@@ -2803,7 +2803,7 @@ element_region2::add_to_hash (inchash::hash &hstate) const
 /* class binding_key2.  */
 
 const binding_key2 *
-binding_key2::make (region_model2_manager *mgr, region2 *r, enum kind kind)
+binding_key2::make (store2_manager *mgr, region2 *r, enum kind kind)
 {
   region_offset offset = r->get_offset ();
   // FIXME: what if symbolic vs concrete?
@@ -2882,7 +2882,7 @@ binding_cluster2::dump_to_pp (pretty_printer *pp, bool simple) const
 }
 
 void
-binding_cluster2::bind (region_model2_manager *mgr,
+binding_cluster2::bind (store2_manager *mgr,
 			region2 *reg, svalue2 *val)
 {
   const binding_key2 *binding
@@ -2891,8 +2891,9 @@ binding_cluster2::bind (region_model2_manager *mgr,
 }
 
 svalue2 *
-binding_cluster2::get_binding (region_model2_manager *mgr, region2 *reg,
-			      binding_key2::kind kind) const
+binding_cluster2::get_binding (store2_manager *mgr,
+			       region2 *reg,
+			       binding_key2::kind kind) const
 {
   const binding_key2 *binding = binding_key2::make (mgr, reg, kind);
   svalue2 **slot = const_cast<map_t &> (m_map).get (binding);
@@ -2921,8 +2922,8 @@ binding_cluster2::get_overlapping_bindings (region2 */*reg*/,
 /* FIXME.  */
 
 void
-binding_cluster2::remove_overlapping_bindings (region_model2_manager */*mgr*/,
-					      region2 *reg)
+binding_cluster2::remove_overlapping_bindings (store2_manager */*mgr*/,
+					       region2 *reg)
 {
   auto_vec<const binding_key2 *> bindings;
   get_overlapping_bindings (reg, &bindings);
@@ -3053,7 +3054,7 @@ region_model2_manager::get_symbolic_region (svalue2 *sval)
 /* binding consolidation.  */
 
 const concrete_binding2 *
-region_model2_manager::get_concrete_binding (const region2 *reg,
+store2_manager::get_concrete_binding (const region2 *reg,
 					     enum binding_key2::kind kind,
 					     concrete_binding2::bit_offset_t offset)
 {
@@ -3062,9 +3063,9 @@ region_model2_manager::get_concrete_binding (const region2 *reg,
 }
 
 const symbolic_binding2 *
-region_model2_manager::get_symbolic_binding (const region2 *reg,
-					     enum binding_key2::kind kind,
-					     region2 *concrete_offset_region)
+store2_manager::get_symbolic_binding (const region2 *reg,
+				      enum binding_key2::kind kind,
+				      region2 *concrete_offset_region)
 {
   symbolic_binding2 *b
     = new symbolic_binding2 (reg, kind, concrete_offset_region);
@@ -3289,18 +3290,14 @@ region_model2::dump_dot (const char *path) const
 }
 #endif
 
-// FIXME:
-/* Dump a multiline representation of this model to PP, showing the
-   region2 hierarchy, the svalue2s, and any constraints.
 
-   If SUMMARIZE is true, show only the most pertinent information,
-   in a form that attempts to be less verbose.
-   Otherwise, show all information.  */
+// TODO: move this to its own header and source file
+
+/* class store2.  */
 
 void
-region_model2::dump_to_pp (pretty_printer *pp, bool summarize) const
+store2::dump_to_pp (pretty_printer *pp, bool summarize) const
 {
-#if 1
   /* Sort into some deterministic order.  */
   auto_vec<const region2 *> base_regions;
   for (cluster_map_t::iterator iter = m_cluster_map.begin ();
@@ -3325,6 +3322,22 @@ region_model2::dump_to_pp (pretty_printer *pp, bool summarize) const
       cluster->dump_to_pp (pp, summarize);
       pp_string (pp, "}");
     }
+}
+
+// FIXME:
+/* Dump a multiline representation of this model to PP, showing the
+   region2 hierarchy, the svalue2s, and any constraints.
+
+   If SUMMARIZE is true, show only the most pertinent information,
+   in a form that attempts to be less verbose.
+   Otherwise, show all information.  */
+
+void
+region_model2::dump_to_pp (pretty_printer *pp, bool summarize) const
+{
+#if 1
+  m_store.dump_to_pp (pp, summarize);
+
 #else
   for (store_map_t::iterator iter = m_store_map.begin ();
        iter != m_store_map.end (); ++iter)
@@ -4659,7 +4672,8 @@ region_model2::get_rvalue (tree expr,
 svalue2 *
 region_model2::get_store_value (region2 *reg)
 {
-  svalue2 *sval = get_direct_binding (reg);
+  svalue2 *sval
+    = m_store.get_direct_binding (m_mgr->get_store2_manager (), reg);
   if (sval)
     return sval;
 
@@ -4668,28 +4682,49 @@ region_model2::get_store_value (region2 *reg)
 }
 
 svalue2 *
-region_model2::get_direct_binding (region2 *reg)
+store2::get_direct_binding (store2_manager *mgr, region2 *reg)
 {
-  return get_binding (reg, binding_key2::BK_direct);
+  return get_binding (mgr, reg, binding_key2::BK_direct);
 }
 
 svalue2 *
-region_model2::get_default_binding (region2 *reg)
+store2::get_default_binding (store2_manager *mgr, region2 *reg)
 {
-  return get_binding (reg, binding_key2::BK_direct);
+  return get_binding (mgr, reg, binding_key2::BK_direct);
 }
 
 svalue2 *
-region_model2::get_binding (region2 *reg,
-			    binding_key2::kind kind)
+store2::get_binding (store2_manager *mgr,
+		     region2 *reg,
+		     binding_key2::kind kind)
 {
   const region2 *base_reg = reg->get_base_region ();
   binding_cluster2 **cluster_slot = m_cluster_map.get (base_reg);
   if (!cluster_slot)
     return NULL;
-  return (*cluster_slot)->get_binding (m_mgr, reg, kind);
+  return (*cluster_slot)->get_binding (mgr, reg, kind);
+}
+
+void
+store2::set_value (store2_manager *mgr, region2 *lhs_reg, svalue2 *rhs_sval)
+{
+  remove_overlapping_bindings (mgr, lhs_reg);
+
+  const region2 *base_reg = lhs_reg->get_base_region ();
+  binding_cluster2 *cluster = NULL;
+  binding_cluster2 **slot = m_cluster_map.get (base_reg);
+  if (slot)
+    cluster = *slot;
+  else
+    {
+      cluster = new binding_cluster2 ();
+      m_cluster_map.put (base_reg, cluster);
+    }
+  cluster->bind (mgr, lhs_reg, rhs_sval);
+  // TODO: various kinds of invalidation etc
 }
 
+
 /* Return an svalue2 *for a pointer to RID of type PTR_TYPE, reusing
    existing pointer values if one is available.  */
 #if 0
@@ -5028,30 +5063,13 @@ region_model2::set_value (region2 *lhs_reg, svalue2 *rhs_sval,
   gcc_assert (lhs_reg);
   gcc_assert (rhs_sval);
 
-#if 1
-  remove_overlapping_bindings (lhs_reg);
-
-  const region2 *base_reg = lhs_reg->get_base_region ();
-  binding_cluster2 *cluster = NULL;
-  binding_cluster2 **slot = m_cluster_map.get (base_reg);
-  if (slot)
-    cluster = *slot;
-  else
-    {
-      cluster = new binding_cluster2 ();
-      m_cluster_map.put (base_reg, cluster);
-    }
-  cluster->bind (m_mgr, lhs_reg, rhs_sval);
-#else
-  m_store_map.put (lhs_reg, rhs_sval);
-  // TODO: various kinds of invalidation etc
-#endif
+  m_store.set_value (m_mgr->get_store2_manager(), lhs_reg, rhs_sval);
 }
 
 /* FIXME.  */
 
 void
-region_model2::remove_overlapping_bindings (region2 *reg)
+store2::remove_overlapping_bindings (store2_manager *mgr, region2 *reg)
 {
   const region2 *base_reg = reg->get_base_region ();
   if (reg == base_reg)
@@ -5061,7 +5079,7 @@ region_model2::remove_overlapping_bindings (region2 *reg)
       return;
     }
   if (binding_cluster2 **cluster_slot = m_cluster_map.get (base_reg))
-    (*cluster_slot)->remove_overlapping_bindings (m_mgr, reg);
+    (*cluster_slot)->remove_overlapping_bindings (mgr, reg);
 }
 
 /* Set the value of the region2 given by LHS to the value given
@@ -7722,6 +7740,15 @@ test_model_equality_1 ()
   region_model2 model0 (&mgr);
   region_model2 model1 (&mgr);
   ASSERT_EQ (model0, model1);
+
+  /* Verify that setting state in model1 makes the models non-equal.  */
+  tree int_42 = build_int_cst (integer_type_node, 42);
+  tree x = build_global_decl ("x", integer_type_node);
+  model0.set_value (x, int_42, NULL);
+  // FIXME:
+#if 0
+  ASSERT_NE (model0, model1);
+#endif
 }
 
 /* Verify that region2 models for
diff --git a/gcc/analyzer/region-model2.h b/gcc/analyzer/region-model2.h
index 49d168f7f37..84adeed13d8 100644
--- a/gcc/analyzer/region-model2.h
+++ b/gcc/analyzer/region-model2.h
@@ -1305,8 +1305,8 @@ public:
     return kind == BK_direct ? "direct" : "default";
   }
 
-  static const binding_key2 *make (region_model2_manager *mgr, region2 *r,
-				  enum kind kind);
+  static const binding_key2 *make (store2_manager *mgr, region2 *r,
+				   enum kind kind);
 
   virtual void dump_to_pp (pretty_printer *pp, bool simple) const
   {
@@ -1423,17 +1423,16 @@ public:
   void dump_to_pp (pretty_printer *pp, bool simple) const;
 
 #if 1
-  void bind (region_model2_manager *mgr,
-	     region2 *, svalue2 *);
+  void bind (store2_manager *mgr, region2 *, svalue2 *);
 #else
   const binding_cluster2 *bind (const extrinsic_state &ext_state,
 			       const region2 *, const svalue2 *) const;
 #endif
 
-  svalue2 *get_binding (region_model2_manager *mgr, region2 *reg,
+  svalue2 *get_binding (store2_manager *mgr, region2 *reg,
 			binding_key2::kind kind) const;
 
-  void remove_overlapping_bindings (region_model2_manager *mgr, region2 *reg);
+  void remove_overlapping_bindings (store2_manager *mgr, region2 *reg);
 
 private:
   void get_overlapping_bindings (region2 *reg,
@@ -1442,6 +1441,47 @@ private:
   map_t m_map;
 };
 
+// TODO: move this (and the binding stuff) to its own header
+/* The mapping from regions to values.
+   This is actually expressed by subdividing into clusters.  */
+
+class store2
+{
+public:
+  void dump_to_pp (pretty_printer *pp, bool summarize) const;
+
+  svalue2 *get_direct_binding (store2_manager *mgr, region2 *reg);
+  svalue2 *get_default_binding (store2_manager *mgr, region2 *reg);
+  svalue2 *get_binding (store2_manager *mgr,
+			region2 *reg, binding_key2::kind kind);
+
+  void set_value (store2_manager *mgr, region2 *lhs_reg, svalue2 *rhs_sval);
+
+private:
+  void remove_overlapping_bindings (store2_manager *mgr, region2 *reg);
+
+  typedef hash_map <const region2 *, binding_cluster2 *> cluster_map_t;
+  cluster_map_t m_cluster_map; // TODO: deep copy of this!
+};
+
+class store2_manager
+{
+public:
+  /* binding consolidation.  */
+  const concrete_binding2 *
+  get_concrete_binding (const region2 *region,
+			enum binding_key2::kind kind,
+			concrete_binding2::bit_offset_t offset);
+
+  const symbolic_binding2 *
+  get_symbolic_binding (const region2 *region,
+			enum binding_key2::kind kind,
+			region2 *concrete_offset_region);
+private:
+  uniq_manager<concrete_binding2> m_concrete_binding_key_mgr;
+  uniq_manager<symbolic_binding2> m_symbolic_binding_key_mgr;
+};
+
 /* A class responsible for owning and consolidating region2 and svalue2
    instances.    */
 
@@ -1474,16 +1514,7 @@ public:
 
   unsigned alloc_region_id () { return m_next_region_id++; }
 
-  /* binding consolidation.  */
-  const concrete_binding2 *
-  get_concrete_binding (const region2 *region,
-			enum binding_key2::kind kind,
-			concrete_binding2::bit_offset_t offset);
-
-  const symbolic_binding2 *
-  get_symbolic_binding (const region2 *region,
-			enum binding_key2::kind kind,
-			region2 *concrete_offset_region);
+  store2_manager *get_store2_manager () { return &m_store2_mgr; }
 
 private:
   unsigned m_next_region_id;
@@ -1519,8 +1550,7 @@ private:
   uniq_manager<frame_region2> m_frames;
   uniq_manager<region2> m_symbolic_regions;
 
-  uniq_manager<concrete_binding2> m_concrete_binding_key_mgr;
-  uniq_manager<symbolic_binding2> m_symbolic_binding_key_mgr;
+  store2_manager m_store2_mgr;
 };
 
 /* A region_model2 encapsulates a representation of the state of memory, with
@@ -1728,12 +1758,6 @@ class region_model2
 			 region_model2_context *ctxt);
   svalue2 *get_store_value (region2 *reg);
 
-  svalue2 *get_direct_binding (region2 *reg);
-  svalue2 *get_default_binding (region2 *reg);
-  svalue2 *get_binding (region2 *reg, binding_key2::kind kind);
-
-  void remove_overlapping_bindings (region2 *reg);
-
 #if 0
   void copy_struct_region2 (region2_id dst_rid, struct_region2 *dst_reg,
 			   struct_region2 *src_reg, region_model2_context *ctxt);
@@ -1783,13 +1807,7 @@ class region_model2
   /* Storing this here to avoid passing it around everywhere.  */
   region_model2_manager *const m_mgr;
 
-#if 1
-  typedef hash_map <const region2 *, binding_cluster2 *> cluster_map_t;
-  cluster_map_t m_cluster_map; // TODO: deep copy of this!
-#else
-  typedef hash_map <region2 *, svalue2 *> store_map_t;
-  store_map_t m_store_map;
-#endif
+  store2 m_store;
 
 #if 0
   constraint_manager *m_constraints; // TODO: embed, rather than dynalloc?
-- 
2.21.0

