public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/arsenic/heads/call_string_update)] analyzer: refactor callstring to work with pair of supernodes
@ 2021-07-29  3:25 Ankur saini
  0 siblings, 0 replies; only message in thread
From: Ankur saini @ 2021-07-29  3:25 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:3e554584f5b5249786fbcf4fd16cbc8e6f0c65ba

commit 3e554584f5b5249786fbcf4fd16cbc8e6f0c65ba
Author: Ankur Saini <arsenic@sourceware.org>
Date:   Sun Jul 25 14:47:53 2021 +0530

    analyzer: refactor callstring to work with pair of supernodes
    
    2021-07-25  Ankur Saini  <arsenic@sourceware.org>
    
    gcc/analyzer/ChangeLog:
            * call-string.cc (call_string::element_t::operator==): New operator.
            (call_String::element_t::operator!=): New operator.
            (call_string::element_t::get_caller_function): New function.
            (call_string::element_t::get_callee_function): New function.
            (call_string::call_string): Refactor to Initialise m_elements.
            (call_string::operator=): Refactor to work with m_elements.
            (call_string::operator==): Likewise.
            (call_string::to_json): Likewise.
            (call_string::hash): Refactor to hash e.m_caller.
            (call_string::push_call): Refactor to work with m_elements.
            (call_string::push_call): New overload to push call via supernodes.
            (call_string::pop): Refactor to work with m_elements.
            (call_string::calc_recursion_depth): Likewise.
            (call_string::cmp): Likewise.
            (call_string::validate): Likewise.
            (call_string::operator[]): Likewise.
            * call-string.h (class supernode): New forward decl.
            (struct call_string::element_t): New struct.
            (call_string::call_string): Refactor to initialise m_elements.
            (call_string::bool empty_p): Refactor to work with m_elements.
            (call_string::get_callee_node): New decl.
            (call_string::get_caller_node): New decl.
            (m_elements): Replaces m_return_edges.
            * program-point.cc (program_point::get_function_at_depth): Refactor to
            work with new call-string format.
            (program_point::validate): Likewise.
            (program_point::on_edge): Likewise.

Diff:
---
 gcc/analyzer/call-string.cc   | 143 +++++++++++++++++++++++++++++++-----------
 gcc/analyzer/call-string.h    |  52 ++++++++++++---
 gcc/analyzer/program-point.cc |  10 +--
 3 files changed, 154 insertions(+), 51 deletions(-)

diff --git a/gcc/analyzer/call-string.cc b/gcc/analyzer/call-string.cc
index 9f4f77ab3a9..1e652a08a5a 100644
--- a/gcc/analyzer/call-string.cc
+++ b/gcc/analyzer/call-string.cc
@@ -45,13 +45,42 @@ along with GCC; see the file COPYING3.  If not see
 
 /* class call_string.  */
 
+/* struct call_string::element_t.  */
+
+/* call_string::element_t's equality operator.  */
+
+bool
+call_string::element_t::operator== (const call_string::element_t &other) const
+{
+  return (m_caller == other.m_caller && m_callee == other.m_callee);
+}
+
+/* call_string::element_t's inequality operator.  */
+bool
+call_string::element_t::operator!= (const call_string::element_t &other) const
+{
+  return !(*this == other);
+}
+
+function *
+call_string::element_t::get_caller_function () const
+{
+  return m_caller->get_function ();
+}
+
+function *
+call_string::element_t::get_callee_function () const
+{
+  return m_callee->get_function ();
+}
+
 /* call_string's copy ctor.  */
 
 call_string::call_string (const call_string &other)
-: m_return_edges (other.m_return_edges.length ())
+: m_elements (other.m_elements.length ())
 {
-  for (const return_superedge *e : other.m_return_edges)
-    m_return_edges.quick_push (e);
+  for (const call_string::element_t &e : other.m_elements)
+    m_elements.quick_push (e);
 }
 
 /* call_string's assignment operator.  */
@@ -60,12 +89,12 @@ call_string&
 call_string::operator= (const call_string &other)
 {
   // would be much simpler if we could rely on vec<> assignment op
-  m_return_edges.truncate (0);
-  m_return_edges.reserve (other.m_return_edges.length (), true);
-  const return_superedge *e;
+  m_elements.truncate (0);
+  m_elements.reserve (other.m_elements.length (), true);
+  call_string::element_t *e;
   int i;
-  FOR_EACH_VEC_ELT (other.m_return_edges, i, e)
-    m_return_edges.quick_push (e);
+  FOR_EACH_VEC_ELT (other.m_elements, i, e)
+    m_elements.quick_push (*e);
   return *this;
 }
 
@@ -74,12 +103,12 @@ call_string::operator= (const call_string &other)
 bool
 call_string::operator== (const call_string &other) const
 {
-  if (m_return_edges.length () != other.m_return_edges.length ())
+  if (m_elements.length () != other.m_elements.length ())
     return false;
-  const return_superedge *e;
+  call_string::element_t *e;
   int i;
-  FOR_EACH_VEC_ELT (m_return_edges, i, e)
-    if (e != other.m_return_edges[i])
+  FOR_EACH_VEC_ELT (m_elements, i, e)
+    if (*e != other.m_elements[i])
       return false;
   return true;
 }
@@ -91,15 +120,15 @@ call_string::print (pretty_printer *pp) const
 {
   pp_string (pp, "[");
 
-  const return_superedge *e;
+  call_string::element_t *e;
   int i;
-  FOR_EACH_VEC_ELT (m_return_edges, i, e)
+  FOR_EACH_VEC_ELT (m_elements, i, e)
     {
       if (i > 0)
 	pp_string (pp, ", ");
       pp_printf (pp, "(SN: %i -> SN: %i in %s)",
-		 e->m_src->m_index, e->m_dest->m_index,
-		 function_name (e->m_dest->m_fun));
+		 e->m_callee->m_index, e->m_caller->m_index,
+		 function_name (e->m_caller->m_fun));
     }
 
   pp_string (pp, "]");
@@ -109,22 +138,22 @@ call_string::print (pretty_printer *pp) const
    [{"src_snode_idx" : int,
      "dst_snode_idx" : int,
      "funcname" : str},
-     ...for each return_superedge in the callstring].  */
+     ...for each element in the callstring].  */
 
 json::value *
 call_string::to_json () const
 {
   json::array *arr = new json::array ();
 
-  for (const return_superedge *e : m_return_edges)
+  for (const call_string::element_t &e : m_elements)
     {
       json::object *e_obj = new json::object ();
       e_obj->set ("src_snode_idx",
-		  new json::integer_number (e->m_src->m_index));
+		  new json::integer_number (e.m_callee->m_index));
       e_obj->set ("dst_snode_idx",
-		  new json::integer_number (e->m_dest->m_index));
+		  new json::integer_number (e.m_caller->m_index));
       e_obj->set ("funcname",
-		  new json::string (function_name (e->m_dest->m_fun)));
+		  new json::string (function_name (e.m_caller->m_fun)));
       arr->append (e_obj);
     }
 
@@ -137,8 +166,8 @@ hashval_t
 call_string::hash () const
 {
   inchash::hash hstate;
-  for (const return_superedge *e : m_return_edges)
-    hstate.add_ptr (e);
+  for (const call_string::element_t &e : m_elements)
+    hstate.add_ptr (e.m_caller);
   return hstate.end ();
 }
 
@@ -152,22 +181,36 @@ call_string::push_call (const supergraph &sg,
   gcc_assert (call_sedge);
   const return_superedge *return_sedge = call_sedge->get_edge_for_return (sg);
   gcc_assert (return_sedge);
-  m_return_edges.safe_push (return_sedge);
+  call_string::element_t e (return_sedge->m_dest, return_sedge->m_src);
+  m_elements.safe_push (e);
+}
+
+void
+call_string::push_call (const supernode *caller,
+			const supernode *callee)
+{
+  call_string::element_t e (caller, callee);
+  m_elements.safe_push (e);
+}
+
+call_string::element_t
+call_string::pop ()
+{
+  return m_elements.pop();
 }
 
 /* Count the number of times the top-most call site appears in the
    stack.  */
-
 int
 call_string::calc_recursion_depth () const
 {
-  if (m_return_edges.is_empty ())
+  if (m_elements.is_empty ())
     return 0;
-  const return_superedge *top_return_sedge
-    = m_return_edges[m_return_edges.length () - 1];
+  const call_string::element_t top_return_sedge 
+    = m_elements[m_elements.length () - 1];
 
   int result = 0;
-  for (const return_superedge *e : m_return_edges)
+  for (const call_string::element_t &e : m_elements)
     if (e == top_return_sedge)
       ++result;
   return result;
@@ -201,13 +244,15 @@ call_string::cmp (const call_string &a,
       if (i >= len_b)
 	return -1;
 
-      /* Otherwise, compare the edges.  */
-      const return_superedge *edge_a = a[i];
-      const return_superedge *edge_b = b[i];
-      int src_cmp = edge_a->m_src->m_index - edge_b->m_src->m_index;
+      /* Otherwise, compare the node pairs.  */
+      const call_string::element_t a_node_pair = a[i];
+      const call_string::element_t b_node_pair = b[i];
+      int src_cmp 
+      	= a_node_pair.m_callee->m_index - b_node_pair.m_callee->m_index;
       if (src_cmp)
 	return src_cmp;
-      int dest_cmp = edge_a->m_dest->m_index - edge_b->m_dest->m_index;
+      int dest_cmp 
+      	= a_node_pair.m_caller->m_index - b_node_pair.m_caller->m_index;
       if (dest_cmp)
 	return dest_cmp;
       i++;
@@ -215,6 +260,26 @@ call_string::cmp (const call_string &a,
     }
 }
 
+/* Return the pointer to callee of the topmost call in the stack,
+   or NULL if stack is empty.  */
+const supernode *
+call_string::get_callee_node () const
+{
+  if(m_elements.is_empty ())
+    return NULL;
+  return m_elements[m_elements.length () - 1].m_callee;
+}
+
+/* Return the pointer to caller of the topmost call in the stack,
+   or NULL if stack is empty.  */
+const supernode * 
+call_string::get_caller_node () const
+{
+  if(m_elements.is_empty ())
+    return NULL;
+  return m_elements[m_elements.length () - 1].m_caller;
+}
+
 /* Assert that this object is sane.  */
 
 void
@@ -226,12 +291,14 @@ call_string::validate () const
 #endif
 
   /* Each entry's "caller" should be the "callee" of the previous entry.  */
-  const return_superedge *e;
+  call_string::element_t *e;
   int i;
-  FOR_EACH_VEC_ELT (m_return_edges, i, e)
+  FOR_EACH_VEC_ELT (m_elements, i, e)
     if (i > 0)
-      gcc_assert (e->get_caller_function ()
-		  == m_return_edges[i - 1]->get_callee_function ());
+    {
+      gcc_assert (e->get_caller_function () == 
+      		  m_elements[i - 1].get_callee_function ());
+    }
 }
 
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/call-string.h b/gcc/analyzer/call-string.h
index 7721571ed60..a1ac60db4e9 100644
--- a/gcc/analyzer/call-string.h
+++ b/gcc/analyzer/call-string.h
@@ -24,22 +24,48 @@ along with GCC; see the file COPYING3.  If not see
 namespace ana {
 
 class supergraph;
+class supernode;
 class call_superedge;
 class return_superedge;
 
+
 /* A string of return_superedge pointers, representing a call stack
    at a program point.
 
    This is used to ensure that we generate interprocedurally valid paths
    i.e. that we return to the same callsite that called us.
 
-   The class actually stores the return edges, rather than the call edges,
-   since that's what we need to compare against.  */
+   The class stores returning calls ( which may be represented by a
+   returning superedge ). We do so because this is what we need to compare 
+   against.  */
 
 class call_string
 {
 public:
-  call_string () : m_return_edges () {}
+  /* A struct representing an element in the call_string.
+
+   Each element represents a path from m_callee to m_caller which represents
+   returning from function.  */
+
+  struct element_t
+  {
+    element_t (const supernode *caller, const supernode *callee)
+    :  m_caller (caller), m_callee (callee)
+    {
+    }
+
+    bool operator== (const element_t &other) const;
+    bool operator!= (const element_t &other) const;
+
+    /* Accessors */
+    function *get_caller_function () const;
+    function *get_callee_function () const;
+    
+    const supernode *m_caller;
+    const supernode *m_callee;
+  };
+
+  call_string () : m_elements () {}
   call_string (const call_string &other);
   call_string& operator= (const call_string &other);
 
@@ -51,27 +77,35 @@ public:
 
   hashval_t hash () const;
 
-  bool empty_p () const { return m_return_edges.is_empty (); }
+  bool empty_p () const { return m_elements.is_empty (); }
 
   void push_call (const supergraph &sg,
 		  const call_superedge *sedge);
-  const return_superedge *pop () { return m_return_edges.pop (); }
+
+  void push_call (const supernode *src, 
+    const supernode *dest);
+
+  element_t pop ();
 
   int calc_recursion_depth () const;
 
   static int cmp (const call_string &a,
 		  const call_string &b);
 
-  unsigned length () const { return m_return_edges.length (); }
-  const return_superedge *operator[] (unsigned idx) const
+  /* Accessors */
+
+  const supernode *get_callee_node () const;
+  const supernode *get_caller_node () const;
+  unsigned length () const { return m_elements.length (); }
+  element_t operator[] (unsigned idx) const
   {
-    return m_return_edges[idx];
+    return m_elements[idx];
   }
 
   void validate () const;
 
 private:
-  auto_vec<const return_superedge *> m_return_edges;
+  auto_vec<element_t> m_elements;
 };
 
 } // namespace ana
diff --git a/gcc/analyzer/program-point.cc b/gcc/analyzer/program-point.cc
index d73b6211141..d9f50daeb3c 100644
--- a/gcc/analyzer/program-point.cc
+++ b/gcc/analyzer/program-point.cc
@@ -350,7 +350,7 @@ program_point::get_function_at_depth (unsigned depth) const
   if (depth == m_call_string.length ())
     return m_function_point.get_function ();
   else
-    return m_call_string[depth]->get_caller_function ();
+    return m_call_string[depth].get_caller_function ();
 }
 
 /* Assert that this object is sane.  */
@@ -367,7 +367,7 @@ program_point::validate () const
   /* The "callee" of the final entry in the callstring should be the
      function of the m_function_point.  */
   if (m_call_string.length () > 0)
-    gcc_assert (m_call_string[m_call_string.length () - 1]->get_callee_function ()
+    gcc_assert (m_call_string[m_call_string.length () - 1].get_callee_function ()
 		== get_function ());
 }
 
@@ -438,8 +438,10 @@ program_point::on_edge (exploded_graph &eg,
 	      logger->log ("rejecting return edge: empty call string");
 	    return false;
 	  }
-	const return_superedge *top_of_stack = m_call_string.pop ();
-	if (top_of_stack != succ)
+	const call_string::element_t top_of_stack = m_call_string.pop ();
+	call_string::element_t current_call_string_element (succ->m_dest,
+							    succ->m_src);
+	if (top_of_stack != current_call_string_element)
 	  {
 	    if (logger)
 	      logger->log ("rejecting return edge: return to wrong callsite");


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-07-29  3:25 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-29  3:25 [gcc(refs/users/arsenic/heads/call_string_update)] analyzer: refactor callstring to work with pair of supernodes Ankur saini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).