aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/call-string.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/analyzer/call-string.cc')
-rw-r--r--gcc/analyzer/call-string.cc160
1 files changed, 95 insertions, 65 deletions
diff --git a/gcc/analyzer/call-string.cc b/gcc/analyzer/call-string.cc
index 2ccd3cc..a09f569 100644
--- a/gcc/analyzer/call-string.cc
+++ b/gcc/analyzer/call-string.cc
@@ -25,7 +25,6 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "options.h"
#include "json.h"
-#include "analyzer/call-string.h"
#include "ordered-hash-map.h"
#include "options.h"
#include "cgraph.h"
@@ -35,6 +34,9 @@ along with GCC; see the file COPYING3. If not see
#include "gimple.h"
#include "gimple-iterator.h"
#include "digraph.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/analyzer-logging.h"
+#include "analyzer/call-string.h"
#include "analyzer/supergraph.h"
#if ENABLE_ANALYZER
@@ -74,45 +76,6 @@ 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_elements (other.m_elements.length ())
-{
- for (const call_string::element_t &e : other.m_elements)
- m_elements.quick_push (e);
-}
-
-/* call_string's assignment operator. */
-
-call_string&
-call_string::operator= (const call_string &other)
-{
- // would be much simpler if we could rely on vec<> assignment op
- 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_elements, i, e)
- m_elements.quick_push (*e);
- return *this;
-}
-
-/* call_string's equality operator. */
-
-bool
-call_string::operator== (const call_string &other) const
-{
- if (m_elements.length () != other.m_elements.length ())
- return false;
- call_string::element_t *e;
- int i;
- FOR_EACH_VEC_ELT (m_elements, i, e)
- if (*e != other.m_elements[i])
- return false;
- return true;
-}
-
/* Print this to PP. */
void
@@ -160,43 +123,34 @@ call_string::to_json () const
return arr;
}
-/* Generate a hash value for this call_string. */
+/* Get or create the call_string resulting from pushing the return
+ superedge for CALL_SEDGE onto the end of this call_string. */
-hashval_t
-call_string::hash () const
-{
- inchash::hash hstate;
- for (const call_string::element_t &e : m_elements)
- hstate.add_ptr (e.m_caller);
- return hstate.end ();
-}
-
-/* Push the return superedge for CALL_SEDGE onto the end of this
- call_string. */
-
-void
+const call_string *
call_string::push_call (const supergraph &sg,
- const call_superedge *call_sedge)
+ const call_superedge *call_sedge) const
{
gcc_assert (call_sedge);
const return_superedge *return_sedge = call_sedge->get_edge_for_return (sg);
gcc_assert (return_sedge);
- call_string::element_t e (return_sedge->m_dest, return_sedge->m_src);
- m_elements.safe_push (e);
+ return push_call (return_sedge->m_dest, return_sedge->m_src);
}
-void
+/* Get or create the call_string resulting from pushing the call
+ (caller, callee) onto the end of this call_string. */
+
+const call_string *
call_string::push_call (const supernode *caller,
- const supernode *callee)
+ const supernode *callee) const
{
call_string::element_t e (caller, callee);
- m_elements.safe_push (e);
-}
-call_string::element_t
-call_string::pop ()
-{
- return m_elements.pop();
+ if (const call_string **slot = m_children.get (e))
+ return *slot;
+
+ call_string *result = new call_string (*this, e);
+ m_children.put (e, result);
+ return result;
}
/* Count the number of times the top-most call site appears in the
@@ -260,6 +214,16 @@ call_string::cmp (const call_string &a,
}
}
+/* Comparator for use by vec<const call_string *>::qsort. */
+
+int
+call_string::cmp_ptr_ptr (const void *pa, const void *pb)
+{
+ const call_string *cs_a = *static_cast <const call_string * const *> (pa);
+ const call_string *cs_b = *static_cast <const call_string * const *> (pb);
+ return cmp (*cs_a, *cs_b);
+}
+
/* Return the pointer to callee of the topmost call in the stack,
or NULL if stack is empty. */
const supernode *
@@ -290,6 +254,8 @@ call_string::validate () const
return;
#endif
+ gcc_assert (m_parent || m_elements.length () == 0);
+
/* Each entry's "caller" should be the "callee" of the previous entry. */
call_string::element_t *e;
int i;
@@ -299,4 +265,68 @@ call_string::validate () const
m_elements[i - 1].get_callee_function ());
}
+/* ctor for the root/empty call_string. */
+
+call_string::call_string ()
+: m_parent (NULL), m_elements ()
+{
+}
+
+/* ctor for a child call_string. */
+
+call_string::call_string (const call_string &parent, const element_t &to_push)
+: m_parent (&parent),
+ m_elements (parent.m_elements.length () + 1)
+{
+ m_elements.splice (parent.m_elements);
+ m_elements.quick_push (to_push);
+}
+
+/* dtor for call_string: recursively delete children. */
+
+call_string::~call_string ()
+{
+ for (auto child_iter : m_children)
+ delete child_iter.second;
+}
+
+/* Log this call_string and all its descendents recursively to LOGGER,
+ using indentation and elision to highlight the hierarchy. */
+
+void
+call_string::recursive_log (logger *logger) const
+{
+ logger->start_log_line ();
+ pretty_printer *pp = logger->get_printer ();
+ for (unsigned i = 0; i < length (); i++)
+ pp_string (pp, " ");
+ if (length () > 0)
+ {
+ pp_string (pp, "[");
+ /* Elide all but the final element, since they are shared with
+ the parent call_string. */
+ for (unsigned i = 0; i < length (); i++)
+ pp_string (pp, "..., ");
+ /* Log the final element in detail. */
+ const element_t *e = &m_elements[m_elements.length () - 1];
+ pp_printf (pp, "(SN: %i -> SN: %i in %s)]",
+ e->m_callee->m_index, e->m_caller->m_index,
+ function_name (e->m_caller->m_fun));
+ }
+ else
+ pp_string (pp, "[]");
+ logger->end_log_line ();
+
+ /* Recurse into children. */
+ {
+ auto_vec<const call_string *> children (m_children.elements ());
+ for (auto iter : m_children)
+ children.safe_push (iter.second);
+ children.qsort (call_string::cmp_ptr_ptr);
+
+ for (auto iter : children)
+ iter->recursive_log (logger);
+ }
+}
+
#endif /* #if ENABLE_ANALYZER */