From 656437943ee061a104dc42bdb0f0dec786757e24 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 23 Jul 2020 16:23:29 -0400
Subject: [PATCH 321/377] FIXME: add conjured_svalue2, but don't use it yet

---
 gcc/analyzer/analyzer.h       |   1 +
 gcc/analyzer/region-model2.cc |  58 +++++++++++++++++++
 gcc/analyzer/region-model2.h  | 106 +++++++++++++++++++++++++++++++++-
 3 files changed, 162 insertions(+), 3 deletions(-)

diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h
index b82241e1b0f..540667821d0 100644
--- a/gcc/analyzer/analyzer.h
+++ b/gcc/analyzer/analyzer.h
@@ -70,6 +70,7 @@ class svalue2;
   class placeholder_svalue2;
   class widening_svalue2;
   class compound_svalue2;
+  class conjured_svalue2;
 class region2;
   class frame_region2;
   class function_region2;
diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc
index 9a2574c29f3..7ac64451d72 100644
--- a/gcc/analyzer/region-model2.cc
+++ b/gcc/analyzer/region-model2.cc
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tree.h"
+#include "gimple-pretty-print.h"
 #include "function.h"
 #include "basic-block.h"
 #include "gimple.h"
@@ -1185,6 +1186,40 @@ compound_svalue2::calc_complexity (const binding_map &map)
   return complexity (num_child_nodes + 1, max_child_depth + 1);
 }
 
+/* class conjured_svalue2 : public svalue2.  */
+
+/* FIXME.  */
+
+void
+conjured_svalue2::accept (visitor *v) const
+{
+  v->visit_conjured_svalue2 (this);
+  m_id_reg->accept (v);
+}
+
+void
+conjured_svalue2::dump_to_pp (pretty_printer *pp, bool simple) const
+{
+  if (simple)
+    {
+      pp_string (pp, "CONJURED(");
+      pp_gimple_stmt_1 (pp, m_stmt, 0, (dump_flags_t)0);
+      pp_string (pp, ", ");
+      m_id_reg->dump_to_pp (pp, simple);
+      pp_character (pp, ')');
+    }
+  else
+    {
+      pp_string (pp, "conjured_svalue2 (");
+      // TODO: type?
+      pp_string (pp, ", ");
+      pp_gimple_stmt_1 (pp, m_stmt, 0, (dump_flags_t)0);
+      pp_string (pp, ", ");
+      m_id_reg->dump_to_pp (pp, simple);
+      pp_character (pp, ')');
+    }
+}
+
 /* class region2 and its various subclasses.  */
 
 /* Get a string for KIND for use in debug dumps.  */
@@ -3445,6 +3480,9 @@ region_model2_manager::~region_model2_manager ()
   for (compound_values_map_t::iterator iter = m_compound_values_map.begin ();
        iter != m_compound_values_map.end (); ++iter)
     delete (*iter).second;
+  for (conjured_values_map_t::iterator iter = m_conjured_values_map.begin ();
+       iter != m_conjured_values_map.end (); ++iter)
+    delete (*iter).second;
 
   /* Delete consolidated regions.  */
   for (fndecls_map_t::iterator iter = m_fndecls_map.begin ();
@@ -4015,6 +4053,23 @@ get_or_create_compound_svalue2 (tree type,
   return compound_sval;
 }
 
+/* FIXME.  */
+
+const svalue2 *
+region_model2_manager::
+get_or_create_conjured_svalue2 (tree type, const gimple *stmt,
+				const region2 *id_reg)
+{
+  conjured_svalue2::key_t key (type, stmt, id_reg);
+  if (conjured_svalue2 **slot = m_conjured_values_map.get (key))
+    return *slot;
+  conjured_svalue2 *conjured_sval
+    = new conjured_svalue2 (type, stmt, id_reg);
+  RETURN_UNKNOWN_IF_TOO_COMPLEX (conjured_sval);
+  m_conjured_values_map.put (key, conjured_sval);
+  return conjured_sval;
+}
+
 /* region2 consolidation.  */
 
 /* FIXME.  */
@@ -4312,6 +4367,7 @@ region_model2_manager::log_stats (logger *logger, bool show_objs) const
 		m_unmergeable_values_map);
   log_uniq_map (logger, show_objs, "widening_svalue2", m_widening_values_map);
   log_uniq_map (logger, show_objs, "compound_svalue2", m_compound_values_map);
+  log_uniq_map (logger, show_objs, "conjured_svalue2", m_conjured_values_map);
   logger->log ("max accepted svalue num_nodes: %i",
 	       m_max_complexity.m_num_nodes);
   logger->log ("max accepted svalue max_depth: %i",
@@ -6389,6 +6445,8 @@ region_model2::deref_rvalue (const svalue2 *ptr_sval, tree ptr_tree,
     case svalue2::SK_CONSTANT:
     case svalue2::SK_INITIAL:
     case svalue2::SK_UNARYOP:
+    case svalue2::SK_SUB:
+    case svalue2::SK_CONJURED:
       goto create_symbolic_region2;
 
     case svalue2::SK_POISONED:
diff --git a/gcc/analyzer/region-model2.h b/gcc/analyzer/region-model2.h
index a1ecf9c472e..2866ab64cd6 100644
--- a/gcc/analyzer/region-model2.h
+++ b/gcc/analyzer/region-model2.h
@@ -161,6 +161,7 @@ public:
   virtual void visit_placeholder_svalue2 (const placeholder_svalue2 *) {}
   virtual void visit_widening_svalue2 (const widening_svalue2 *) {}
   virtual void visit_compound_svalue2 (const compound_svalue2 *) {}
+  virtual void visit_conjured_svalue2 (const conjured_svalue2 *) {}
 
   virtual void visit_region (const region2 *) {}
 };
@@ -173,7 +174,7 @@ public:
    svalue2
      region_svalue2 (SK_REGION): a pointer to a region2
      constant_svalue2 (SK_CONSTANT): a constant
-     unknown_svalue2 (SK_UNKNOWN)
+     unknown_svalue2 (SK_UNKNOWN): an unknowable value
      poisoned_svalue2 (SK_POISONED): a unusable value (undefined)
      setjmp_svalue2 (SK_SETJMP): a setjmp/longjmp buffer
      initial2_svalue2 (SK_INITIAL): the initial value of a region2
@@ -185,7 +186,8 @@ public:
      placeholder_svalue2 (SK_PLACEHOLDER): for use in selftests.
      widening_svalue2 (SK_WIDENING): a merger of two svalues (possibly
        in an iteration).
-     compound_svalue2 (SK_COMPOUND): a mapping of bit-ranges to svalues.  */
+     compound_svalue2 (SK_COMPOUND): a mapping of bit-ranges to svalues
+     conjured_svalue2 (SK_CONJURED): a value arising from a stmt.  */
 
 /* An abstract base class representing a value held by a region of memory.  */
 
@@ -208,7 +210,8 @@ public:
    SK_UNMERGEABLE,
    SK_PLACEHOLDER,
    SK_WIDENING,
-   SK_COMPOUND
+   SK_COMPOUND,
+   SK_CONJURED
   };
 
   virtual ~svalue2 () {}
@@ -254,6 +257,8 @@ public:
   dyn_cast_widening_svalue2 () const { return NULL; }
   virtual const compound_svalue2 *
   dyn_cast_compound_svalue2 () const { return NULL; }
+  virtual const conjured_svalue2 *
+  dyn_cast_conjured_svalue2 () const { return NULL; }
 
   tree maybe_get_constant () const;
   const svalue2 *maybe_undo_cast () const;
@@ -1258,6 +1263,95 @@ template <> struct default_hash_traits<compound_svalue2::key_t>
 
 namespace ana {
 
+/* FIXME.  */
+
+class conjured_svalue2 : public svalue2
+{
+public:
+  typedef binding_map::iterator_t iterator_t;
+
+  /* A support class for uniquifying instances of conjured_svalue2.  */
+  struct key_t
+  {
+    key_t (tree type, const gimple *stmt, const region2 *id_reg)
+    : m_type (type), m_stmt (stmt), m_id_reg (id_reg)
+    {}
+
+    hashval_t hash () const
+    {
+      inchash::hash hstate;
+      hstate.add_ptr (m_type);
+      hstate.add_ptr (m_stmt);
+      hstate.add_ptr (m_id_reg);
+      return hstate.end ();
+    }
+
+    bool operator== (const key_t &other) const
+    {
+      return (m_type == other.m_type
+	      && m_stmt == other.m_stmt
+	      && m_id_reg == other.m_id_reg);
+    }
+
+    /* Use m_stmt to mark empty/deleted, as m_type can be NULL for
+       legitimate instances.  */
+    void mark_deleted () { m_stmt = reinterpret_cast<const gimple *> (1); }
+    void mark_empty () { m_stmt = NULL; }
+    bool is_deleted () const
+    {
+      return m_stmt == reinterpret_cast<const gimple *> (1);
+    }
+    bool is_empty () const { return m_stmt == NULL; }
+
+    tree m_type;
+    const gimple *m_stmt;
+    const region2 *m_id_reg;
+  };
+
+  conjured_svalue2 (tree type, const gimple *stmt, const region2 *id_reg)
+  : svalue2 (complexity (id_reg), type),
+    m_stmt (stmt), m_id_reg (id_reg)
+  {
+    gcc_assert (m_stmt != NULL);
+  }
+
+  enum kind get_kind () const FINAL OVERRIDE { return SK_CONJURED; }
+  const conjured_svalue2 *dyn_cast_conjured_svalue2 () const { return this; }
+  void accept (visitor *v) const FINAL OVERRIDE;
+
+#if 0
+  void dump_dot_to_pp (const region_model2 &model,
+		       pretty_printer *pp) const
+    FINAL OVERRIDE;
+#endif
+
+  void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+
+ private:
+  const gimple *m_stmt;
+  const region2 *m_id_reg;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <conjured_svalue2 *>::test (svalue2 *sval)
+{
+  return sval->get_kind () == svalue2::SK_CONJURED;
+}
+
+#if 1
+template <> struct default_hash_traits<conjured_svalue2::key_t>
+: public member_function_hash_traits<conjured_svalue2::key_t>
+{
+  static const bool empty_zero_p = true;
+};
+#endif
+
+namespace ana {
+
 /* Region and its subclasses.
 
    The class hierarchy looks like this (using indentation to show
@@ -2198,6 +2292,8 @@ public:
 						 const svalue2 *iter_svalue);
   const svalue2 *get_or_create_compound_svalue2 (tree type,
 						 const binding_map &map);
+  const svalue2 *get_or_create_conjured_svalue2 (tree type, const gimple *stmt,
+						 const region2 *id_reg);
 
   /* region2 consolidation.  */
   const stack_region2 * get_stack_region () const { return &m_stack_region; }
@@ -2304,6 +2400,10 @@ private:
 		   compound_svalue2 *> compound_values_map_t;
   compound_values_map_t m_compound_values_map;
 
+  typedef hash_map<conjured_svalue2::key_t,
+		   conjured_svalue2 *> conjured_values_map_t;
+  conjured_values_map_t m_conjured_values_map;
+
   /* Maximum complexity of svalues that weren't rejected.  */
   complexity m_max_complexity;
 
-- 
2.26.2

