diff options
Diffstat (limited to 'gcc/analyzer/call-string.cc')
-rw-r--r-- | gcc/analyzer/call-string.cc | 160 |
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 */ |