From 56477a372ab0b0ce51613771297e930f4bafdad6 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 16 Oct 2019 10:43:08 -0400
Subject: [PATCH 89/95] FIXME: add 'escaped' flag to ECs

---
 gcc/analyzer/constraint-manager.cc | 89 +++++++++++++++++++++++++++++++++++++-
 gcc/analyzer/constraint-manager.h  |  6 +++
 2 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/gcc/analyzer/constraint-manager.cc b/gcc/analyzer/constraint-manager.cc
index 1d112cf..20c18cb 100644
--- a/gcc/analyzer/constraint-manager.cc
+++ b/gcc/analyzer/constraint-manager.cc
@@ -159,7 +159,7 @@ IMPL_POOL_ALLOCATOR (equiv_class)
 
 equiv_class::equiv_class ()
 : m_constant (NULL_TREE), m_cst_sid (svalue_id::null ()),
-  m_vars ()
+  m_vars (), m_escaped (false)
 {
 }
 
@@ -167,7 +167,8 @@ equiv_class::equiv_class ()
 
 equiv_class::equiv_class (const equiv_class &other)
 : m_constant (other.m_constant), m_cst_sid (other.m_cst_sid),
-  m_vars (other.m_vars.length ())
+  m_vars (other.m_vars.length ()),
+  m_escaped (other.m_escaped)
 {
   int i;
   svalue_id *sid;
@@ -198,6 +199,8 @@ PUSH_IGNORE_WFORMAT
       pp_printf (pp, "%qE", m_constant);
 POP_IGNORE_WFORMAT
     }
+  if (m_escaped)
+    pp_string (pp, " (escaped)");
   pp_character (pp, '}');
 }
 
@@ -213,6 +216,8 @@ equiv_class::hash () const
   inchash::add_expr (m_constant, hstate);
   FOR_EACH_VEC_ELT (m_vars, i, sid)
     inchash::add (*sid, hstate);
+  hstate.add_flag (m_escaped);
+  hstate.commit_flag ();
   return hstate.end ();
 }
 
@@ -234,6 +239,8 @@ equiv_class::operator== (const equiv_class &other)
   FOR_EACH_VEC_ELT (m_vars, i, sid)
     if (! (*sid == other.m_vars[i]))
       return false;
+  if (m_escaped != other.m_escaped)
+    return false;
 
   return true;
 }
@@ -253,6 +260,12 @@ equiv_class::add (svalue_id sid, const constraint_manager &cm)
       m_cst_sid = sid;
     }
   m_vars.safe_push (sid);
+
+#if 0
+      if (DECL_P (v.m_tree)
+	  && is_global_var (v.m_tree))
+	m_escaped = true;
+#endif
 }
 
 /* Remove SID from this equivalence class.
@@ -1069,6 +1082,78 @@ constraint_manager::eval_condition (svalue_id lhs,
 			 get_or_add_equiv_class (rhs));
 }
 
+/* Mark EC_ID as having escaped; walk other ECs that haven't yet been marked
+   as escaped, and determine if they've now escaped, if so, mark them,
+   recursively.
+   e.g. if we know "ptr" escapes, then "ptr->foo" escapes.  */
+
+#if 0
+void
+constraint_manager::recursively_mark_as_escaping (equiv_class_id ec_id)
+{
+  equiv_class &ec = ec_id.get_obj (*this);
+  if (ec.m_escaped)
+    {
+      /* Nothing to do.  */
+      return;
+    }
+
+  ec.m_escaped = true;
+
+  /* Look for other ECs that haven't yet been marked as escaped.  */
+  int other_ec_idx;
+  equiv_class *other_ec;
+  FOR_EACH_VEC_ELT (m_equiv_classes, other_ec_idx, other_ec)
+    {
+      if (other_ec->m_escaped)
+	continue;
+
+      int var_idx;
+      svalue_id *v;
+      FOR_EACH_VEC_ELT (other_ec->m_vars, var_idx, v)
+	{
+	  gcc_assert (!CONSTANT_CLASS_P (v->m_tree));
+	  if (calc_escaped_p (*v))
+	    {
+	      recursively_mark_as_escaping (other_ec_idx);
+	      break;
+	    }
+	}
+    }
+
+  // TODO: selftests
+  // TODO: selftest involving a cycle
+}
+#endif
+
+/* Determine if PV (or something that points to it) has been marked as
+   having escaped.  */
+
+#if 0
+bool
+constraint_manager::calc_escaped_p (svalue_id pv)
+{
+  switch (TREE_CODE (pv.m_tree))
+    {
+    case COMPONENT_REF:
+    case MEM_REF:
+      return calc_escaped_p (svalue_id (TREE_OPERAND (pv.m_tree, 0),
+				       pv.m_stack_depth));
+    case SSA_NAME:
+      {
+	equiv_class_id ec_id (-1);
+	if (get_equiv_class (pv, &ec_id))
+	  return ec_id.get_obj (*this).m_escaped;
+      }
+      break;
+    default:
+      return false;
+    }
+
+  return false;
+}
+#endif
+
 /* Delete any information about svalue_id instances identified by P.
    Such instances are removed from equivalence classes, and any
    redundant ECs and constraints are also removed.
diff --git a/gcc/analyzer/constraint-manager.h b/gcc/analyzer/constraint-manager.h
index c883d47..5346bf5 100644
--- a/gcc/analyzer/constraint-manager.h
+++ b/gcc/analyzer/constraint-manager.h
@@ -71,6 +71,9 @@ public:
 
   // TODO: should this be a set rather than a vec?
   auto_vec<svalue_id> m_vars;
+
+  /* Has this value escaped from this function?  */
+  bool m_escaped;
 };
 
 /* The various kinds of constraint.  */
@@ -220,6 +223,9 @@ public:
 			   enum tree_code op,
 			   svalue_id rhs);
 
+  void recursively_mark_as_escaping (equiv_class_id ec_id);
+  bool calc_escaped_p (svalue_id sid);
+
   void purge (const purge_criteria &p, purge_stats *stats);
 
   void remap_svalue_ids (const svalue_id_map &map);
-- 
1.8.5.3

