1/* "Supergraph" classes that combine CFGs and callgraph into one digraph. 2 Copyright (C) 2019-2020 Free Software Foundation, Inc. 3 Contributed by David Malcolm <dmalcolm@redhat.com>. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it 8under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 3, or (at your option) 10any later version. 11 12GCC is distributed in the hope that it will be useful, but 13WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING3. If not see 19<http://www.gnu.org/licenses/>. */ 20 21#include "config.h" 22#include "system.h" 23#include "coretypes.h" 24#include "tree.h" 25#include "tm.h" 26#include "toplev.h" 27#include "hash-table.h" 28#include "vec.h" 29#include "ggc.h" 30#include "basic-block.h" 31#include "function.h" 32#include "gimple-fold.h" 33#include "tree-eh.h" 34#include "gimple-expr.h" 35#include "is-a.h" 36#include "timevar.h" 37#include "gimple.h" 38#include "gimple-iterator.h" 39#include "gimple-pretty-print.h" 40#include "tree-pretty-print.h" 41#include "graphviz.h" 42#include "cgraph.h" 43#include "tree-dfa.h" 44#include "cfganal.h" 45#include "function.h" 46#include "analyzer/analyzer.h" 47#include "ordered-hash-map.h" 48#include "options.h" 49#include "cgraph.h" 50#include "cfg.h" 51#include "digraph.h" 52#include "analyzer/supergraph.h" 53#include "analyzer/analyzer-logging.h" 54 55#if ENABLE_ANALYZER 56 57namespace ana { 58 59/* Get the function of the ultimate alias target being called at EDGE, 60 if any. */ 61 62static function * 63get_ultimate_function_for_cgraph_edge (cgraph_edge *edge) 64{ 65 cgraph_node *ultimate_node = edge->callee->ultimate_alias_target (); 66 if (!ultimate_node) 67 return NULL; 68 return ultimate_node->get_fun (); 69} 70 71/* Get the cgraph_edge, but only if there's an underlying function body. */ 72 73cgraph_edge * 74supergraph_call_edge (function *fun, gimple *stmt) 75{ 76 gcall *call = dyn_cast<gcall *> (stmt); 77 if (!call) 78 return NULL; 79 cgraph_edge *edge = cgraph_node::get (fun->decl)->get_edge (stmt); 80 if (!edge) 81 return NULL; 82 if (!edge->callee) 83 return NULL; /* e.g. for a function pointer. */ 84 if (!get_ultimate_function_for_cgraph_edge (edge)) 85 return NULL; 86 return edge; 87} 88 89/* supergraph's ctor. Walk the callgraph, building supernodes for each 90 CFG basic block, splitting the basic blocks at callsites. Join 91 together the supernodes with interprocedural and intraprocedural 92 superedges as appropriate. */ 93 94supergraph::supergraph (logger *logger) 95{ 96 auto_timevar tv (TV_ANALYZER_SUPERGRAPH); 97 98 LOG_FUNC (logger); 99 100 /* First pass: make supernodes. */ 101 { 102 /* Sort the cgraph_nodes? */ 103 cgraph_node *node; 104 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) 105 { 106 function *fun = node->get_fun (); 107 108 /* Ensure that EDGE_DFS_BACK is correct for every CFG edge in 109 the supergraph (by doing it per-function). */ 110 auto_cfun sentinel (fun); 111 mark_dfs_back_edges (); 112 113 const int start_idx = m_nodes.length (); 114 115 basic_block bb; 116 FOR_ALL_BB_FN (bb, fun) 117 { 118 /* The initial supernode for the BB gets the phi nodes (if any). */ 119 supernode *node_for_stmts = add_node (fun, bb, NULL, phi_nodes (bb)); 120 m_bb_to_initial_node.put (bb, node_for_stmts); 121 for (gphi_iterator gpi = gsi_start_phis (bb); !gsi_end_p (gpi); 122 gsi_next (&gpi)) 123 { 124 gimple *stmt = gsi_stmt (gpi); 125 m_stmt_to_node_t.put (stmt, node_for_stmts); 126 } 127 128 /* Append statements from BB to the current supernode, splitting 129 them into a new supernode at each call site; such call statements 130 appear in both supernodes (representing call and return). */ 131 gimple_stmt_iterator gsi; 132 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 133 { 134 gimple *stmt = gsi_stmt (gsi); 135 node_for_stmts->m_stmts.safe_push (stmt); 136 m_stmt_to_node_t.put (stmt, node_for_stmts); 137 if (cgraph_edge *edge = supergraph_call_edge (fun, stmt)) 138 { 139 m_cgraph_edge_to_caller_prev_node.put(edge, node_for_stmts); 140 node_for_stmts = add_node (fun, bb, as_a <gcall *> (stmt), NULL); 141 m_cgraph_edge_to_caller_next_node.put (edge, node_for_stmts); 142 } 143 } 144 145 m_bb_to_final_node.put (bb, node_for_stmts); 146 } 147 148 const unsigned num_snodes = m_nodes.length () - start_idx; 149 m_function_to_num_snodes.put (fun, num_snodes); 150 151 if (logger) 152 { 153 const int end_idx = m_nodes.length () - 1; 154 logger->log ("SN: %i...%i: function %qD", 155 start_idx, end_idx, fun->decl); 156 } 157 } 158 } 159 160 /* Second pass: make superedges. */ 161 { 162 /* Make superedges for CFG edges. */ 163 for (bb_to_node_t::iterator iter = m_bb_to_final_node.begin (); 164 iter != m_bb_to_final_node.end (); 165 ++iter) 166 { 167 basic_block bb = (*iter).first; 168 supernode *src_supernode = (*iter).second; 169 170 ::edge cfg_edge; 171 int idx; 172 if (bb->succs) 173 FOR_EACH_VEC_ELT (*bb->succs, idx, cfg_edge) 174 { 175 basic_block dest_cfg_block = cfg_edge->dest; 176 supernode *dest_supernode 177 = *m_bb_to_initial_node.get (dest_cfg_block); 178 cfg_superedge *cfg_sedge 179 = add_cfg_edge (src_supernode, dest_supernode, cfg_edge, idx); 180 m_cfg_edge_to_cfg_superedge.put (cfg_edge, cfg_sedge); 181 } 182 } 183 184 /* Make interprocedural superedges for calls. */ 185 { 186 for (cgraph_edge_to_node_t::iterator iter 187 = m_cgraph_edge_to_caller_prev_node.begin (); 188 iter != m_cgraph_edge_to_caller_prev_node.end (); 189 ++iter) 190 { 191 cgraph_edge *edge = (*iter).first; 192 supernode *caller_prev_supernode = (*iter).second; 193 function* callee_fn = get_ultimate_function_for_cgraph_edge (edge); 194 if (!callee_fn || !callee_fn->cfg) 195 continue; 196 basic_block callee_cfg_block = ENTRY_BLOCK_PTR_FOR_FN (callee_fn); 197 supernode *callee_supernode 198 = *m_bb_to_initial_node.get (callee_cfg_block); 199 call_superedge *sedge 200 = add_call_superedge (caller_prev_supernode, 201 callee_supernode, 202 edge); 203 m_cgraph_edge_to_call_superedge.put (edge, sedge); 204 } 205 } 206 207 /* Make interprocedural superedges for returns. */ 208 { 209 for (cgraph_edge_to_node_t::iterator iter 210 = m_cgraph_edge_to_caller_next_node.begin (); 211 iter != m_cgraph_edge_to_caller_next_node.end (); 212 ++iter) 213 { 214 cgraph_edge *edge = (*iter).first; 215 supernode *caller_next_supernode = (*iter).second; 216 function* callee_fn = get_ultimate_function_for_cgraph_edge (edge); 217 if (!callee_fn || !callee_fn->cfg) 218 continue; 219 basic_block callee_cfg_block = EXIT_BLOCK_PTR_FOR_FN (callee_fn); 220 supernode *callee_supernode 221 = *m_bb_to_initial_node.get (callee_cfg_block); 222 return_superedge *sedge 223 = add_return_superedge (callee_supernode, 224 caller_next_supernode, 225 edge); 226 m_cgraph_edge_to_return_superedge.put (edge, sedge); 227 } 228 } 229 230 /* Make intraprocedural superedges linking the two halves of a call. */ 231 { 232 for (cgraph_edge_to_node_t::iterator iter 233 = m_cgraph_edge_to_caller_prev_node.begin (); 234 iter != m_cgraph_edge_to_caller_prev_node.end (); 235 ++iter) 236 { 237 cgraph_edge *edge = (*iter).first; 238 supernode *caller_prev_supernode = (*iter).second; 239 supernode *caller_next_supernode 240 = *m_cgraph_edge_to_caller_next_node.get (edge); 241 superedge *sedge 242 = new callgraph_superedge (caller_prev_supernode, 243 caller_next_supernode, 244 SUPEREDGE_INTRAPROCEDURAL_CALL, 245 edge); 246 add_edge (sedge); 247 m_cgraph_edge_to_intraproc_superedge.put (edge, sedge); 248 } 249 250 } 251 } 252} 253 254/* Dump this graph in .dot format to PP, using DUMP_ARGS. 255 Cluster the supernodes by function, then by BB from original CFG. */ 256 257void 258supergraph::dump_dot_to_pp (pretty_printer *pp, 259 const dump_args_t &dump_args) const 260{ 261 graphviz_out gv (pp); 262 263 pp_string (pp, "digraph \""); 264 pp_write_text_to_stream (pp); 265 pp_string (pp, "supergraph"); 266 pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/false); 267 pp_string (pp, "\" {\n"); 268 gv.indent (); 269 270 gv.println ("overlap=false;"); 271 gv.println ("compound=true;"); 272 273 /* TODO: maybe (optionally) sub-subdivide by TU, for LTO; see also: 274 https://gcc-python-plugin.readthedocs.io/en/latest/_images/sample-supergraph.png 275 */ 276 277 /* Break out the supernodes into clusters by function. */ 278 { 279 cgraph_node *node; 280 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) 281 { 282 function *fun = node->get_fun (); 283 const char *funcname = function_name (fun); 284 gv.println ("subgraph \"cluster_%s\" {", 285 funcname); 286 gv.indent (); 287 pp_printf (pp, 288 ("style=\"dashed\";" 289 " color=\"black\";" 290 " label=\"%s\";\n"), 291 funcname); 292 293 /* Break out the nodes into clusters by BB from original CFG. */ 294 { 295 basic_block bb; 296 FOR_ALL_BB_FN (bb, fun) 297 { 298 if (dump_args.m_flags & SUPERGRAPH_DOT_SHOW_BBS) 299 { 300 gv.println ("subgraph \"cluster_%s_bb_%i\" {", 301 funcname, bb->index); 302 gv.indent (); 303 pp_printf (pp, 304 ("style=\"dashed\";" 305 " color=\"black\";" 306 " label=\"bb: %i\";\n"), 307 bb->index); 308 } 309 310 // TODO: maybe keep an index per-function/per-bb to speed this up??? 311 int i; 312 supernode *n; 313 FOR_EACH_VEC_ELT (m_nodes, i, n) 314 if (n->m_fun == fun && n->m_bb == bb) 315 n->dump_dot (&gv, dump_args); 316 317 if (dump_args.m_flags & SUPERGRAPH_DOT_SHOW_BBS) 318 { 319 /* Terminate per-bb "subgraph" */ 320 gv.outdent (); 321 gv.println ("}"); 322 } 323 } 324 } 325 326 /* Add an invisible edge from ENTRY to EXIT, to improve the graph layout. */ 327 pp_string (pp, "\t"); 328 get_node_for_function_entry (fun)->dump_dot_id (pp); 329 pp_string (pp, ":s -> "); 330 get_node_for_function_exit (fun)->dump_dot_id (pp); 331 pp_string (pp, ":n [style=\"invis\",constraint=true];\n"); 332 333 /* Terminate per-function "subgraph" */ 334 gv.outdent (); 335 gv.println ("}"); 336 } 337 } 338 339 /* Superedges. */ 340 int i; 341 superedge *e; 342 FOR_EACH_VEC_ELT (m_edges, i, e) 343 e->dump_dot (&gv, dump_args); 344 345 /* Terminate "digraph" */ 346 gv.outdent (); 347 gv.println ("}"); 348} 349 350/* Dump this graph in .dot format to FP, using DUMP_ARGS. */ 351 352void 353supergraph::dump_dot_to_file (FILE *fp, const dump_args_t &dump_args) const 354{ 355 pretty_printer *pp = global_dc->printer->clone (); 356 pp_show_color (pp) = 0; 357 /* %qE in logs for SSA_NAMEs should show the ssa names, rather than 358 trying to prettify things by showing the underlying var. */ 359 pp_format_decoder (pp) = default_tree_printer; 360 361 pp->buffer->stream = fp; 362 dump_dot_to_pp (pp, dump_args); 363 pp_flush (pp); 364 delete pp; 365} 366 367/* Dump this graph in .dot format to PATH, using DUMP_ARGS. */ 368 369void 370supergraph::dump_dot (const char *path, const dump_args_t &dump_args) const 371{ 372 FILE *fp = fopen (path, "w"); 373 dump_dot_to_file (fp, dump_args); 374 fclose (fp); 375} 376 377/* Create a supernode for BB within FUN and add it to this supergraph. 378 379 If RETURNING_CALL is non-NULL, the supernode represents the resumption 380 of the basic block after returning from that call. 381 382 If PHI_NODES is non-NULL, this is the initial supernode for the basic 383 block, and is responsible for any handling of the phi nodes. */ 384 385supernode * 386supergraph::add_node (function *fun, basic_block bb, gcall *returning_call, 387 gimple_seq phi_nodes) 388{ 389 supernode *n = new supernode (fun, bb, returning_call, phi_nodes, 390 m_nodes.length ()); 391 m_nodes.safe_push (n); 392 return n; 393} 394 395/* Create a new cfg_superedge from SRC to DEST for the underlying CFG edge E, 396 adding it to this supergraph. 397 398 If the edge is for a switch statement, create a switch_cfg_superedge 399 subclass using IDX (the index of E within the out-edges from SRC's 400 underlying basic block). */ 401 402cfg_superedge * 403supergraph::add_cfg_edge (supernode *src, supernode *dest, ::edge e, int idx) 404{ 405 /* Special-case switch edges. */ 406 gimple *stmt = src->get_last_stmt (); 407 cfg_superedge *new_edge; 408 if (stmt && stmt->code == GIMPLE_SWITCH) 409 new_edge = new switch_cfg_superedge (src, dest, e, idx); 410 else 411 new_edge = new cfg_superedge (src, dest, e); 412 add_edge (new_edge); 413 return new_edge; 414} 415 416/* Create and add a call_superedge representing an interprocedural call 417 from SRC to DEST, using CEDGE. */ 418 419call_superedge * 420supergraph::add_call_superedge (supernode *src, supernode *dest, 421 cgraph_edge *cedge) 422{ 423 call_superedge *new_edge = new call_superedge (src, dest, cedge); 424 add_edge (new_edge); 425 return new_edge; 426} 427 428/* Create and add a return_superedge representing returning from an 429 interprocedural call, returning from SRC to DEST, using CEDGE. */ 430 431return_superedge * 432supergraph::add_return_superedge (supernode *src, supernode *dest, 433 cgraph_edge *cedge) 434{ 435 return_superedge *new_edge = new return_superedge (src, dest, cedge); 436 add_edge (new_edge); 437 return new_edge; 438} 439 440/* Implementation of dnode::dump_dot vfunc for supernodes. 441 442 Write a cluster for the node, and within it a .dot node showing 443 the phi nodes and stmts. Call into any node annotator from ARGS to 444 potentially add other records to the cluster. */ 445 446void 447supernode::dump_dot (graphviz_out *gv, const dump_args_t &args) const 448{ 449 gv->println ("subgraph cluster_node_%i {", 450 m_index); 451 gv->indent (); 452 453 gv->println("style=\"solid\";"); 454 gv->println("color=\"black\";"); 455 gv->println("fillcolor=\"lightgrey\";"); 456 gv->println("label=\"sn: %i (bb: %i)\";", m_index, m_bb->index); 457 458 pretty_printer *pp = gv->get_pp (); 459 460 if (args.m_node_annotator) 461 args.m_node_annotator->add_node_annotations (gv, *this, false); 462 463 gv->write_indent (); 464 dump_dot_id (pp); 465 pp_printf (pp, 466 " [shape=none,margin=0,style=filled,fillcolor=%s,label=<", 467 "lightgrey"); 468 pp_string (pp, "<TABLE BORDER=\"0\">"); 469 pp_write_text_to_stream (pp); 470 471 bool had_row = false; 472 473 /* Give any annotator the chance to add its own per-node TR elements. */ 474 if (args.m_node_annotator) 475 if (args.m_node_annotator->add_node_annotations (gv, *this, true)) 476 had_row = true; 477 478 if (m_returning_call) 479 { 480 gv->begin_trtd (); 481 pp_string (pp, "returning call: "); 482 gv->end_tdtr (); 483 484 gv->begin_tr (); 485 gv->begin_td (); 486 pp_gimple_stmt_1 (pp, m_returning_call, 0, (dump_flags_t)0); 487 pp_write_text_as_html_like_dot_to_stream (pp); 488 gv->end_td (); 489 /* Give any annotator the chance to add per-stmt TD elements to 490 this row. */ 491 if (args.m_node_annotator) 492 args.m_node_annotator->add_stmt_annotations (gv, m_returning_call, 493 true); 494 gv->end_tr (); 495 496 /* Give any annotator the chance to add per-stmt TR elements. */ 497 if (args.m_node_annotator) 498 args.m_node_annotator->add_stmt_annotations (gv, m_returning_call, 499 false); 500 pp_newline (pp); 501 502 had_row = true; 503 } 504 505 if (entry_p ()) 506 { 507 pp_string (pp, "<TR><TD>ENTRY</TD></TR>"); 508 pp_newline (pp); 509 had_row = true; 510 } 511 512 if (return_p ()) 513 { 514 pp_string (pp, "<TR><TD>EXIT</TD></TR>"); 515 pp_newline (pp); 516 had_row = true; 517 } 518 519 /* Phi nodes. */ 520 for (gphi_iterator gpi = const_cast<supernode *> (this)->start_phis (); 521 !gsi_end_p (gpi); gsi_next (&gpi)) 522 { 523 const gimple *stmt = gsi_stmt (gpi); 524 gv->begin_tr (); 525 gv->begin_td (); 526 pp_gimple_stmt_1 (pp, stmt, 0, (dump_flags_t)0); 527 pp_write_text_as_html_like_dot_to_stream (pp); 528 gv->end_td (); 529 /* Give any annotator the chance to add per-phi TD elements to 530 this row. */ 531 if (args.m_node_annotator) 532 args.m_node_annotator->add_stmt_annotations (gv, stmt, true); 533 gv->end_tr (); 534 535 /* Give any annotator the chance to add per-phi TR elements. */ 536 if (args.m_node_annotator) 537 args.m_node_annotator->add_stmt_annotations (gv, stmt, false); 538 539 pp_newline (pp); 540 had_row = true; 541 } 542 543 /* Statements. */ 544 int i; 545 gimple *stmt; 546 FOR_EACH_VEC_ELT (m_stmts, i, stmt) 547 { 548 gv->begin_tr (); 549 gv->begin_td (); 550 pp_gimple_stmt_1 (pp, stmt, 0, (dump_flags_t)0); 551 pp_write_text_as_html_like_dot_to_stream (pp); 552 gv->end_td (); 553 /* Give any annotator the chance to add per-stmt TD elements to 554 this row. */ 555 if (args.m_node_annotator) 556 args.m_node_annotator->add_stmt_annotations (gv, stmt, true); 557 gv->end_tr (); 558 559 /* Give any annotator the chance to add per-stmt TR elements. */ 560 if (args.m_node_annotator) 561 args.m_node_annotator->add_stmt_annotations (gv, stmt, false); 562 563 pp_newline (pp); 564 had_row = true; 565 } 566 567 /* Give any annotator the chance to add additional per-node TR elements 568 to the end of the TABLE. */ 569 if (args.m_node_annotator) 570 if (args.m_node_annotator->add_after_node_annotations (gv, *this)) 571 had_row = true; 572 573 /* Graphviz requires a TABLE element to have at least one TR 574 (and each TR to have at least one TD). */ 575 if (!had_row) 576 { 577 pp_string (pp, "<TR><TD>(empty)</TD></TR>"); 578 pp_newline (pp); 579 } 580 581 pp_string (pp, "</TABLE>>];\n\n"); 582 pp_flush (pp); 583 584 /* Terminate "subgraph" */ 585 gv->outdent (); 586 gv->println ("}"); 587} 588 589/* Write an ID for this node to PP, for use in .dot output. */ 590 591void 592supernode::dump_dot_id (pretty_printer *pp) const 593{ 594 pp_printf (pp, "node_%i", m_index); 595} 596 597/* Get a location_t for the start of this supernode. */ 598 599location_t 600supernode::get_start_location () const 601{ 602 if (m_returning_call 603 && get_pure_location (m_returning_call->location) != UNKNOWN_LOCATION) 604 return m_returning_call->location; 605 606 int i; 607 gimple *stmt; 608 FOR_EACH_VEC_ELT (m_stmts, i, stmt) 609 if (get_pure_location (stmt->location) != UNKNOWN_LOCATION) 610 return stmt->location; 611 612 if (entry_p ()) 613 { 614 // TWEAK: show the decl instead; this leads to more readable output: 615 return DECL_SOURCE_LOCATION (m_fun->decl); 616 617 return m_fun->function_start_locus; 618 } 619 if (return_p ()) 620 return m_fun->function_end_locus; 621 622 return UNKNOWN_LOCATION; 623} 624 625/* Get a location_t for the end of this supernode. */ 626 627location_t 628supernode::get_end_location () const 629{ 630 int i; 631 gimple *stmt; 632 FOR_EACH_VEC_ELT_REVERSE (m_stmts, i, stmt) 633 if (get_pure_location (stmt->location) != UNKNOWN_LOCATION) 634 return stmt->location; 635 636 if (m_returning_call 637 && get_pure_location (m_returning_call->location) != UNKNOWN_LOCATION) 638 return m_returning_call->location; 639 640 if (entry_p ()) 641 return m_fun->function_start_locus; 642 if (return_p ()) 643 return m_fun->function_end_locus; 644 645 return UNKNOWN_LOCATION; 646} 647 648/* Given STMT within this supernode, return its index within m_stmts. */ 649 650unsigned int 651supernode::get_stmt_index (const gimple *stmt) const 652{ 653 unsigned i; 654 gimple *iter_stmt; 655 FOR_EACH_VEC_ELT (m_stmts, i, iter_stmt) 656 if (iter_stmt == stmt) 657 return i; 658 gcc_unreachable (); 659} 660 661/* Dump this superedge to PP. */ 662 663void 664superedge::dump (pretty_printer *pp) const 665{ 666 pp_printf (pp, "edge: SN: %i -> SN: %i", m_src->m_index, m_dest->m_index); 667 char *desc = get_description (false); 668 if (strlen (desc) > 0) 669 { 670 pp_space (pp); 671 pp_string (pp, desc); 672 } 673 free (desc); 674} 675 676/* Dump this superedge to stderr. */ 677 678DEBUG_FUNCTION void 679superedge::dump () const 680{ 681 pretty_printer pp; 682 pp_format_decoder (&pp) = default_tree_printer; 683 pp_show_color (&pp) = pp_show_color (global_dc->printer); 684 pp.buffer->stream = stderr; 685 dump (&pp); 686 pp_newline (&pp); 687 pp_flush (&pp); 688} 689 690/* Implementation of dedge::dump_dot for superedges. 691 Write a .dot edge to GV representing this superedge. */ 692 693void 694superedge::dump_dot (graphviz_out *gv, const dump_args_t &) const 695{ 696 const char *style = "\"solid,bold\""; 697 const char *color = "black"; 698 int weight = 10; 699 const char *constraint = "true"; 700 701 switch (m_kind) 702 { 703 default: 704 gcc_unreachable (); 705 case SUPEREDGE_CFG_EDGE: 706 break; 707 case SUPEREDGE_CALL: 708 color = "red"; 709 break; 710 case SUPEREDGE_RETURN: 711 color = "green"; 712 break; 713 case SUPEREDGE_INTRAPROCEDURAL_CALL: 714 style = "\"dotted\""; 715 break; 716 } 717 718 /* Adapted from graph.c:draw_cfg_node_succ_edges. */ 719 if (::edge cfg_edge = get_any_cfg_edge ()) 720 { 721 if (cfg_edge->flags & EDGE_FAKE) 722 { 723 style = "dotted"; 724 color = "green"; 725 weight = 0; 726 } 727 else if (cfg_edge->flags & EDGE_DFS_BACK) 728 { 729 style = "\"dotted,bold\""; 730 color = "blue"; 731 weight = 10; 732 } 733 else if (cfg_edge->flags & EDGE_FALLTHRU) 734 { 735 color = "blue"; 736 weight = 100; 737 } 738 739 if (cfg_edge->flags & EDGE_ABNORMAL) 740 color = "red"; 741 } 742 743 gv->write_indent (); 744 745 pretty_printer *pp = gv->get_pp (); 746 747 m_src->dump_dot_id (pp); 748 pp_string (pp, " -> "); 749 m_dest->dump_dot_id (pp); 750 pp_printf (pp, 751 (" [style=%s, color=%s, weight=%d, constraint=%s," 752 " ltail=\"cluster_node_%i\", lhead=\"cluster_node_%i\"" 753 " headlabel=\""), 754 style, color, weight, constraint, 755 m_src->m_index, m_dest->m_index); 756 757 dump_label_to_pp (pp, false); 758 759 pp_printf (pp, "\"];\n"); 760} 761 762/* If this is an intraprocedural superedge, return the associated 763 CFG edge. Otherwise, return NULL. */ 764 765::edge 766superedge::get_any_cfg_edge () const 767{ 768 if (const cfg_superedge *sub = dyn_cast_cfg_superedge ()) 769 return sub->get_cfg_edge (); 770 return NULL; 771} 772 773/* If this is an interprocedural superedge, return the associated 774 cgraph_edge *. Otherwise, return NULL. */ 775 776cgraph_edge * 777superedge::get_any_callgraph_edge () const 778{ 779 if (const callgraph_superedge *sub = dyn_cast_callgraph_superedge ()) 780 return sub->m_cedge; 781 return NULL; 782} 783 784/* Build a description of this superedge (e.g. "true" for the true 785 edge of a conditional, or "case 42:" for a switch case). 786 787 The caller is responsible for freeing the result. 788 789 If USER_FACING is false, the result also contains any underlying 790 CFG edge flags. e.g. " (flags FALLTHRU | DFS_BACK)". */ 791 792char * 793superedge::get_description (bool user_facing) const 794{ 795 pretty_printer pp; 796 dump_label_to_pp (&pp, user_facing); 797 return xstrdup (pp_formatted_text (&pp)); 798} 799 800/* Implementation of superedge::dump_label_to_pp for non-switch CFG 801 superedges. 802 803 For true/false edges, print "true" or "false" to PP. 804 805 If USER_FACING is false, also print flags on the underlying CFG edge to 806 PP. */ 807 808void 809cfg_superedge::dump_label_to_pp (pretty_printer *pp, 810 bool user_facing) const 811{ 812 if (true_value_p ()) 813 pp_printf (pp, "true"); 814 else if (false_value_p ()) 815 pp_printf (pp, "false"); 816 817 if (user_facing) 818 return; 819 820 /* Express edge flags as a string with " | " separator. 821 e.g. " (flags FALLTHRU | DFS_BACK)". */ 822 if (get_flags ()) 823 { 824 pp_string (pp, " (flags "); 825 bool seen_flag = false; 826#define DEF_EDGE_FLAG(NAME,IDX) \ 827 do { \ 828 if (get_flags () & EDGE_##NAME) \ 829 { \ 830 if (seen_flag) \ 831 pp_string (pp, " | "); \ 832 pp_printf (pp, "%s", (#NAME)); \ 833 seen_flag = true; \ 834 } \ 835 } while (0); 836#include "cfg-flags.def" 837#undef DEF_EDGE_FLAG 838 pp_string (pp, ")"); 839 } 840 841 /* Otherwise, no label. */ 842} 843 844/* Get the phi argument for PHI for this CFG edge. */ 845 846tree 847cfg_superedge::get_phi_arg (const gphi *phi) const 848{ 849 size_t index = m_cfg_edge->dest_idx; 850 return gimple_phi_arg_def (phi, index); 851} 852 853/* Implementation of superedge::dump_label_to_pp for CFG superedges for 854 "switch" statements. 855 856 Print "case VAL:", "case LOWER ... UPPER:", or "default:" to PP. */ 857 858void 859switch_cfg_superedge::dump_label_to_pp (pretty_printer *pp, 860 bool user_facing ATTRIBUTE_UNUSED) const 861{ 862 tree case_label = get_case_label (); 863 gcc_assert (TREE_CODE (case_label) == CASE_LABEL_EXPR); 864 tree lower_bound = CASE_LOW (case_label); 865 tree upper_bound = CASE_HIGH (case_label); 866 if (lower_bound) 867 { 868 pp_printf (pp, "case "); 869 dump_generic_node (pp, lower_bound, 0, (dump_flags_t)0, false); 870 if (upper_bound) 871 { 872 pp_printf (pp, " ... "); 873 dump_generic_node (pp, upper_bound, 0, (dump_flags_t)0, false); 874 } 875 pp_printf (pp, ":"); 876 } 877 else 878 pp_printf (pp, "default:"); 879} 880 881/* Get the case label for this "switch" superedge. */ 882 883tree 884switch_cfg_superedge::get_case_label () const 885{ 886 return gimple_switch_label (get_switch_stmt (), m_idx); 887} 888 889/* Implementation of superedge::dump_label_to_pp for interprocedural 890 superedges. */ 891 892void 893callgraph_superedge::dump_label_to_pp (pretty_printer *pp, 894 bool user_facing ATTRIBUTE_UNUSED) const 895{ 896 switch (m_kind) 897 { 898 default: 899 case SUPEREDGE_CFG_EDGE: 900 gcc_unreachable (); 901 902 case SUPEREDGE_CALL: 903 pp_printf (pp, "call"); 904 break; 905 906 case SUPEREDGE_RETURN: 907 pp_printf (pp, "return"); 908 break; 909 910 case SUPEREDGE_INTRAPROCEDURAL_CALL: 911 pp_printf (pp, "intraproc link"); 912 break; 913 } 914} 915 916/* Get the function that was called at this interprocedural call/return 917 edge. */ 918 919function * 920callgraph_superedge::get_callee_function () const 921{ 922 return get_ultimate_function_for_cgraph_edge (m_cedge); 923} 924 925/* Get the calling function at this interprocedural call/return edge. */ 926 927function * 928callgraph_superedge::get_caller_function () const 929{ 930 return m_cedge->caller->get_fun (); 931} 932 933/* Get the fndecl that was called at this interprocedural call/return 934 edge. */ 935 936tree 937callgraph_superedge::get_callee_decl () const 938{ 939 return get_callee_function ()->decl; 940} 941 942/* Get the calling fndecl at this interprocedural call/return edge. */ 943 944tree 945callgraph_superedge::get_caller_decl () const 946{ 947 return get_caller_function ()->decl; 948} 949 950/* Given PARM_TO_FIND, a PARM_DECL, identify its index (writing it 951 to *OUT if OUT is non-NULL), and return the corresponding argument 952 at the callsite. */ 953 954tree 955callgraph_superedge::get_arg_for_parm (tree parm_to_find, 956 callsite_expr *out) const 957{ 958 gcc_assert (TREE_CODE (parm_to_find) == PARM_DECL); 959 960 tree callee = get_callee_decl (); 961 const gcall *call_stmt = get_call_stmt (); 962 963 unsigned i = 0; 964 for (tree iter_parm = DECL_ARGUMENTS (callee); iter_parm; 965 iter_parm = DECL_CHAIN (iter_parm), ++i) 966 { 967 if (i >= gimple_call_num_args (call_stmt)) 968 return NULL_TREE; 969 if (iter_parm == parm_to_find) 970 { 971 if (out) 972 *out = callsite_expr::from_zero_based_param (i); 973 return gimple_call_arg (call_stmt, i); 974 } 975 } 976 977 /* Not found. */ 978 return NULL_TREE; 979} 980 981/* Look for a use of ARG_TO_FIND as an argument at this callsite. 982 If found, return the default SSA def of the corresponding parm within 983 the callee, and if OUT is non-NULL, write the index to *OUT. 984 Only the first match is handled. */ 985 986tree 987callgraph_superedge::get_parm_for_arg (tree arg_to_find, 988 callsite_expr *out) const 989{ 990 tree callee = get_callee_decl (); 991 const gcall *call_stmt = get_call_stmt (); 992 993 unsigned i = 0; 994 for (tree iter_parm = DECL_ARGUMENTS (callee); iter_parm; 995 iter_parm = DECL_CHAIN (iter_parm), ++i) 996 { 997 if (i >= gimple_call_num_args (call_stmt)) 998 return NULL_TREE; 999 tree param = gimple_call_arg (call_stmt, i); 1000 if (arg_to_find == param) 1001 { 1002 if (out) 1003 *out = callsite_expr::from_zero_based_param (i); 1004 return ssa_default_def (get_callee_function (), iter_parm); 1005 } 1006 } 1007 1008 /* Not found. */ 1009 return NULL_TREE; 1010} 1011 1012/* Map caller_expr back to an expr within the callee, or return NULL_TREE. 1013 If non-NULL is returned, populate OUT. */ 1014 1015tree 1016callgraph_superedge::map_expr_from_caller_to_callee (tree caller_expr, 1017 callsite_expr *out) const 1018{ 1019 /* Is it an argument (actual param)? If so, convert to 1020 parameter (formal param). */ 1021 tree parm = get_parm_for_arg (caller_expr, out); 1022 if (parm) 1023 return parm; 1024 /* Otherwise try return value. */ 1025 if (caller_expr == gimple_call_lhs (get_call_stmt ())) 1026 { 1027 if (out) 1028 *out = callsite_expr::from_return_value (); 1029 return DECL_RESULT (get_callee_decl ()); 1030 } 1031 1032 return NULL_TREE; 1033} 1034 1035/* Map callee_expr back to an expr within the caller, or return NULL_TREE. 1036 If non-NULL is returned, populate OUT. */ 1037 1038tree 1039callgraph_superedge::map_expr_from_callee_to_caller (tree callee_expr, 1040 callsite_expr *out) const 1041{ 1042 if (callee_expr == NULL_TREE) 1043 return NULL_TREE; 1044 1045 /* If it's a parameter (formal param), get the argument (actual param). */ 1046 if (TREE_CODE (callee_expr) == PARM_DECL) 1047 return get_arg_for_parm (callee_expr, out); 1048 1049 /* Similar for the default SSA name of the PARM_DECL. */ 1050 if (TREE_CODE (callee_expr) == SSA_NAME 1051 && SSA_NAME_IS_DEFAULT_DEF (callee_expr) 1052 && TREE_CODE (SSA_NAME_VAR (callee_expr)) == PARM_DECL) 1053 return get_arg_for_parm (SSA_NAME_VAR (callee_expr), out); 1054 1055 /* Otherwise try return value. */ 1056 if (callee_expr == DECL_RESULT (get_callee_decl ())) 1057 { 1058 if (out) 1059 *out = callsite_expr::from_return_value (); 1060 return gimple_call_lhs (get_call_stmt ()); 1061 } 1062 1063 return NULL_TREE; 1064} 1065 1066} // namespace ana 1067 1068#endif /* #if ENABLE_ANALYZER */ 1069