From 674fe475fe693d89e929f62e379dff3016c9dbdc Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 9 Apr 2020 14:07:39 -0400
Subject: [PATCH 16/22] FIXME: WIP on smarter region bindings

---
 gcc/analyzer/revamp-state.cc | 26 ++++++++++
 gcc/analyzer/revamp-state.h  | 98 +++++++++++++++++++++++++++++++++++-
 2 files changed, 122 insertions(+), 2 deletions(-)

diff --git a/gcc/analyzer/revamp-state.cc b/gcc/analyzer/revamp-state.cc
index 49c1b647321..92918b5137a 100644
--- a/gcc/analyzer/revamp-state.cc
+++ b/gcc/analyzer/revamp-state.cc
@@ -158,6 +158,27 @@ mem_region::to_json () const
   return obj;
 }
 
+/* FIXME.  */
+
+const mem_region *
+mem_region::get_base_region () const
+{
+  const mem_region *iter = this;
+  while (iter)
+    {
+      switch (iter->get_kind ())
+	{
+	case RK_element_region:
+	case RK_field_region:
+	  iter = as_a <const sub_region *> (iter)->get_super_region ();
+	  continue;
+	default:
+	  break;
+	}
+    }
+  return iter;
+}
+
 /* sval hash implementations.  */
 
 void
@@ -392,6 +413,7 @@ store::store (const store &other)
 void
 store::bind (const mem_region *dst, const sval *val)
 {
+  const mem_region *base = dst->get_base_region ();
   m_map.put (dst, val);
   dump ();
 }
@@ -725,6 +747,10 @@ revamp_state::get_lvalue (const extrinsic_state &ext_state, tree expr)
 			      TREE_OPERAND (expr, 1));
 	return eng->get_loc_val_for_region (reg);
       }
+    case MEM_REF:
+      {
+	gcc_unreachable ();
+      }
     case PARM_DECL:
     case VAR_DECL:
       {
diff --git a/gcc/analyzer/revamp-state.h b/gcc/analyzer/revamp-state.h
index aa454da90c8..a213bdaf230 100644
--- a/gcc/analyzer/revamp-state.h
+++ b/gcc/analyzer/revamp-state.h
@@ -170,6 +170,9 @@ class mem_region
   virtual void dump_to_pp (pretty_printer *pp) const = 0;
   json::value *to_json () const;
 
+  virtual bool sub_region_p () const { return false; }
+  const mem_region *get_base_region () const;
+
  protected:
   virtual void add_to_hash (inchash::hash &hstate) const = 0;
   virtual bool cmp_fields (const mem_region &other) const = 0;
@@ -199,14 +202,17 @@ class frame_mem_region : public mem_region
 
 class sub_region : public mem_region
 {
+public:
+  const mem_region *get_super_region () const { return m_super_region; }
+
+  bool sub_region_p () const FINAL OVERRIDE { return true; }
+
  protected:
   sub_region (const mem_region *super_region)
   : m_super_region (super_region)
   {
   }
 
-  const mem_region *get_super_region () const { return m_super_region; }
-
   void add_to_hash (inchash::hash &hstate) const OVERRIDE;
   bool cmp_fields (const mem_region &other) const OVERRIDE;
 
@@ -214,6 +220,18 @@ class sub_region : public mem_region
   const mem_region *m_super_region;
 };
 
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const sub_region *>::test (const mem_region *reg)
+{
+  return reg->sub_region_p ();
+}
+
+namespace ana {
+
 class var_decl_region : public sub_region
 {
 public:
@@ -293,16 +311,88 @@ private:
   tree m_field;
 };
 
+/* A binding within a store.  */
+
+class binding_key
+{
+protected:
+  binding_key (mem_region *region, bool direct)
+  : m_region (region), m_direct (direct) {}
+
+  mem_region *get_region () const { return m_region; }
+
+  bool direct_p () const { return m_direct; }
+  bool default_p () const { return !m_direct; }
+
+private:
+  mem_region *m_region;
+  bool m_direct; /* vs default.  */
+};
+
+class concrete_binding : public binding_key
+{
+public:
+  typedef unsigned offset_t;
+
+  concrete_binding (mem_region *region, bool direct, offset_t offset)
+  : binding_key (region, direct), m_offset (offset)
+  {}
+
+private:
+  offset_t m_offset;
+};
+
+class symbolic_binding : public binding_key
+{
+public:
+  symbolic_binding (sub_region *region, bool direct,
+		    sub_region *concrete_offset_region)
+  : binding_key (region, direct),
+    m_concrete_offset_region (concrete_offset_region)
+  {}
+private:
+  sub_region *m_concrete_offset_region;
+};
+
+/* All of the bindings within a store for regions that share the same
+   base region.  */
+
+class binding_cluster
+{
+public:
+  typedef hash_map <const mem_region *, const sval *> map_t;
+  typedef map_t::iterator iterator_t;
+
+  binding_cluster ();
+  binding_cluster (const binding_cluster &other);
+
+private:
+  map_t m_map;
+};
+
+class store_manager
+{
+  uniq_manager<binding_key> *m_binding_key_mgr;
+  uniq_manager<binding_cluster> *m_cluster_mgr;
+};
+
+/* A mapping from mem_region to sval.  */
+
 class store
 {
  public:
+#if 1
   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;
+#endif
 
   store ();
   store (const store &other);
 
   void bind (const mem_region *dst, const sval *val);
+
   const sval *get_val_for_loc (const extrinsic_state &ext_state,
 			       const loc_val *val);
 
@@ -315,7 +405,11 @@ class store
   bool operator== (const store &other) const;
 
  private:
+#if 1
   map_t m_map;
+#else
+  cluster_map_t m_map;
+#endif
 };
 
 // TODO:
-- 
2.21.0

