1*0bfacb9bSmrg /* Classes for representing locations within the program. 2*0bfacb9bSmrg Copyright (C) 2019-2020 Free Software Foundation, Inc. 3*0bfacb9bSmrg Contributed by David Malcolm <dmalcolm@redhat.com>. 4*0bfacb9bSmrg 5*0bfacb9bSmrg This file is part of GCC. 6*0bfacb9bSmrg 7*0bfacb9bSmrg GCC is free software; you can redistribute it and/or modify it 8*0bfacb9bSmrg under the terms of the GNU General Public License as published by 9*0bfacb9bSmrg the Free Software Foundation; either version 3, or (at your option) 10*0bfacb9bSmrg any later version. 11*0bfacb9bSmrg 12*0bfacb9bSmrg GCC is distributed in the hope that it will be useful, but 13*0bfacb9bSmrg WITHOUT ANY WARRANTY; without even the implied warranty of 14*0bfacb9bSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15*0bfacb9bSmrg General Public License for more details. 16*0bfacb9bSmrg 17*0bfacb9bSmrg You should have received a copy of the GNU General Public License 18*0bfacb9bSmrg along with GCC; see the file COPYING3. If not see 19*0bfacb9bSmrg <http://www.gnu.org/licenses/>. */ 20*0bfacb9bSmrg 21*0bfacb9bSmrg #ifndef GCC_ANALYZER_PROGRAM_POINT_H 22*0bfacb9bSmrg #define GCC_ANALYZER_PROGRAM_POINT_H 23*0bfacb9bSmrg 24*0bfacb9bSmrg namespace ana { 25*0bfacb9bSmrg 26*0bfacb9bSmrg class exploded_graph; 27*0bfacb9bSmrg 28*0bfacb9bSmrg /* An enum for distinguishing the various kinds of program_point. */ 29*0bfacb9bSmrg 30*0bfacb9bSmrg enum point_kind { 31*0bfacb9bSmrg /* A "fake" node which has edges to all entrypoints. */ 32*0bfacb9bSmrg PK_ORIGIN, 33*0bfacb9bSmrg 34*0bfacb9bSmrg PK_BEFORE_SUPERNODE, 35*0bfacb9bSmrg PK_BEFORE_STMT, 36*0bfacb9bSmrg PK_AFTER_SUPERNODE, 37*0bfacb9bSmrg 38*0bfacb9bSmrg /* Special values used for hash_map: */ 39*0bfacb9bSmrg PK_EMPTY, 40*0bfacb9bSmrg PK_DELETED, 41*0bfacb9bSmrg 42*0bfacb9bSmrg NUM_POINT_KINDS 43*0bfacb9bSmrg }; 44*0bfacb9bSmrg 45*0bfacb9bSmrg extern const char *point_kind_to_string (enum point_kind pk); 46*0bfacb9bSmrg 47*0bfacb9bSmrg class format 48*0bfacb9bSmrg { 49*0bfacb9bSmrg public: format(bool newlines)50*0bfacb9bSmrg format (bool newlines) : m_newlines (newlines) {} 51*0bfacb9bSmrg spacer(pretty_printer * pp)52*0bfacb9bSmrg void spacer (pretty_printer *pp) const 53*0bfacb9bSmrg { 54*0bfacb9bSmrg if (m_newlines) 55*0bfacb9bSmrg pp_newline (pp); 56*0bfacb9bSmrg else 57*0bfacb9bSmrg pp_space (pp); 58*0bfacb9bSmrg } 59*0bfacb9bSmrg 60*0bfacb9bSmrg bool m_newlines; 61*0bfacb9bSmrg }; 62*0bfacb9bSmrg 63*0bfacb9bSmrg /* A class for representing a location within the program, without 64*0bfacb9bSmrg interprocedural information. 65*0bfacb9bSmrg 66*0bfacb9bSmrg This represents a fine-grained location within the supergraph (or 67*0bfacb9bSmrg within one of its nodes). */ 68*0bfacb9bSmrg 69*0bfacb9bSmrg class function_point 70*0bfacb9bSmrg { 71*0bfacb9bSmrg public: function_point(const supernode * supernode,const superedge * from_edge,unsigned stmt_idx,enum point_kind kind)72*0bfacb9bSmrg function_point (const supernode *supernode, 73*0bfacb9bSmrg const superedge *from_edge, 74*0bfacb9bSmrg unsigned stmt_idx, 75*0bfacb9bSmrg enum point_kind kind) 76*0bfacb9bSmrg : m_supernode (supernode), m_from_edge (from_edge), 77*0bfacb9bSmrg m_stmt_idx (stmt_idx), m_kind (kind) 78*0bfacb9bSmrg { 79*0bfacb9bSmrg if (from_edge) 80*0bfacb9bSmrg { 81*0bfacb9bSmrg gcc_checking_assert (m_kind == PK_BEFORE_SUPERNODE); 82*0bfacb9bSmrg gcc_checking_assert (from_edge->get_kind () == SUPEREDGE_CFG_EDGE); 83*0bfacb9bSmrg } 84*0bfacb9bSmrg if (stmt_idx) 85*0bfacb9bSmrg gcc_checking_assert (m_kind == PK_BEFORE_STMT); 86*0bfacb9bSmrg } 87*0bfacb9bSmrg 88*0bfacb9bSmrg void print (pretty_printer *pp, const format &f) const; 89*0bfacb9bSmrg void print_source_line (pretty_printer *pp) const; 90*0bfacb9bSmrg void dump () const; 91*0bfacb9bSmrg 92*0bfacb9bSmrg hashval_t hash () const; 93*0bfacb9bSmrg bool operator== (const function_point &other) const 94*0bfacb9bSmrg { 95*0bfacb9bSmrg return (m_supernode == other.m_supernode 96*0bfacb9bSmrg && m_from_edge == other.m_from_edge 97*0bfacb9bSmrg && m_stmt_idx == other.m_stmt_idx 98*0bfacb9bSmrg && m_kind == other.m_kind); 99*0bfacb9bSmrg } 100*0bfacb9bSmrg 101*0bfacb9bSmrg /* Accessors. */ 102*0bfacb9bSmrg get_supernode()103*0bfacb9bSmrg const supernode *get_supernode () const { return m_supernode; } get_function()104*0bfacb9bSmrg function *get_function () const 105*0bfacb9bSmrg { 106*0bfacb9bSmrg if (m_supernode) 107*0bfacb9bSmrg return m_supernode->m_fun; 108*0bfacb9bSmrg else 109*0bfacb9bSmrg return NULL; 110*0bfacb9bSmrg } 111*0bfacb9bSmrg const gimple *get_stmt () const; 112*0bfacb9bSmrg location_t get_location () const; get_kind()113*0bfacb9bSmrg enum point_kind get_kind () const { return m_kind; } get_from_edge()114*0bfacb9bSmrg const superedge *get_from_edge () const 115*0bfacb9bSmrg { 116*0bfacb9bSmrg return m_from_edge; 117*0bfacb9bSmrg } get_stmt_idx()118*0bfacb9bSmrg unsigned get_stmt_idx () const 119*0bfacb9bSmrg { 120*0bfacb9bSmrg gcc_assert (m_kind == PK_BEFORE_STMT); 121*0bfacb9bSmrg return m_stmt_idx; 122*0bfacb9bSmrg } 123*0bfacb9bSmrg 124*0bfacb9bSmrg /* Factory functions for making various kinds of program_point. */ 125*0bfacb9bSmrg from_function_entry(const supergraph & sg,function * fun)126*0bfacb9bSmrg static function_point from_function_entry (const supergraph &sg, 127*0bfacb9bSmrg function *fun) 128*0bfacb9bSmrg { 129*0bfacb9bSmrg return before_supernode (sg.get_node_for_function_entry (fun), 130*0bfacb9bSmrg NULL); 131*0bfacb9bSmrg } 132*0bfacb9bSmrg before_supernode(const supernode * supernode,const superedge * from_edge)133*0bfacb9bSmrg static function_point before_supernode (const supernode *supernode, 134*0bfacb9bSmrg const superedge *from_edge) 135*0bfacb9bSmrg { 136*0bfacb9bSmrg if (from_edge && from_edge->get_kind () != SUPEREDGE_CFG_EDGE) 137*0bfacb9bSmrg from_edge = NULL; 138*0bfacb9bSmrg return function_point (supernode, from_edge, 0, PK_BEFORE_SUPERNODE); 139*0bfacb9bSmrg } 140*0bfacb9bSmrg before_stmt(const supernode * supernode,unsigned stmt_idx)141*0bfacb9bSmrg static function_point before_stmt (const supernode *supernode, 142*0bfacb9bSmrg unsigned stmt_idx) 143*0bfacb9bSmrg { 144*0bfacb9bSmrg return function_point (supernode, NULL, stmt_idx, PK_BEFORE_STMT); 145*0bfacb9bSmrg } 146*0bfacb9bSmrg after_supernode(const supernode * supernode)147*0bfacb9bSmrg static function_point after_supernode (const supernode *supernode) 148*0bfacb9bSmrg { 149*0bfacb9bSmrg return function_point (supernode, NULL, 0, PK_AFTER_SUPERNODE); 150*0bfacb9bSmrg } 151*0bfacb9bSmrg 152*0bfacb9bSmrg /* Support for hash_map. */ 153*0bfacb9bSmrg empty()154*0bfacb9bSmrg static function_point empty () 155*0bfacb9bSmrg { 156*0bfacb9bSmrg return function_point (NULL, NULL, 0, PK_EMPTY); 157*0bfacb9bSmrg } deleted()158*0bfacb9bSmrg static function_point deleted () 159*0bfacb9bSmrg { 160*0bfacb9bSmrg return function_point (NULL, NULL, 0, PK_DELETED); 161*0bfacb9bSmrg } 162*0bfacb9bSmrg 163*0bfacb9bSmrg static int cmp_within_supernode_1 (const function_point &point_a, 164*0bfacb9bSmrg const function_point &point_b); 165*0bfacb9bSmrg static int cmp_within_supernode (const function_point &point_a, 166*0bfacb9bSmrg const function_point &point_b); 167*0bfacb9bSmrg 168*0bfacb9bSmrg private: 169*0bfacb9bSmrg const supernode *m_supernode; 170*0bfacb9bSmrg 171*0bfacb9bSmrg /* For PK_BEFORE_SUPERNODE, and only for CFG edges. */ 172*0bfacb9bSmrg const superedge *m_from_edge; 173*0bfacb9bSmrg 174*0bfacb9bSmrg /* Only for PK_BEFORE_STMT. */ 175*0bfacb9bSmrg unsigned m_stmt_idx; 176*0bfacb9bSmrg 177*0bfacb9bSmrg enum point_kind m_kind; 178*0bfacb9bSmrg }; 179*0bfacb9bSmrg 180*0bfacb9bSmrg /* A class for representing a location within the program, including 181*0bfacb9bSmrg interprocedural information. 182*0bfacb9bSmrg 183*0bfacb9bSmrg This represents a fine-grained location within the supergraph (or 184*0bfacb9bSmrg within one of its nodes), along with a call string giving the 185*0bfacb9bSmrg interprocedural context. */ 186*0bfacb9bSmrg 187*0bfacb9bSmrg class program_point 188*0bfacb9bSmrg { 189*0bfacb9bSmrg public: program_point(const function_point & fn_point,const call_string & call_string)190*0bfacb9bSmrg program_point (const function_point &fn_point, 191*0bfacb9bSmrg const call_string &call_string) 192*0bfacb9bSmrg : m_function_point (fn_point), 193*0bfacb9bSmrg m_call_string (call_string) 194*0bfacb9bSmrg { 195*0bfacb9bSmrg } 196*0bfacb9bSmrg 197*0bfacb9bSmrg void print (pretty_printer *pp, const format &f) const; 198*0bfacb9bSmrg void print_source_line (pretty_printer *pp) const; 199*0bfacb9bSmrg void dump () const; 200*0bfacb9bSmrg 201*0bfacb9bSmrg hashval_t hash () const; 202*0bfacb9bSmrg bool operator== (const program_point &other) const 203*0bfacb9bSmrg { 204*0bfacb9bSmrg return (m_function_point == other.m_function_point 205*0bfacb9bSmrg && m_call_string == other.m_call_string); 206*0bfacb9bSmrg } 207*0bfacb9bSmrg 208*0bfacb9bSmrg /* Accessors. */ 209*0bfacb9bSmrg get_function_point()210*0bfacb9bSmrg const function_point &get_function_point () const { return m_function_point; } get_call_string()211*0bfacb9bSmrg const call_string &get_call_string () const { return m_call_string; } 212*0bfacb9bSmrg get_supernode()213*0bfacb9bSmrg const supernode *get_supernode () const 214*0bfacb9bSmrg { 215*0bfacb9bSmrg return m_function_point.get_supernode (); 216*0bfacb9bSmrg } get_function()217*0bfacb9bSmrg function *get_function () const 218*0bfacb9bSmrg { 219*0bfacb9bSmrg return m_function_point.get_function (); 220*0bfacb9bSmrg } 221*0bfacb9bSmrg function *get_function_at_depth (unsigned depth) const; get_fndecl()222*0bfacb9bSmrg tree get_fndecl () const 223*0bfacb9bSmrg { 224*0bfacb9bSmrg gcc_assert (get_kind () != PK_ORIGIN); 225*0bfacb9bSmrg return get_function ()->decl; 226*0bfacb9bSmrg } get_stmt()227*0bfacb9bSmrg const gimple *get_stmt () const 228*0bfacb9bSmrg { 229*0bfacb9bSmrg return m_function_point.get_stmt (); 230*0bfacb9bSmrg } get_location()231*0bfacb9bSmrg location_t get_location () const 232*0bfacb9bSmrg { 233*0bfacb9bSmrg return m_function_point.get_location (); 234*0bfacb9bSmrg } get_kind()235*0bfacb9bSmrg enum point_kind get_kind () const 236*0bfacb9bSmrg { 237*0bfacb9bSmrg return m_function_point.get_kind (); 238*0bfacb9bSmrg } get_from_edge()239*0bfacb9bSmrg const superedge *get_from_edge () const 240*0bfacb9bSmrg { 241*0bfacb9bSmrg return m_function_point.get_from_edge (); 242*0bfacb9bSmrg } get_stmt_idx()243*0bfacb9bSmrg unsigned get_stmt_idx () const 244*0bfacb9bSmrg { 245*0bfacb9bSmrg return m_function_point.get_stmt_idx (); 246*0bfacb9bSmrg } 247*0bfacb9bSmrg 248*0bfacb9bSmrg /* Get the number of frames we expect at this program point. 249*0bfacb9bSmrg This will be one more than the length of the call_string 250*0bfacb9bSmrg (which stores the parent callsites), apart from the origin 251*0bfacb9bSmrg node, which doesn't have any frames. */ get_stack_depth()252*0bfacb9bSmrg int get_stack_depth () const 253*0bfacb9bSmrg { 254*0bfacb9bSmrg if (get_kind () == PK_ORIGIN) 255*0bfacb9bSmrg return 0; 256*0bfacb9bSmrg return m_call_string.length () + 1; 257*0bfacb9bSmrg } 258*0bfacb9bSmrg 259*0bfacb9bSmrg /* Factory functions for making various kinds of program_point. */ 260*0bfacb9bSmrg from_function_entry(const supergraph & sg,function * fun)261*0bfacb9bSmrg static program_point from_function_entry (const supergraph &sg, 262*0bfacb9bSmrg function *fun) 263*0bfacb9bSmrg { 264*0bfacb9bSmrg return program_point (function_point::from_function_entry (sg, fun), 265*0bfacb9bSmrg call_string ()); 266*0bfacb9bSmrg } 267*0bfacb9bSmrg before_supernode(const supernode * supernode,const superedge * from_edge,const call_string & call_string)268*0bfacb9bSmrg static program_point before_supernode (const supernode *supernode, 269*0bfacb9bSmrg const superedge *from_edge, 270*0bfacb9bSmrg const call_string &call_string) 271*0bfacb9bSmrg { 272*0bfacb9bSmrg return program_point (function_point::before_supernode (supernode, 273*0bfacb9bSmrg from_edge), 274*0bfacb9bSmrg call_string); 275*0bfacb9bSmrg } 276*0bfacb9bSmrg before_stmt(const supernode * supernode,unsigned stmt_idx,const call_string & call_string)277*0bfacb9bSmrg static program_point before_stmt (const supernode *supernode, 278*0bfacb9bSmrg unsigned stmt_idx, 279*0bfacb9bSmrg const call_string &call_string) 280*0bfacb9bSmrg { 281*0bfacb9bSmrg return program_point (function_point::before_stmt (supernode, stmt_idx), 282*0bfacb9bSmrg call_string); 283*0bfacb9bSmrg } 284*0bfacb9bSmrg after_supernode(const supernode * supernode,const call_string & call_string)285*0bfacb9bSmrg static program_point after_supernode (const supernode *supernode, 286*0bfacb9bSmrg const call_string &call_string) 287*0bfacb9bSmrg { 288*0bfacb9bSmrg return program_point (function_point::after_supernode (supernode), 289*0bfacb9bSmrg call_string); 290*0bfacb9bSmrg } 291*0bfacb9bSmrg 292*0bfacb9bSmrg /* Support for hash_map. */ 293*0bfacb9bSmrg empty()294*0bfacb9bSmrg static program_point empty () 295*0bfacb9bSmrg { 296*0bfacb9bSmrg return program_point (function_point::empty (), call_string ()); 297*0bfacb9bSmrg } deleted()298*0bfacb9bSmrg static program_point deleted () 299*0bfacb9bSmrg { 300*0bfacb9bSmrg return program_point (function_point::deleted (), call_string ()); 301*0bfacb9bSmrg } 302*0bfacb9bSmrg 303*0bfacb9bSmrg bool on_edge (exploded_graph &eg, const superedge *succ); 304*0bfacb9bSmrg 305*0bfacb9bSmrg void validate () const; 306*0bfacb9bSmrg 307*0bfacb9bSmrg private: 308*0bfacb9bSmrg const function_point m_function_point; 309*0bfacb9bSmrg call_string m_call_string; 310*0bfacb9bSmrg }; 311*0bfacb9bSmrg 312*0bfacb9bSmrg } // namespace ana 313*0bfacb9bSmrg 314*0bfacb9bSmrg #endif /* GCC_ANALYZER_PROGRAM_POINT_H */ 315