From f4eb1784dbdeaac9084e187516b2bfd7b27f570b Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Tue, 7 Apr 2020 17:10:52 -0400
Subject: [PATCH 013/159] FIXME: WIP on element_region and field_region

---
 gcc/analyzer/engine.cc       |  2 +-
 gcc/analyzer/revamp-state.cc | 84 ++++++++++++++++++++++++++++++++++++
 gcc/analyzer/revamp-state.h  | 48 ++++++++++++++++++++-
 3 files changed, 131 insertions(+), 3 deletions(-)

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 914cc0db7b1..4a6272e875f 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -2078,7 +2078,7 @@ exploded_graph::get_or_create_node (const program_point &point,
       pp_show_color (&pp) = pp_show_color (global_dc->printer);
       json::value *js = node->to_json ();
       js->print (&pp); // FIXME: format, colorize
-      inform (point.get_location (), "EN: %i%s",
+      inform (point.get_location (), "EN: %i: %s",
 	      node->m_index, pp_formatted_text (&pp));
       delete js;
     }
diff --git a/gcc/analyzer/revamp-state.cc b/gcc/analyzer/revamp-state.cc
index 09321ce64d3..4fb62799780 100644
--- a/gcc/analyzer/revamp-state.cc
+++ b/gcc/analyzer/revamp-state.cc
@@ -102,6 +102,7 @@ sval::dump ()
   pp_show_color (&pp) = pp_show_color (global_dc->printer);
   pp.buffer->stream = stderr;
   dump_to_pp (&pp);
+  pp_newline (&pp);
   pp_flush (&pp);
 }
 
@@ -136,6 +137,20 @@ ssa_name_region::add_to_hash (inchash::hash &hstate) const
   inchash::add_expr (m_name, hstate);
 }
 
+void
+element_region::add_to_hash (inchash::hash &hstate) const
+{
+  hstate.add_ptr (m_arr);
+  hstate.add_ptr (m_element);
+}
+
+void
+field_region::add_to_hash (inchash::hash &hstate) const
+{
+  hstate.add_ptr (m_struct);
+  inchash::add_expr (m_field, hstate);
+}
+
 /* cmp_fields implementations.  */
 
 bool
@@ -159,6 +174,20 @@ ssa_name_region::cmp_fields (const sval &base_other) const
   return m_name == sub_other.m_name;
 }
 
+bool
+element_region::cmp_fields (const sval &base_other) const
+{
+  const element_region &sub_other = (const element_region &)base_other;
+  return m_arr == sub_other.m_arr && m_element == sub_other.m_element;
+}
+
+bool
+field_region::cmp_fields (const sval &base_other) const
+{
+  const field_region &sub_other = (const field_region &)base_other;
+  return m_struct == sub_other.m_struct && m_field == sub_other.m_field;
+}
+
 /* dump_to_pp implementations.  */
 
 void
@@ -179,6 +208,24 @@ ssa_name_region::dump_to_pp (pretty_printer *pp) const
   pp_printf (pp, "ssa_name_region(%qE)", m_name);
 }
 
+void
+element_region::dump_to_pp (pretty_printer *pp) const
+{
+  pp_string (pp, "element_region(");
+  m_arr->dump_to_pp (pp);
+  pp_string (pp, ", ");
+  m_element->dump_to_pp (pp);
+  pp_string (pp, ")");
+}
+
+void
+field_region::dump_to_pp (pretty_printer *pp) const
+{
+  pp_string (pp, "field_region(");
+  m_struct->dump_to_pp (pp);
+  pp_printf (pp, ", %qE)", m_field);
+}
+
 /* class store.  */
 
 store::store ()
@@ -198,6 +245,25 @@ store::bind (const region_val *dst, const sval *val)
   dump ();
 }
 
+const sval *
+store::get_val_for_loc (const loc_val *val)
+{
+  if (const region_val *regval = val->dyn_cast_region_val ())
+    {
+      if (const sval **slot = m_map.get (regval))
+	return *slot;
+      else
+	{
+	  /* No value recorded for this region; try parent.  */
+	  gcc_unreachable (); // TODO
+	}
+    }
+  else
+    {
+      gcc_unreachable (); // TODO
+    }
+}
+
 json::value *
 store::to_json () const
 {
@@ -338,6 +404,7 @@ revamp_state::on_gassign (const extrinsic_state &ext_state,
   enum tree_code op = gimple_assign_rhs_code (stmt);
   switch (op)
     {
+    case ARRAY_REF:
     case INTEGER_CST:
       bind (ext_state, lhs, rhs1);
       break;
@@ -484,6 +551,21 @@ revamp_state::get_lvalue (const extrinsic_state &ext_state, tree expr)
   engine *eng = ext_state.get_engine ();
   switch (TREE_CODE (expr))
     {
+    case ARRAY_REF:
+      {
+	element_region *reg
+	  = new element_region (get_lvalue (ext_state, TREE_OPERAND (expr, 0)),
+				get_rvalue (ext_state, TREE_OPERAND (expr, 1)));
+	return eng->consolidate_sval (reg);
+      }
+    case COMPONENT_REF:
+      {
+	field_region *reg
+	  = new field_region (get_lvalue (ext_state, TREE_OPERAND (expr, 0)),
+			      TREE_OPERAND (expr, 1));
+	return eng->consolidate_sval (reg);
+      }
+    case PARM_DECL:
     case VAR_DECL:
       return eng->consolidate_sval (new var_decl_region (expr));
     case SSA_NAME:
@@ -500,6 +582,8 @@ revamp_state::get_rvalue (const extrinsic_state &ext_state, tree expr)
   engine *eng = ext_state.get_engine ();
   switch (TREE_CODE (expr))
     {
+    case ARRAY_REF:
+      return m_store->get_val_for_loc (get_lvalue (ext_state, expr));
     case INTEGER_CST:
       return eng->consolidate_sval (new cst_sval (expr));
     default:
diff --git a/gcc/analyzer/revamp-state.h b/gcc/analyzer/revamp-state.h
index bde81d71804..2acb15aa778 100644
--- a/gcc/analyzer/revamp-state.h
+++ b/gcc/analyzer/revamp-state.h
@@ -36,7 +36,9 @@ public:
   {
    SK_cst_sval,
    SK_var_decl_region,
-   SK_ssa_name_region
+   SK_ssa_name_region,
+   SK_element_region,
+   SK_field_region
   };
   virtual ~sval () {}
 
@@ -107,7 +109,7 @@ class var_decl_region : public region_val
 public:
   var_decl_region (tree decl) : m_decl (decl)
   {
-    gcc_assert (TREE_CODE (decl) == VAR_DECL);
+    gcc_assert (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL);
   }
 
   kind get_kind () const FINAL OVERRIDE { return SK_var_decl_region; }
@@ -140,6 +142,47 @@ public:
   tree m_name;
 };
 
+class element_region : public region_val
+{
+public:
+  element_region (const loc_val *arr,
+		  const sval *element)
+  : m_arr (arr), m_element (element)
+  {
+  }
+
+  kind get_kind () const FINAL OVERRIDE { return SK_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;
+
+private:
+  const loc_val *m_arr;
+  const sval *m_element;
+};
+
+class field_region : public region_val
+{
+public:
+  field_region (const loc_val *struct_, tree field)
+  : m_struct (struct_), m_field (field)
+  {
+  }
+
+  kind get_kind () const FINAL OVERRIDE { return SK_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;
+
+private:
+  const loc_val *m_struct;
+  tree m_field;
+};
+
 class store
 {
  public:
@@ -150,6 +193,7 @@ class store
   store (const store &other);
 
   void bind (const region_val *dst, const sval *val);
+  const sval *get_val_for_loc (const loc_val *val);
 
   json::value *to_json () const;
   void dump ();
-- 
2.21.0

