1 1.1 mrg /* Call stacks at program points. 2 1.1.1.2 mrg Copyright (C) 2019-2022 Free Software Foundation, Inc. 3 1.1 mrg Contributed by David Malcolm <dmalcolm (at) redhat.com>. 4 1.1 mrg 5 1.1 mrg This file is part of GCC. 6 1.1 mrg 7 1.1 mrg GCC is free software; you can redistribute it and/or modify it 8 1.1 mrg under the terms of the GNU General Public License as published by 9 1.1 mrg the Free Software Foundation; either version 3, or (at your option) 10 1.1 mrg any later version. 11 1.1 mrg 12 1.1 mrg GCC is distributed in the hope that it will be useful, but 13 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 1.1 mrg General Public License for more details. 16 1.1 mrg 17 1.1 mrg You should have received a copy of the GNU General Public License 18 1.1 mrg along with GCC; see the file COPYING3. If not see 19 1.1 mrg <http://www.gnu.org/licenses/>. */ 20 1.1 mrg 21 1.1 mrg #include "config.h" 22 1.1 mrg #include "system.h" 23 1.1 mrg #include "coretypes.h" 24 1.1 mrg #include "pretty-print.h" 25 1.1 mrg #include "tree.h" 26 1.1 mrg #include "options.h" 27 1.1.1.2 mrg #include "json.h" 28 1.1 mrg #include "analyzer/call-string.h" 29 1.1 mrg #include "ordered-hash-map.h" 30 1.1 mrg #include "options.h" 31 1.1 mrg #include "cgraph.h" 32 1.1 mrg #include "function.h" 33 1.1 mrg #include "cfg.h" 34 1.1 mrg #include "basic-block.h" 35 1.1 mrg #include "gimple.h" 36 1.1 mrg #include "gimple-iterator.h" 37 1.1 mrg #include "digraph.h" 38 1.1 mrg #include "analyzer/supergraph.h" 39 1.1 mrg 40 1.1 mrg #if ENABLE_ANALYZER 41 1.1 mrg 42 1.1.1.2 mrg #if __GNUC__ >= 10 43 1.1.1.2 mrg #pragma GCC diagnostic ignored "-Wformat-diag" 44 1.1.1.2 mrg #endif 45 1.1.1.2 mrg 46 1.1 mrg /* class call_string. */ 47 1.1 mrg 48 1.1.1.2 mrg /* struct call_string::element_t. */ 49 1.1.1.2 mrg 50 1.1.1.2 mrg /* call_string::element_t's equality operator. */ 51 1.1.1.2 mrg 52 1.1.1.2 mrg bool 53 1.1.1.2 mrg call_string::element_t::operator== (const call_string::element_t &other) const 54 1.1.1.2 mrg { 55 1.1.1.2 mrg return (m_caller == other.m_caller && m_callee == other.m_callee); 56 1.1.1.2 mrg } 57 1.1.1.2 mrg 58 1.1.1.2 mrg /* call_string::element_t's inequality operator. */ 59 1.1.1.2 mrg bool 60 1.1.1.2 mrg call_string::element_t::operator!= (const call_string::element_t &other) const 61 1.1.1.2 mrg { 62 1.1.1.2 mrg return !(*this == other); 63 1.1.1.2 mrg } 64 1.1.1.2 mrg 65 1.1.1.2 mrg function * 66 1.1.1.2 mrg call_string::element_t::get_caller_function () const 67 1.1.1.2 mrg { 68 1.1.1.2 mrg return m_caller->get_function (); 69 1.1.1.2 mrg } 70 1.1.1.2 mrg 71 1.1.1.2 mrg function * 72 1.1.1.2 mrg call_string::element_t::get_callee_function () const 73 1.1.1.2 mrg { 74 1.1.1.2 mrg return m_callee->get_function (); 75 1.1.1.2 mrg } 76 1.1.1.2 mrg 77 1.1 mrg /* call_string's copy ctor. */ 78 1.1 mrg 79 1.1 mrg call_string::call_string (const call_string &other) 80 1.1.1.2 mrg : m_elements (other.m_elements.length ()) 81 1.1 mrg { 82 1.1.1.2 mrg for (const call_string::element_t &e : other.m_elements) 83 1.1.1.2 mrg m_elements.quick_push (e); 84 1.1 mrg } 85 1.1 mrg 86 1.1 mrg /* call_string's assignment operator. */ 87 1.1 mrg 88 1.1 mrg call_string& 89 1.1 mrg call_string::operator= (const call_string &other) 90 1.1 mrg { 91 1.1 mrg // would be much simpler if we could rely on vec<> assignment op 92 1.1.1.2 mrg m_elements.truncate (0); 93 1.1.1.2 mrg m_elements.reserve (other.m_elements.length (), true); 94 1.1.1.2 mrg call_string::element_t *e; 95 1.1 mrg int i; 96 1.1.1.2 mrg FOR_EACH_VEC_ELT (other.m_elements, i, e) 97 1.1.1.2 mrg m_elements.quick_push (*e); 98 1.1 mrg return *this; 99 1.1 mrg } 100 1.1 mrg 101 1.1 mrg /* call_string's equality operator. */ 102 1.1 mrg 103 1.1 mrg bool 104 1.1 mrg call_string::operator== (const call_string &other) const 105 1.1 mrg { 106 1.1.1.2 mrg if (m_elements.length () != other.m_elements.length ()) 107 1.1 mrg return false; 108 1.1.1.2 mrg call_string::element_t *e; 109 1.1 mrg int i; 110 1.1.1.2 mrg FOR_EACH_VEC_ELT (m_elements, i, e) 111 1.1.1.2 mrg if (*e != other.m_elements[i]) 112 1.1 mrg return false; 113 1.1 mrg return true; 114 1.1 mrg } 115 1.1 mrg 116 1.1 mrg /* Print this to PP. */ 117 1.1 mrg 118 1.1 mrg void 119 1.1 mrg call_string::print (pretty_printer *pp) const 120 1.1 mrg { 121 1.1 mrg pp_string (pp, "["); 122 1.1 mrg 123 1.1.1.2 mrg call_string::element_t *e; 124 1.1 mrg int i; 125 1.1.1.2 mrg FOR_EACH_VEC_ELT (m_elements, i, e) 126 1.1 mrg { 127 1.1 mrg if (i > 0) 128 1.1 mrg pp_string (pp, ", "); 129 1.1 mrg pp_printf (pp, "(SN: %i -> SN: %i in %s)", 130 1.1.1.2 mrg e->m_callee->m_index, e->m_caller->m_index, 131 1.1.1.2 mrg function_name (e->m_caller->m_fun)); 132 1.1 mrg } 133 1.1 mrg 134 1.1 mrg pp_string (pp, "]"); 135 1.1 mrg } 136 1.1 mrg 137 1.1.1.2 mrg /* Return a new json::array of the form 138 1.1.1.2 mrg [{"src_snode_idx" : int, 139 1.1.1.2 mrg "dst_snode_idx" : int, 140 1.1.1.2 mrg "funcname" : str}, 141 1.1.1.2 mrg ...for each element in the callstring]. */ 142 1.1.1.2 mrg 143 1.1.1.2 mrg json::value * 144 1.1.1.2 mrg call_string::to_json () const 145 1.1.1.2 mrg { 146 1.1.1.2 mrg json::array *arr = new json::array (); 147 1.1.1.2 mrg 148 1.1.1.2 mrg for (const call_string::element_t &e : m_elements) 149 1.1.1.2 mrg { 150 1.1.1.2 mrg json::object *e_obj = new json::object (); 151 1.1.1.2 mrg e_obj->set ("src_snode_idx", 152 1.1.1.2 mrg new json::integer_number (e.m_callee->m_index)); 153 1.1.1.2 mrg e_obj->set ("dst_snode_idx", 154 1.1.1.2 mrg new json::integer_number (e.m_caller->m_index)); 155 1.1.1.2 mrg e_obj->set ("funcname", 156 1.1.1.2 mrg new json::string (function_name (e.m_caller->m_fun))); 157 1.1.1.2 mrg arr->append (e_obj); 158 1.1.1.2 mrg } 159 1.1.1.2 mrg 160 1.1.1.2 mrg return arr; 161 1.1.1.2 mrg } 162 1.1.1.2 mrg 163 1.1 mrg /* Generate a hash value for this call_string. */ 164 1.1 mrg 165 1.1 mrg hashval_t 166 1.1 mrg call_string::hash () const 167 1.1 mrg { 168 1.1 mrg inchash::hash hstate; 169 1.1.1.2 mrg for (const call_string::element_t &e : m_elements) 170 1.1.1.2 mrg hstate.add_ptr (e.m_caller); 171 1.1 mrg return hstate.end (); 172 1.1 mrg } 173 1.1 mrg 174 1.1 mrg /* Push the return superedge for CALL_SEDGE onto the end of this 175 1.1 mrg call_string. */ 176 1.1 mrg 177 1.1 mrg void 178 1.1 mrg call_string::push_call (const supergraph &sg, 179 1.1 mrg const call_superedge *call_sedge) 180 1.1 mrg { 181 1.1 mrg gcc_assert (call_sedge); 182 1.1 mrg const return_superedge *return_sedge = call_sedge->get_edge_for_return (sg); 183 1.1 mrg gcc_assert (return_sedge); 184 1.1.1.2 mrg call_string::element_t e (return_sedge->m_dest, return_sedge->m_src); 185 1.1.1.2 mrg m_elements.safe_push (e); 186 1.1.1.2 mrg } 187 1.1.1.2 mrg 188 1.1.1.2 mrg void 189 1.1.1.2 mrg call_string::push_call (const supernode *caller, 190 1.1.1.2 mrg const supernode *callee) 191 1.1.1.2 mrg { 192 1.1.1.2 mrg call_string::element_t e (caller, callee); 193 1.1.1.2 mrg m_elements.safe_push (e); 194 1.1.1.2 mrg } 195 1.1.1.2 mrg 196 1.1.1.2 mrg call_string::element_t 197 1.1.1.2 mrg call_string::pop () 198 1.1.1.2 mrg { 199 1.1.1.2 mrg return m_elements.pop(); 200 1.1 mrg } 201 1.1 mrg 202 1.1 mrg /* Count the number of times the top-most call site appears in the 203 1.1 mrg stack. */ 204 1.1 mrg int 205 1.1 mrg call_string::calc_recursion_depth () const 206 1.1 mrg { 207 1.1.1.2 mrg if (m_elements.is_empty ()) 208 1.1 mrg return 0; 209 1.1.1.2 mrg const call_string::element_t top_return_sedge 210 1.1.1.2 mrg = m_elements[m_elements.length () - 1]; 211 1.1 mrg 212 1.1 mrg int result = 0; 213 1.1.1.2 mrg for (const call_string::element_t &e : m_elements) 214 1.1 mrg if (e == top_return_sedge) 215 1.1 mrg ++result; 216 1.1 mrg return result; 217 1.1 mrg } 218 1.1 mrg 219 1.1 mrg /* Comparator for call strings. 220 1.1 mrg This implements a version of lexicographical order. 221 1.1 mrg Return negative if A is before B. 222 1.1 mrg Return positive if B is after A. 223 1.1 mrg Return 0 if they are equal. */ 224 1.1 mrg 225 1.1 mrg int 226 1.1 mrg call_string::cmp (const call_string &a, 227 1.1 mrg const call_string &b) 228 1.1 mrg { 229 1.1 mrg unsigned len_a = a.length (); 230 1.1 mrg unsigned len_b = b.length (); 231 1.1 mrg 232 1.1 mrg unsigned i = 0; 233 1.1 mrg while (1) 234 1.1 mrg { 235 1.1 mrg /* Consider index i; the strings have been equal up to it. */ 236 1.1 mrg 237 1.1 mrg /* Have both strings run out? */ 238 1.1 mrg if (i >= len_a && i >= len_b) 239 1.1 mrg return 0; 240 1.1 mrg 241 1.1 mrg /* Otherwise, has just one of the strings run out? */ 242 1.1 mrg if (i >= len_a) 243 1.1 mrg return 1; 244 1.1 mrg if (i >= len_b) 245 1.1 mrg return -1; 246 1.1 mrg 247 1.1.1.2 mrg /* Otherwise, compare the node pairs. */ 248 1.1.1.2 mrg const call_string::element_t a_node_pair = a[i]; 249 1.1.1.2 mrg const call_string::element_t b_node_pair = b[i]; 250 1.1.1.2 mrg int src_cmp 251 1.1.1.2 mrg = a_node_pair.m_callee->m_index - b_node_pair.m_callee->m_index; 252 1.1 mrg if (src_cmp) 253 1.1 mrg return src_cmp; 254 1.1.1.2 mrg int dest_cmp 255 1.1.1.2 mrg = a_node_pair.m_caller->m_index - b_node_pair.m_caller->m_index; 256 1.1 mrg if (dest_cmp) 257 1.1 mrg return dest_cmp; 258 1.1 mrg i++; 259 1.1 mrg // TODO: test coverage for this 260 1.1 mrg } 261 1.1 mrg } 262 1.1 mrg 263 1.1.1.2 mrg /* Return the pointer to callee of the topmost call in the stack, 264 1.1.1.2 mrg or NULL if stack is empty. */ 265 1.1.1.2 mrg const supernode * 266 1.1.1.2 mrg call_string::get_callee_node () const 267 1.1.1.2 mrg { 268 1.1.1.2 mrg if(m_elements.is_empty ()) 269 1.1.1.2 mrg return NULL; 270 1.1.1.2 mrg return m_elements[m_elements.length () - 1].m_callee; 271 1.1.1.2 mrg } 272 1.1.1.2 mrg 273 1.1.1.2 mrg /* Return the pointer to caller of the topmost call in the stack, 274 1.1.1.2 mrg or NULL if stack is empty. */ 275 1.1.1.2 mrg const supernode * 276 1.1.1.2 mrg call_string::get_caller_node () const 277 1.1.1.2 mrg { 278 1.1.1.2 mrg if(m_elements.is_empty ()) 279 1.1.1.2 mrg return NULL; 280 1.1.1.2 mrg return m_elements[m_elements.length () - 1].m_caller; 281 1.1.1.2 mrg } 282 1.1.1.2 mrg 283 1.1 mrg /* Assert that this object is sane. */ 284 1.1 mrg 285 1.1 mrg void 286 1.1 mrg call_string::validate () const 287 1.1 mrg { 288 1.1 mrg /* Skip this in a release build. */ 289 1.1 mrg #if !CHECKING_P 290 1.1 mrg return; 291 1.1 mrg #endif 292 1.1 mrg 293 1.1 mrg /* Each entry's "caller" should be the "callee" of the previous entry. */ 294 1.1.1.2 mrg call_string::element_t *e; 295 1.1 mrg int i; 296 1.1.1.2 mrg FOR_EACH_VEC_ELT (m_elements, i, e) 297 1.1 mrg if (i > 0) 298 1.1.1.2 mrg { 299 1.1.1.2 mrg gcc_assert (e->get_caller_function () == 300 1.1.1.2 mrg m_elements[i - 1].get_callee_function ()); 301 1.1.1.2 mrg } 302 1.1 mrg } 303 1.1 mrg 304 1.1 mrg #endif /* #if ENABLE_ANALYZER */ 305