From df77448f64ade53832ab29071470b73d38ee1626 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Tue, 7 Apr 2020 21:02:27 -0400
Subject: [PATCH 014/193] FIXME: split out mem_region into a separate hierarchy
 from sval

---
 gcc/analyzer/revamp-state.cc | 294 ++++++++++++++++++++++++++++++-----
 gcc/analyzer/revamp-state.h  | 192 +++++++++++++++++++----
 2 files changed, 419 insertions(+), 67 deletions(-)

diff --git a/gcc/analyzer/revamp-state.cc b/gcc/analyzer/revamp-state.cc
index 4fb62799780..49c1b647321 100644
--- a/gcc/analyzer/revamp-state.cc
+++ b/gcc/analyzer/revamp-state.cc
@@ -95,7 +95,7 @@ sval::operator== (const sval &other) const
 }
 
 DEBUG_FUNCTION void
-sval::dump ()
+sval::dump () const
 {
   pretty_printer pp;
   pp_format_decoder (&pp) = default_tree_printer;
@@ -117,7 +117,48 @@ sval::to_json () const
   return obj;
 }
 
-/* hash implementations.  */
+/* class mem_region.  */
+
+hashval_t
+mem_region::hash () const
+{
+  inchash::hash hstate;
+  hstate.add_int (get_kind ());
+  return hstate.end ();
+}
+
+bool
+mem_region::operator== (const mem_region &other) const
+{
+  if (get_kind () != other.get_kind ())
+    return false;
+  return cmp_fields (other);
+}
+
+DEBUG_FUNCTION void
+mem_region::dump () 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);
+  pp_newline (&pp);
+  pp_flush (&pp);
+}
+
+json::value *
+mem_region::to_json () const
+{
+  json::object *obj = make_obj_with_address (this);
+  pretty_printer pp;
+  pp_format_decoder (&pp) = default_tree_printer;
+  dump_to_pp (&pp);
+  obj->set ("desc", new json::string (pp_formatted_text (&pp)));
+  return obj;
+}
+
+/* sval hash implementations.  */
 
 void
 cst_sval::add_to_hash (inchash::hash &hstate) const
@@ -125,33 +166,67 @@ cst_sval::add_to_hash (inchash::hash &hstate) const
   inchash::add_expr (m_cst, hstate);
 }
 
+void
+unknown_sval::add_to_hash (inchash::hash &/*hstate*/) const
+{
+  /* Empty.  */
+}
+
+void
+mem_region_val::add_to_hash (inchash::hash &hstate) const
+{
+  hstate.add_ptr (m_region);
+}
+
+/* mem_region hash implementations.  */
+
+void
+globals_mem_region::add_to_hash (inchash::hash &) const
+{
+  /* Empty.  */
+}
+
+void
+frame_mem_region::add_to_hash (inchash::hash &/*hstate*/) const
+{
+  /* TODO.  */
+}
+
+void
+sub_region::add_to_hash (inchash::hash &hstate) const
+{
+  hstate.add_ptr (m_super_region);
+}
+
 void
 var_decl_region::add_to_hash (inchash::hash &hstate) const
 {
+  sub_region::add_to_hash (hstate);
   inchash::add_expr (m_decl, hstate);
 }
 
 void
 ssa_name_region::add_to_hash (inchash::hash &hstate) const
 {
+  sub_region::add_to_hash (hstate);
   inchash::add_expr (m_name, hstate);
 }
 
 void
 element_region::add_to_hash (inchash::hash &hstate) const
 {
-  hstate.add_ptr (m_arr);
+  sub_region::add_to_hash (hstate);
   hstate.add_ptr (m_element);
 }
 
 void
 field_region::add_to_hash (inchash::hash &hstate) const
 {
-  hstate.add_ptr (m_struct);
+  sub_region::add_to_hash (hstate);
   inchash::add_expr (m_field, hstate);
 }
 
-/* cmp_fields implementations.  */
+/* sval cmp_fields implementations.  */
 
 bool
 cst_sval::cmp_fields (const sval &base_other) const
@@ -161,34 +236,79 @@ cst_sval::cmp_fields (const sval &base_other) const
 }
 
 bool
-var_decl_region::cmp_fields (const sval &base_other) const
+unknown_sval::cmp_fields (const sval &base_other) const
+{
+  // TODO
+  return true;
+}
+
+bool
+mem_region_val::cmp_fields (const sval &base_other) const
+{
+  const mem_region_val &sub_other = (const mem_region_val &)base_other;
+  return m_region == sub_other.m_region;
+}
+
+/* mem_region cmp_fields implementations.  */
+
+bool
+globals_mem_region::cmp_fields (const mem_region &/*base_other*/) const
 {
+  return true;
+}
+
+bool
+frame_mem_region::cmp_fields (const mem_region &/*base_other*/) const
+{
+  //const frame_mem_region &sub_other = (const frame_mem_region &)base_other;
+  // TODO
+  return true;
+}
+
+bool
+sub_region::cmp_fields (const mem_region &base_other) const
+{
+  const sub_region &sub_other = (const sub_region &)base_other;
+  return m_super_region == sub_other.m_super_region;
+}
+
+bool
+var_decl_region::cmp_fields (const mem_region &base_other) const
+{
+  if (!sub_region::cmp_fields (base_other))
+    return false;
   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
+ssa_name_region::cmp_fields (const mem_region &base_other) const
 {
+  if (!sub_region::cmp_fields (base_other))
+    return false;
   const ssa_name_region &sub_other = (const ssa_name_region &)base_other;
   return m_name == sub_other.m_name;
 }
 
 bool
-element_region::cmp_fields (const sval &base_other) const
+element_region::cmp_fields (const mem_region &base_other) const
 {
+  if (!sub_region::cmp_fields (base_other))
+    return false;
   const element_region &sub_other = (const element_region &)base_other;
-  return m_arr == sub_other.m_arr && m_element == sub_other.m_element;
+  return m_element == sub_other.m_element;
 }
 
 bool
-field_region::cmp_fields (const sval &base_other) const
+field_region::cmp_fields (const mem_region &base_other) const
 {
+  if (!sub_region::cmp_fields (base_other))
+    return false;
   const field_region &sub_other = (const field_region &)base_other;
-  return m_struct == sub_other.m_struct && m_field == sub_other.m_field;
+  return m_field == sub_other.m_field;
 }
 
-/* dump_to_pp implementations.  */
+/* sval dump_to_pp implementations.  */
 
 void
 cst_sval::dump_to_pp (pretty_printer *pp) const
@@ -196,10 +316,41 @@ cst_sval::dump_to_pp (pretty_printer *pp) const
   pp_printf (pp, "cst_sval(%qE)", m_cst);
 }
 
+void
+unknown_sval::dump_to_pp (pretty_printer *pp) const
+{
+  pp_printf (pp, "unknown_sval");
+}
+
+void
+mem_region_val::dump_to_pp (pretty_printer *pp) const
+{
+  pp_printf (pp, "mem_region_val(");
+  m_region->dump_to_pp (pp);
+  pp_printf (pp, ")");
+}
+
+/* mem_region dump_to_pp implementations.  */
+
+void
+globals_mem_region::dump_to_pp (pretty_printer *pp) const
+{
+  pp_printf (pp, "globals_mem_region");
+}
+
+void
+frame_mem_region::dump_to_pp (pretty_printer *pp) const
+{
+  pp_printf (pp, "frame_mem_region()"); // TODO
+}
+
 void
 var_decl_region::dump_to_pp (pretty_printer *pp) const
 {
-  pp_printf (pp, "var_decl_region(%qE)", m_decl);
+  pp_printf (pp, "var_decl_region(");
+  get_super_region ()->dump_to_pp (pp);
+  pp_string (pp, ", ");
+  pp_printf (pp, "%qE)", m_decl);
 }
 
 void
@@ -212,7 +363,7 @@ void
 element_region::dump_to_pp (pretty_printer *pp) const
 {
   pp_string (pp, "element_region(");
-  m_arr->dump_to_pp (pp);
+  get_super_region ()->dump_to_pp (pp);
   pp_string (pp, ", ");
   m_element->dump_to_pp (pp);
   pp_string (pp, ")");
@@ -222,7 +373,7 @@ void
 field_region::dump_to_pp (pretty_printer *pp) const
 {
   pp_string (pp, "field_region(");
-  m_struct->dump_to_pp (pp);
+  get_super_region ()->dump_to_pp (pp);
   pp_printf (pp, ", %qE)", m_field);
 }
 
@@ -239,23 +390,27 @@ store::store (const store &other)
 }
 
 void
-store::bind (const region_val *dst, const sval *val)
+store::bind (const mem_region *dst, const sval *val)
 {
   m_map.put (dst, val);
   dump ();
 }
 
 const sval *
-store::get_val_for_loc (const loc_val *val)
+store::get_val_for_loc (const extrinsic_state &ext_state, const loc_val *val)
 {
-  if (const region_val *regval = val->dyn_cast_region_val ())
+  if (const mem_region *reg = val->get_mem_region ())
     {
-      if (const sval **slot = m_map.get (regval))
+      if (const sval **slot = m_map.get (reg))
 	return *slot;
       else
 	{
+	  // TODO:
 	  /* No value recorded for this region; try parent.  */
-	  gcc_unreachable (); // TODO
+	  // ...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 ());
 	}
     }
   else
@@ -274,7 +429,7 @@ store::to_json () const
        iter != m_map.end ();
        ++iter)
     {
-      const region_val *reg = (*iter).first;
+      const mem_region *reg = (*iter).first;
       const sval *val = (*iter).second;
       json::object *item_obj = new json::object ();
       item_obj->set ("region", reg->to_json ());
@@ -305,7 +460,7 @@ store::dump_to_pp (pretty_printer *pp) const
     {
       if (iter != m_map.begin ())
 	pp_string (pp, ", ");
-      const region_val *reg = (*iter).first;
+      const mem_region *reg = (*iter).first;
       const sval *val = (*iter).second;
       reg->dump_to_pp (pp);
       pp_string (pp, ": ");
@@ -322,7 +477,7 @@ store::hash () const
        iter != m_map.end ();
        ++iter)
     {
-      const region_val *key = (*iter).first;
+      const mem_region *key = (*iter).first;
       const sval *val = (*iter).second;
       hstate.add_ptr (key);
       hstate.add_ptr (val);
@@ -340,7 +495,7 @@ store::operator== (const store &other) const
        iter != m_map.end ();
        ++iter)
     {
-      const region_val *key = (*iter).first;
+      const mem_region *key = (*iter).first;
       const sval *val = (*iter).second;
       const sval **other_slot = const_cast <map_t &> (other.m_map).get (key);
       if (other_slot == NULL)
@@ -539,10 +694,12 @@ 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);
-  if (const region_val *rval = dst->dyn_cast_region_val ())
-    m_store->bind (rval, src);
+  const mem_region *reg = dst->get_mem_region ();
+  m_store->bind (reg, src);
+#if 0
   else
     gcc_unreachable (); // unknown loc_val; what could be clobbered?
+#endif
 }
 
 const loc_val *
@@ -553,23 +710,32 @@ revamp_state::get_lvalue (const extrinsic_state &ext_state, tree expr)
     {
     case ARRAY_REF:
       {
+	const loc_val *arr_loc = get_lvalue (ext_state, TREE_OPERAND (expr, 0));
 	element_region *reg
-	  = new element_region (get_lvalue (ext_state, TREE_OPERAND (expr, 0)),
+	  = new element_region (arr_loc->get_mem_region (),
 				get_rvalue (ext_state, TREE_OPERAND (expr, 1)));
-	return eng->consolidate_sval (reg);
+	return eng->get_loc_val_for_region (reg);
       }
     case COMPONENT_REF:
       {
+	const loc_val *struct_loc
+	  = get_lvalue (ext_state, TREE_OPERAND (expr, 0));
 	field_region *reg
-	  = new field_region (get_lvalue (ext_state, TREE_OPERAND (expr, 0)),
+	  = new field_region (struct_loc->get_mem_region (),
 			      TREE_OPERAND (expr, 1));
-	return eng->consolidate_sval (reg);
+	return eng->get_loc_val_for_region (reg);
       }
     case PARM_DECL:
     case VAR_DECL:
-      return eng->consolidate_sval (new var_decl_region (expr));
+      {
+	const mem_region *reg = make_var_decl_region (ext_state, expr);
+	return eng->get_loc_val_for_region (reg);
+      }
     case SSA_NAME:
-      return eng->consolidate_sval (new ssa_name_region (expr));
+      {
+	const mem_region *reg = make_ssa_name_region (ext_state, expr);
+	return eng->get_loc_val_for_region (reg);
+      }
     default:
       gcc_unreachable ();
       //return ext_state::new_unknown_sval (expr);
@@ -583,7 +749,8 @@ revamp_state::get_rvalue (const extrinsic_state &ext_state, tree expr)
   switch (TREE_CODE (expr))
     {
     case ARRAY_REF:
-      return m_store->get_val_for_loc (get_lvalue (ext_state, expr));
+      return m_store->get_val_for_loc (ext_state,
+				       get_lvalue (ext_state, expr));
     case INTEGER_CST:
       return eng->consolidate_sval (new cst_sval (expr));
     default:
@@ -624,11 +791,50 @@ revamp_state::operator== (const revamp_state &other) const
   return m_store == other.m_store;
 }
 
+const mem_region *
+revamp_state::make_var_decl_region (const extrinsic_state &ext_state,
+				    tree decl) const
+{
+  engine *eng = ext_state.get_engine ();
+  const mem_region *super_region = get_super_region_for_decl (ext_state, decl);
+  mem_region *new_reg = new var_decl_region (super_region, decl);
+  return eng->consolidate_mem_region (new_reg);
+}
+
+const mem_region *
+revamp_state::make_ssa_name_region (const extrinsic_state &ext_state,
+				    tree name) const
+{
+  engine *eng = ext_state.get_engine ();
+  const mem_region *super_region = get_super_region_for_decl (ext_state, name);
+  mem_region *new_reg = new ssa_name_region (super_region, name);
+  return eng->consolidate_mem_region (new_reg);
+}
+
+/* FIXME: locals vs globals.  */
+
+const mem_region *
+revamp_state::get_super_region_for_decl (const extrinsic_state &ext_state,
+					 tree decl) const
+{
+  engine *eng = ext_state.get_engine ();
+  mem_region *reg;
+  gcc_assert (TREE_CODE (decl) == VAR_DECL
+	      || TREE_CODE (decl) == PARM_DECL
+	      || TREE_CODE (decl) == SSA_NAME);
+  if (TREE_CODE (decl) == VAR_DECL && is_global_var (decl))
+    reg = new globals_mem_region ();
+  else
+    reg = new frame_mem_region (); // TODO: which frame
+  return eng->consolidate_mem_region (reg);
+}
+
 /* class engine.  */
 
 engine::engine ()
 {
   m_sval_mgr = new uniq_manager<sval> ();
+  m_mem_region_mgr = new uniq_manager<mem_region> ();
   m_store_mgr = new uniq_manager<store> ();
   m_state_mgr = new uniq_manager<revamp_state> ();
 }
@@ -636,16 +842,30 @@ engine::engine ()
 engine::~engine ()
 {
   delete m_sval_mgr;
+  delete m_mem_region_mgr;
   delete m_store_mgr;
   delete m_state_mgr;
 }
 
+const loc_val *
+engine::get_loc_val_for_region (const mem_region *reg)
+{
+  loc_val *val = new mem_region_val (reg);
+  return consolidate_sval (val);
+}
+
 size_t
 engine::get_num_svals () const
 {
   return m_sval_mgr->get_count ();
 }
 
+size_t
+engine::get_num_mem_regions () const
+{
+  return m_mem_region_mgr->get_count ();
+}
+
 size_t
 engine::get_num_stores () const
 {
@@ -691,10 +911,13 @@ test_consolidation ()
   ASSERT_EQ (cst42_0, cst42_1);
   ASSERT_NE (cst17_0, cst42_0);
 
+#if 0
   tree x = build_global_decl ("x", integer_type_node);
   tree y = build_global_decl ("y", integer_type_node);
-  const region_val* x_decl = eng.consolidate_sval (new var_decl_region (x));
-  const region_val* y_decl = eng.consolidate_sval (new var_decl_region (y));
+  const mem_region *x_decl
+    = eng.consolidate_mem_region (new var_decl_region (NULL, x));
+  const mem_region *y_decl
+    = eng.consolidate_mem_region (new var_decl_region (NULL, y));
   ASSERT_EQ (eng.get_num_svals (), 4);
   ASSERT_NE (x_decl, y_decl);
 
@@ -748,6 +971,7 @@ test_consolidation ()
   const revamp_state *state3_cons = eng.consolidate_state (state3_mut);
   ASSERT_EQ (state3_cons, state2_cons);
   ASSERT_EQ (eng.get_num_states (), 3);
+#endif
 }
 
 /* Run all of the selftests within this file.  */
diff --git a/gcc/analyzer/revamp-state.h b/gcc/analyzer/revamp-state.h
index 2acb15aa778..aa454da90c8 100644
--- a/gcc/analyzer/revamp-state.h
+++ b/gcc/analyzer/revamp-state.h
@@ -26,7 +26,8 @@ along with GCC; see the file COPYING3.  If not see
 
 namespace ana {
 
-class region_val;
+class mem_region_val;
+class mem_region;
 
 // TODO:
 class sval
@@ -35,10 +36,8 @@ public:
   enum kind
   {
    SK_cst_sval,
-   SK_var_decl_region,
-   SK_ssa_name_region,
-   SK_element_region,
-   SK_field_region
+   SK_unknown_sval,
+   SK_mem_region_val,
   };
   virtual ~sval () {}
 
@@ -48,11 +47,12 @@ public:
   hashval_t hash () const;
   bool operator== (const sval &other) const;
 
-  void dump ();
+  void dump () const;
   virtual void dump_to_pp (pretty_printer *pp) const = 0;
   json::value *to_json () const;
 
-  virtual const region_val *dyn_cast_region_val () const { return NULL; }
+  virtual const mem_region_val *dyn_cast_mem_region_val () const
+  { return NULL; }
 
  protected:
   virtual void add_to_hash (inchash::hash &hstate) const = 0;
@@ -90,110 +90,221 @@ private:
   tree m_cst;
 };
 
+class unknown_sval : public sval
+{
+public:
+  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:
+  // FIXME: is there a single unknown_sval, or multiple ones?
+  // FIXME: perhaps there's just one, and equality
+  // is recorded in constraint manager?  (but how?)
+};
+
 class loc_val : public sval
 {
+ public:
+  virtual const mem_region *get_mem_region () const = 0;
 };
 
 class unknown_loc_val : public loc_val
 {
+ public:
+  const mem_region *get_mem_region () const FINAL OVERRIDE;
 };
 
-class region_val : public loc_val
+class mem_region_val : public loc_val
 {
  public:
-  const region_val *dyn_cast_region_val () const FINAL OVERRIDE { return this; }
+  mem_region_val (const mem_region *region) : m_region (region) {}
+
+  const mem_region_val *dyn_cast_mem_region_val () const FINAL OVERRIDE
+  { return this; }
+
+  const mem_region *get_mem_region () const
+  {
+    return m_region;
+  }
+
+  kind get_kind () const FINAL OVERRIDE { return SK_mem_region_val; }
+
+  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:
+  const mem_region *m_region;
 };
 
-class var_decl_region : public region_val
+/* Memory regions.  */
+
+class mem_region
+{
+ public:
+  enum kind
+  {
+   RK_globals_mem_region,
+   RK_frame_mem_region,
+   RK_var_decl_region,
+   RK_ssa_name_region,
+   RK_element_region,
+   RK_field_region
+  };
+  virtual ~mem_region () {}
+
+  virtual kind get_kind () const = 0;
+
+  /* For use with uniq_manager.  */
+  hashval_t hash () const;
+  bool operator== (const mem_region &other) const;
+
+  void dump () const;
+  virtual void dump_to_pp (pretty_printer *pp) const = 0;
+  json::value *to_json () const;
+
+ protected:
+  virtual void add_to_hash (inchash::hash &hstate) const = 0;
+  virtual bool cmp_fields (const mem_region &other) const = 0;
+};
+
+class globals_mem_region : public mem_region
+{
+ public:
+  kind get_kind () const FINAL OVERRIDE { return RK_globals_mem_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 mem_region &other) const FINAL OVERRIDE;
+};
+
+class frame_mem_region : public mem_region
+{
+ public:
+  kind get_kind () const FINAL OVERRIDE { return RK_frame_mem_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 mem_region &other) const FINAL OVERRIDE;
+};
+
+class sub_region : public mem_region
+{
+ 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;
+
+ private:
+  const mem_region *m_super_region;
+};
+
+class var_decl_region : public sub_region
 {
 public:
-  var_decl_region (tree decl) : m_decl (decl)
+  var_decl_region (const mem_region *super_region, tree decl)
+  : sub_region (super_region), m_decl (decl)
   {
     gcc_assert (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL);
   }
 
-  kind get_kind () const FINAL OVERRIDE { return SK_var_decl_region; }
+  kind get_kind () const FINAL OVERRIDE { return RK_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;
+  bool cmp_fields (const mem_region &other) const FINAL OVERRIDE;
 
 private:
   tree m_decl;
 };
 
-class ssa_name_region : public region_val
+class ssa_name_region : public sub_region
 {
 public:
-  ssa_name_region (tree name) : m_name (name)
+  ssa_name_region (const mem_region *super_region, tree name)
+  : sub_region (super_region),  m_name (name)
   {
     gcc_assert (TREE_CODE (name) == SSA_NAME);
   }
 
-  kind get_kind () const FINAL OVERRIDE { return SK_ssa_name_region; }
+  kind get_kind () const FINAL OVERRIDE { return RK_ssa_name_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;
+  bool cmp_fields (const mem_region &other) const FINAL OVERRIDE;
 
  private:
   tree m_name;
 };
 
-class element_region : public region_val
+class element_region : public sub_region
 {
 public:
-  element_region (const loc_val *arr,
+  element_region (const mem_region *arr_region,
 		  const sval *element)
-  : m_arr (arr), m_element (element)
+  : sub_region (arr_region), m_element (element)
   {
   }
 
-  kind get_kind () const FINAL OVERRIDE { return SK_element_region; }
+  kind get_kind () const FINAL OVERRIDE { return RK_element_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;
+  bool cmp_fields (const mem_region &other) const FINAL OVERRIDE;
 
 private:
-  const loc_val *m_arr;
   const sval *m_element;
 };
 
-class field_region : public region_val
+class field_region : public sub_region
 {
 public:
-  field_region (const loc_val *struct_, tree field)
-  : m_struct (struct_), m_field (field)
+  field_region (const mem_region *struct_region, tree field)
+  : sub_region (struct_region), m_field (field)
   {
   }
 
-  kind get_kind () const FINAL OVERRIDE { return SK_field_region; }
+  kind get_kind () const FINAL OVERRIDE { return RK_field_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;
+  bool cmp_fields (const mem_region &other) const FINAL OVERRIDE;
 
 private:
-  const loc_val *m_struct;
   tree m_field;
 };
 
 class store
 {
  public:
-  typedef hash_map <const region_val *, const sval *> map_t; // or region * ?
+  typedef hash_map <const mem_region *, const sval *> map_t;
   typedef map_t::iterator iterator_t;
 
   store ();
   store (const store &other);
 
-  void bind (const region_val *dst, const sval *val);
-  const sval *get_val_for_loc (const loc_val *val);
+  void bind (const mem_region *dst, const sval *val);
+  const sval *get_val_for_loc (const extrinsic_state &ext_state,
+			       const loc_val *val);
 
   json::value *to_json () const;
   void dump ();
@@ -252,6 +363,13 @@ private:
   bool apply_constraints_for_gswitch (const switch_cfg_superedge &edge,
 				      const gswitch *switch_stmt);
 
+  const mem_region *make_var_decl_region (const extrinsic_state &ext_state,
+					  tree decl) const;
+  const mem_region *make_ssa_name_region (const extrinsic_state &ext_state,
+					  tree name) const;
+  const mem_region *get_super_region_for_decl (const extrinsic_state &ext_state,
+					       tree decl) const;
+
   // TODO
   store *m_store;
 };
@@ -262,6 +380,8 @@ class engine
   engine ();
   ~engine ();
 
+  const loc_val *get_loc_val_for_region (const mem_region *);
+
   /* Instance consolidation.  */
 
   template <typename SvalSubclass>
@@ -271,6 +391,13 @@ class engine
   }
   size_t get_num_svals () const;
 
+  template <typename MemregionSubclass>
+  const MemregionSubclass *consolidate_mem_region (MemregionSubclass *s)
+  {
+    return m_mem_region_mgr->consolidate (s);
+  }
+  size_t get_num_mem_regions () const;
+
   const store *consolidate_store (store *s)
   {
     return m_store_mgr->consolidate (s);
@@ -282,6 +409,7 @@ class engine
 
  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;
 };
-- 
2.21.0

