From fbacda3d844336e1efa66d7f8039ac649fc8ad8e Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 9 Apr 2020 16:56:50 -0400
Subject: [PATCH 18/44] FIXME: WIP on binding clusters

---
 gcc/analyzer/revamp-state.cc | 61 +++++++++++++++++++++++++++---------
 gcc/analyzer/revamp-state.h  | 34 +++++++++++++++-----
 2 files changed, 73 insertions(+), 22 deletions(-)

diff --git a/gcc/analyzer/revamp-state.cc b/gcc/analyzer/revamp-state.cc
index 92918b5137a..c26236a85db 100644
--- a/gcc/analyzer/revamp-state.cc
+++ b/gcc/analyzer/revamp-state.cc
@@ -398,6 +398,14 @@ field_region::dump_to_pp (pretty_printer *pp) const
   pp_printf (pp, ", %qE)", m_field);
 }
 
+const binding_cluster *
+binding_cluster::bind (const extrinsic_state &ext_state,
+		       const mem_region *reg, const sval *val) const
+{
+  gcc_unreachable ();
+  return this;
+}
+
 /* class store.  */
 
 store::store ()
@@ -411,11 +419,24 @@ store::store (const store &other)
 }
 
 void
-store::bind (const mem_region *dst, const sval *val)
+store::bind (const extrinsic_state &ext_state,
+	     const mem_region *dst, const sval *val)
 {
+  engine *eng = ext_state.get_engine ();
+  uniq_manager<cluster_map_t> *map_mgr = eng->get_store_map_manager ();
+  //uniq_manager<binding_cluster> *bc_mgr = eng->get_binding_cluster_manager ();
   const mem_region *base = dst->get_base_region ();
-  m_map.put (dst, val);
-  dump ();
+  if (const binding_cluster * const *c = m_map->get (base))
+    {
+      const binding_cluster *new_c = (*c)->bind (ext_state, dst, val);
+      m_map = m_map->put (base, new_c, map_mgr);
+    }
+  else
+    {
+      binding_cluster empty_c;
+      const binding_cluster *new_c = empty_c.bind (ext_state, dst, val);
+      m_map = m_map->put (base, new_c, map_mgr);
+    }
 }
 
 const sval *
@@ -423,21 +444,24 @@ store::get_val_for_loc (const extrinsic_state &ext_state, const loc_val *val)
 {
   if (const mem_region *reg = val->get_mem_region ())
     {
-      if (const sval **slot = m_map.get (reg))
-	return *slot;
+      const mem_region *base = reg->get_base_region ();
+      if (const binding_cluster * const *c = m_map->get (base))
+	{
+	  gcc_unreachable ();
+	}
       else
 	{
-	  // TODO:
-	  /* No value recorded for this region; try parent.  */
-	  // ...and try inheritance, default values, etc
-	  // FIXME: for now, an unknown value
-	  engine *eng = ext_state.get_engine ();
-	  return eng->consolidate_sval (new unknown_sval ());
+	  gcc_unreachable ();
 	}
     }
   else
     {
-      gcc_unreachable (); // TODO
+      // TODO:
+      /* No value recorded for this region; try parent.  */
+      // ...and try inheritance, default values, etc
+      // FIXME: for now, an unknown value
+      engine *eng = ext_state.get_engine ();
+      return eng->consolidate_sval (new unknown_sval ());
     }
 }
 
@@ -445,6 +469,7 @@ json::value *
 store::to_json () const
 {
   json::object *store_obj = make_obj_with_address (this);
+#if 0
   json::array *store_arr = new json::array ();
   store_obj->set ("items", store_arr);
   for (map_t::iterator iter = m_map.begin ();
@@ -458,6 +483,7 @@ store::to_json () const
       item_obj->set ("value", val->to_json ());
       store_arr->append (item_obj);
     }
+#endif
   return store_obj;
 }
 
@@ -476,6 +502,7 @@ void
 store::dump_to_pp (pretty_printer *pp) const
 {
   pp_character (pp, '{');
+#if 0
   for (map_t::iterator iter = m_map.begin ();
        iter != m_map.end ();
        ++iter)
@@ -488,6 +515,7 @@ store::dump_to_pp (pretty_printer *pp) const
       pp_string (pp, ": ");
       val->dump_to_pp (pp);
     }
+#endif
   pp_character (pp, '}');
 }
 
@@ -495,6 +523,7 @@ hashval_t
 store::hash () const
 {
   inchash::hash hstate;
+#if 0
   for (map_t::iterator iter = m_map.begin ();
        iter != m_map.end ();
        ++iter)
@@ -504,15 +533,16 @@ store::hash () const
       hstate.add_ptr (key);
       hstate.add_ptr (val);
     }
+#endif
   return hstate.end ();
 }
 
 bool
 store::operator== (const store &other) const
 {
-  if (m_map.elements () != other.m_map.elements ())
+  if (m_map->elements () != other.m_map->elements ())
     return false;
-
+#if 0
   for (map_t::iterator iter = m_map.begin ();
        iter != m_map.end ();
        ++iter)
@@ -525,6 +555,7 @@ store::operator== (const store &other) const
       if (val != *other_slot)
 	return false;
     }
+#endif
   return true;
 }
 
@@ -717,7 +748,7 @@ revamp_state::bind (const extrinsic_state &ext_state,
   const loc_val *dst = get_lvalue (ext_state, lhs);
   const sval *src = get_rvalue (ext_state, rhs);
   const mem_region *reg = dst->get_mem_region ();
-  m_store->bind (reg, src);
+  m_store->bind (ext_state, reg, src);
 #if 0
   else
     gcc_unreachable (); // unknown loc_val; what could be clobbered?
diff --git a/gcc/analyzer/revamp-state.h b/gcc/analyzer/revamp-state.h
index a213bdaf230..357b10d5485 100644
--- a/gcc/analyzer/revamp-state.h
+++ b/gcc/analyzer/revamp-state.h
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "json.h"
 #include "uniq-manager.h"
+#include "immutable-hash-map.h"
 
 namespace ana {
 
@@ -360,11 +361,16 @@ private:
 class binding_cluster
 {
 public:
-  typedef hash_map <const mem_region *, const sval *> map_t;
-  typedef map_t::iterator iterator_t;
+  typedef immutable_hash_map <const binding_key *, const sval *> map_t;
+  //typedef typename map_t::iterator iterator_t;
 
+#if 0
   binding_cluster ();
   binding_cluster (const binding_cluster &other);
+#endif
+
+  const binding_cluster *bind (const extrinsic_state &ext_state,
+			       const mem_region *, const sval *) const;
 
 private:
   map_t m_map;
@@ -381,17 +387,19 @@ class store_manager
 class store
 {
  public:
-#if 1
+#if 0
   typedef hash_map <const mem_region *, const sval *> map_t;
   typedef map_t::iterator iterator_t;
 #else
-  typedef hash_map <const mem_region *, binding_cluster *> cluster_map_t;
+  typedef immutable_hash_map <const mem_region *,
+			      const binding_cluster *> cluster_map_t;
 #endif
 
   store ();
   store (const store &other);
 
-  void bind (const mem_region *dst, const sval *val);
+  void bind (const extrinsic_state &ext_state,
+	     const mem_region *dst, const sval *val);
 
   const sval *get_val_for_loc (const extrinsic_state &ext_state,
 			       const loc_val *val);
@@ -405,10 +413,10 @@ class store
   bool operator== (const store &other) const;
 
  private:
-#if 1
+#if 0
   map_t m_map;
 #else
-  cluster_map_t m_map;
+  const cluster_map_t *m_map;
 #endif
 };
 
@@ -501,11 +509,23 @@ class engine
   const revamp_state *consolidate_state (revamp_state *rs);
   size_t get_num_states () const;
 
+  uniq_manager<binding_cluster> *get_binding_cluster_manager ()
+  {
+    return &m_binding_cluster_mgr;
+  }
+
+  uniq_manager<store::cluster_map_t> *get_store_map_manager ()
+  {
+    return &m_store_map_mgr;
+  }
+
  private:
   uniq_manager<sval> *m_sval_mgr;
   uniq_manager<mem_region> *m_mem_region_mgr;
   uniq_manager<store> *m_store_mgr;
   uniq_manager<revamp_state> *m_state_mgr;
+  uniq_manager<binding_cluster> m_binding_cluster_mgr;
+  uniq_manager<store::cluster_map_t> m_store_map_mgr;
 };
 
 } // namespace ana
-- 
2.21.0

