1 /* Print RTL for GCC. 2 Copyright (C) 1987, 1988, 1992, 1997, 1998, 1999, 2000, 2002, 2003, 3 2004, 2005, 2007, 2008, 2009, 2010 4 Free Software Foundation, Inc. 5 6 This file is part of GCC. 7 8 GCC is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free 10 Software Foundation; either version 3, or (at your option) any later 11 version. 12 13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14 WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with GCC; see the file COPYING3. If not see 20 <http://www.gnu.org/licenses/>. */ 21 22 /* This file is compiled twice: once for the generator programs, 23 once for the compiler. */ 24 #ifdef GENERATOR_FILE 25 #include "bconfig.h" 26 #else 27 #include "config.h" 28 #endif 29 30 #include "system.h" 31 #include "coretypes.h" 32 #include "tm.h" 33 #include "rtl.h" 34 35 /* These headers all define things which are not available in 36 generator programs. */ 37 #ifndef GENERATOR_FILE 38 #include "tree.h" 39 #include "real.h" 40 #include "flags.h" 41 #include "hard-reg-set.h" 42 #include "basic-block.h" 43 #include "diagnostic.h" 44 #include "cselib.h" 45 #include "tree-pass.h" 46 #endif 47 48 static FILE *outfile; 49 50 static int sawclose = 0; 51 52 static int indent; 53 54 static void print_rtx (const_rtx); 55 56 /* String printed at beginning of each RTL when it is dumped. 57 This string is set to ASM_COMMENT_START when the RTL is dumped in 58 the assembly output file. */ 59 const char *print_rtx_head = ""; 60 61 /* Nonzero means suppress output of instruction numbers 62 in debugging dumps. 63 This must be defined here so that programs like gencodes can be linked. */ 64 int flag_dump_unnumbered = 0; 65 66 /* Nonzero means suppress output of instruction numbers for previous 67 and next insns in debugging dumps. 68 This must be defined here so that programs like gencodes can be linked. */ 69 int flag_dump_unnumbered_links = 0; 70 71 /* Nonzero means use simplified format without flags, modes, etc. */ 72 int flag_simple = 0; 73 74 /* Nonzero if we are dumping graphical description. */ 75 int dump_for_graph; 76 77 #ifndef GENERATOR_FILE 78 void 79 print_mem_expr (FILE *outfile, const_tree expr) 80 { 81 fputc (' ', outfile); 82 print_generic_expr (outfile, CONST_CAST_TREE (expr), dump_flags); 83 } 84 #endif 85 86 /* Print IN_RTX onto OUTFILE. This is the recursive part of printing. */ 87 88 static void 89 print_rtx (const_rtx in_rtx) 90 { 91 int i = 0; 92 int j; 93 const char *format_ptr; 94 int is_insn; 95 96 if (sawclose) 97 { 98 if (flag_simple) 99 fputc (' ', outfile); 100 else 101 fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, ""); 102 sawclose = 0; 103 } 104 105 if (in_rtx == 0) 106 { 107 fputs ("(nil)", outfile); 108 sawclose = 1; 109 return; 110 } 111 else if (GET_CODE (in_rtx) > NUM_RTX_CODE) 112 { 113 fprintf (outfile, "(??? bad code %d\n%s%*s)", GET_CODE (in_rtx), 114 print_rtx_head, indent * 2, ""); 115 sawclose = 1; 116 return; 117 } 118 119 is_insn = INSN_P (in_rtx); 120 121 /* When printing in VCG format we write INSNs, NOTE, LABEL, and BARRIER 122 in separate nodes and therefore have to handle them special here. */ 123 if (dump_for_graph 124 && (is_insn || NOTE_P (in_rtx) 125 || LABEL_P (in_rtx) || BARRIER_P (in_rtx))) 126 { 127 i = 3; 128 indent = 0; 129 } 130 else 131 { 132 /* Print name of expression code. */ 133 if (flag_simple && CONST_INT_P (in_rtx)) 134 fputc ('(', outfile); 135 else 136 fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx))); 137 138 if (! flag_simple) 139 { 140 if (RTX_FLAG (in_rtx, in_struct)) 141 fputs ("/s", outfile); 142 143 if (RTX_FLAG (in_rtx, volatil)) 144 fputs ("/v", outfile); 145 146 if (RTX_FLAG (in_rtx, unchanging)) 147 fputs ("/u", outfile); 148 149 if (RTX_FLAG (in_rtx, frame_related)) 150 fputs ("/f", outfile); 151 152 if (RTX_FLAG (in_rtx, jump)) 153 fputs ("/j", outfile); 154 155 if (RTX_FLAG (in_rtx, call)) 156 fputs ("/c", outfile); 157 158 if (RTX_FLAG (in_rtx, return_val)) 159 fputs ("/i", outfile); 160 161 /* Print REG_NOTE names for EXPR_LIST and INSN_LIST. */ 162 if ((GET_CODE (in_rtx) == EXPR_LIST 163 || GET_CODE (in_rtx) == INSN_LIST) 164 && (int)GET_MODE (in_rtx) < REG_NOTE_MAX) 165 fprintf (outfile, ":%s", 166 GET_REG_NOTE_NAME (GET_MODE (in_rtx))); 167 168 /* For other rtl, print the mode if it's not VOID. */ 169 else if (GET_MODE (in_rtx) != VOIDmode) 170 fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx))); 171 172 #ifndef GENERATOR_FILE 173 if (GET_CODE (in_rtx) == VAR_LOCATION) 174 { 175 if (TREE_CODE (PAT_VAR_LOCATION_DECL (in_rtx)) == STRING_CST) 176 fputs (" <debug string placeholder>", outfile); 177 else 178 print_mem_expr (outfile, PAT_VAR_LOCATION_DECL (in_rtx)); 179 fputc (' ', outfile); 180 print_rtx (PAT_VAR_LOCATION_LOC (in_rtx)); 181 if (PAT_VAR_LOCATION_STATUS (in_rtx) 182 == VAR_INIT_STATUS_UNINITIALIZED) 183 fprintf (outfile, " [uninit]"); 184 sawclose = 1; 185 i = GET_RTX_LENGTH (VAR_LOCATION); 186 } 187 #endif 188 } 189 } 190 191 #ifndef GENERATOR_FILE 192 if (GET_CODE (in_rtx) == CONST_DOUBLE && FLOAT_MODE_P (GET_MODE (in_rtx))) 193 i = 5; 194 #endif 195 196 /* Get the format string and skip the first elements if we have handled 197 them already. */ 198 format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)) + i; 199 for (; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++) 200 switch (*format_ptr++) 201 { 202 const char *str; 203 204 case 'T': 205 str = XTMPL (in_rtx, i); 206 goto string; 207 208 case 'S': 209 case 's': 210 str = XSTR (in_rtx, i); 211 string: 212 213 if (str == 0) 214 fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile); 215 else 216 { 217 if (dump_for_graph) 218 fprintf (outfile, " (\\\"%s\\\")", str); 219 else 220 fprintf (outfile, " (\"%s\")", str); 221 } 222 sawclose = 1; 223 break; 224 225 /* 0 indicates a field for internal use that should not be printed. 226 An exception is the third field of a NOTE, where it indicates 227 that the field has several different valid contents. */ 228 case '0': 229 if (i == 1 && REG_P (in_rtx)) 230 { 231 if (REGNO (in_rtx) != ORIGINAL_REGNO (in_rtx)) 232 fprintf (outfile, " [%d]", ORIGINAL_REGNO (in_rtx)); 233 } 234 #ifndef GENERATOR_FILE 235 else if (i == 1 && GET_CODE (in_rtx) == SYMBOL_REF) 236 { 237 int flags = SYMBOL_REF_FLAGS (in_rtx); 238 if (flags) 239 fprintf (outfile, " [flags 0x%x]", flags); 240 } 241 else if (i == 2 && GET_CODE (in_rtx) == SYMBOL_REF) 242 { 243 tree decl = SYMBOL_REF_DECL (in_rtx); 244 if (decl) 245 print_node_brief (outfile, "", decl, dump_flags); 246 } 247 #endif 248 else if (i == 4 && NOTE_P (in_rtx)) 249 { 250 switch (NOTE_KIND (in_rtx)) 251 { 252 case NOTE_INSN_EH_REGION_BEG: 253 case NOTE_INSN_EH_REGION_END: 254 if (flag_dump_unnumbered) 255 fprintf (outfile, " #"); 256 else 257 fprintf (outfile, " %d", NOTE_EH_HANDLER (in_rtx)); 258 sawclose = 1; 259 break; 260 261 case NOTE_INSN_BLOCK_BEG: 262 case NOTE_INSN_BLOCK_END: 263 #ifndef GENERATOR_FILE 264 dump_addr (outfile, " ", NOTE_BLOCK (in_rtx)); 265 #endif 266 sawclose = 1; 267 break; 268 269 case NOTE_INSN_BASIC_BLOCK: 270 { 271 #ifndef GENERATOR_FILE 272 basic_block bb = NOTE_BASIC_BLOCK (in_rtx); 273 if (bb != 0) 274 fprintf (outfile, " [bb %d]", bb->index); 275 #endif 276 break; 277 } 278 279 case NOTE_INSN_DELETED_LABEL: 280 { 281 const char *label = NOTE_DELETED_LABEL_NAME (in_rtx); 282 if (label) 283 fprintf (outfile, " (\"%s\")", label); 284 else 285 fprintf (outfile, " \"\""); 286 } 287 break; 288 289 case NOTE_INSN_SWITCH_TEXT_SECTIONS: 290 { 291 #ifndef GENERATOR_FILE 292 basic_block bb = NOTE_BASIC_BLOCK (in_rtx); 293 if (bb != 0) 294 fprintf (outfile, " [bb %d]", bb->index); 295 #endif 296 break; 297 } 298 299 case NOTE_INSN_VAR_LOCATION: 300 #ifndef GENERATOR_FILE 301 fputc (' ', outfile); 302 print_rtx (NOTE_VAR_LOCATION (in_rtx)); 303 #endif 304 break; 305 306 default: 307 break; 308 } 309 } 310 else if (i == 8 && JUMP_P (in_rtx) && JUMP_LABEL (in_rtx) != NULL) 311 /* Output the JUMP_LABEL reference. */ 312 fprintf (outfile, "\n%s%*s -> %d", print_rtx_head, indent * 2, "", 313 INSN_UID (JUMP_LABEL (in_rtx))); 314 else if (i == 0 && GET_CODE (in_rtx) == VALUE) 315 { 316 #ifndef GENERATOR_FILE 317 cselib_val *val = CSELIB_VAL_PTR (in_rtx); 318 319 fprintf (outfile, " %u:%u", val->uid, val->hash); 320 dump_addr (outfile, " @", in_rtx); 321 dump_addr (outfile, "/", (void*)val); 322 #endif 323 } 324 else if (i == 0 && GET_CODE (in_rtx) == DEBUG_EXPR) 325 { 326 #ifndef GENERATOR_FILE 327 fprintf (outfile, " D#%i", 328 DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (in_rtx))); 329 #endif 330 } 331 break; 332 333 case 'e': 334 do_e: 335 indent += 2; 336 if (!sawclose) 337 fprintf (outfile, " "); 338 print_rtx (XEXP (in_rtx, i)); 339 indent -= 2; 340 break; 341 342 case 'E': 343 case 'V': 344 indent += 2; 345 if (sawclose) 346 { 347 fprintf (outfile, "\n%s%*s", 348 print_rtx_head, indent * 2, ""); 349 sawclose = 0; 350 } 351 fputs (" [", outfile); 352 if (NULL != XVEC (in_rtx, i)) 353 { 354 indent += 2; 355 if (XVECLEN (in_rtx, i)) 356 sawclose = 1; 357 358 for (j = 0; j < XVECLEN (in_rtx, i); j++) 359 print_rtx (XVECEXP (in_rtx, i, j)); 360 361 indent -= 2; 362 } 363 if (sawclose) 364 fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, ""); 365 366 fputs ("]", outfile); 367 sawclose = 1; 368 indent -= 2; 369 break; 370 371 case 'w': 372 if (! flag_simple) 373 fprintf (outfile, " "); 374 fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, XWINT (in_rtx, i)); 375 if (! flag_simple) 376 fprintf (outfile, " [" HOST_WIDE_INT_PRINT_HEX "]", 377 (unsigned HOST_WIDE_INT) XWINT (in_rtx, i)); 378 break; 379 380 case 'i': 381 if (i == 4 && INSN_P (in_rtx)) 382 { 383 #ifndef GENERATOR_FILE 384 /* Pretty-print insn locators. Ignore scoping as it is mostly 385 redundant with line number information and do not print anything 386 when there is no location information available. */ 387 if (INSN_LOCATOR (in_rtx) && insn_file (in_rtx)) 388 fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx)); 389 #endif 390 } 391 else if (i == 6 && GET_CODE (in_rtx) == ASM_OPERANDS) 392 { 393 #ifndef GENERATOR_FILE 394 fprintf (outfile, " %s:%i", 395 locator_file (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)), 396 locator_line (ASM_OPERANDS_SOURCE_LOCATION (in_rtx))); 397 #endif 398 } 399 else if (i == 1 && GET_CODE (in_rtx) == ASM_INPUT) 400 { 401 #ifndef GENERATOR_FILE 402 fprintf (outfile, " %s:%i", 403 locator_file (ASM_INPUT_SOURCE_LOCATION (in_rtx)), 404 locator_line (ASM_INPUT_SOURCE_LOCATION (in_rtx))); 405 #endif 406 } 407 else if (i == 6 && NOTE_P (in_rtx)) 408 { 409 /* This field is only used for NOTE_INSN_DELETED_LABEL, and 410 other times often contains garbage from INSN->NOTE death. */ 411 if (NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_LABEL) 412 fprintf (outfile, " %d", XINT (in_rtx, i)); 413 } 414 else 415 { 416 int value = XINT (in_rtx, i); 417 const char *name; 418 419 #ifndef GENERATOR_FILE 420 if (REG_P (in_rtx) && value < FIRST_PSEUDO_REGISTER) 421 fprintf (outfile, " %d %s", REGNO (in_rtx), 422 reg_names[REGNO (in_rtx)]); 423 else if (REG_P (in_rtx) 424 && value <= LAST_VIRTUAL_REGISTER) 425 { 426 if (value == VIRTUAL_INCOMING_ARGS_REGNUM) 427 fprintf (outfile, " %d virtual-incoming-args", value); 428 else if (value == VIRTUAL_STACK_VARS_REGNUM) 429 fprintf (outfile, " %d virtual-stack-vars", value); 430 else if (value == VIRTUAL_STACK_DYNAMIC_REGNUM) 431 fprintf (outfile, " %d virtual-stack-dynamic", value); 432 else if (value == VIRTUAL_OUTGOING_ARGS_REGNUM) 433 fprintf (outfile, " %d virtual-outgoing-args", value); 434 else if (value == VIRTUAL_CFA_REGNUM) 435 fprintf (outfile, " %d virtual-cfa", value); 436 else 437 fprintf (outfile, " %d virtual-reg-%d", value, 438 value-FIRST_VIRTUAL_REGISTER); 439 } 440 else 441 #endif 442 if (flag_dump_unnumbered 443 && (is_insn || NOTE_P (in_rtx))) 444 fputc ('#', outfile); 445 else 446 fprintf (outfile, " %d", value); 447 448 #ifndef GENERATOR_FILE 449 if (REG_P (in_rtx) && REG_ATTRS (in_rtx)) 450 { 451 fputs (" [", outfile); 452 if (ORIGINAL_REGNO (in_rtx) != REGNO (in_rtx)) 453 fprintf (outfile, "orig:%i", ORIGINAL_REGNO (in_rtx)); 454 if (REG_EXPR (in_rtx)) 455 print_mem_expr (outfile, REG_EXPR (in_rtx)); 456 457 if (REG_OFFSET (in_rtx)) 458 fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, 459 REG_OFFSET (in_rtx)); 460 fputs (" ]", outfile); 461 } 462 #endif 463 464 if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, i) 465 && XINT (in_rtx, i) >= 0 466 && (name = get_insn_name (XINT (in_rtx, i))) != NULL) 467 fprintf (outfile, " {%s}", name); 468 sawclose = 0; 469 } 470 break; 471 472 /* Print NOTE_INSN names rather than integer codes. */ 473 474 case 'n': 475 fprintf (outfile, " %s", GET_NOTE_INSN_NAME (XINT (in_rtx, i))); 476 sawclose = 0; 477 break; 478 479 case 'u': 480 if (XEXP (in_rtx, i) != NULL) 481 { 482 rtx sub = XEXP (in_rtx, i); 483 enum rtx_code subc = GET_CODE (sub); 484 485 if (GET_CODE (in_rtx) == LABEL_REF) 486 { 487 if (subc == NOTE 488 && NOTE_KIND (sub) == NOTE_INSN_DELETED_LABEL) 489 { 490 if (flag_dump_unnumbered) 491 fprintf (outfile, " [# deleted]"); 492 else 493 fprintf (outfile, " [%d deleted]", INSN_UID (sub)); 494 sawclose = 0; 495 break; 496 } 497 498 if (subc != CODE_LABEL) 499 goto do_e; 500 } 501 502 if (flag_dump_unnumbered 503 || (flag_dump_unnumbered_links && (i == 1 || i == 2) 504 && (INSN_P (in_rtx) || NOTE_P (in_rtx) 505 || LABEL_P (in_rtx) || BARRIER_P (in_rtx)))) 506 fputs (" #", outfile); 507 else 508 fprintf (outfile, " %d", INSN_UID (sub)); 509 } 510 else 511 fputs (" 0", outfile); 512 sawclose = 0; 513 break; 514 515 case 'b': 516 #ifndef GENERATOR_FILE 517 if (XBITMAP (in_rtx, i) == NULL) 518 fputs (" {null}", outfile); 519 else 520 bitmap_print (outfile, XBITMAP (in_rtx, i), " {", "}"); 521 #endif 522 sawclose = 0; 523 break; 524 525 case 't': 526 #ifndef GENERATOR_FILE 527 dump_addr (outfile, " ", XTREE (in_rtx, i)); 528 #endif 529 break; 530 531 case '*': 532 fputs (" Unknown", outfile); 533 sawclose = 0; 534 break; 535 536 case 'B': 537 #ifndef GENERATOR_FILE 538 if (XBBDEF (in_rtx, i)) 539 fprintf (outfile, " %i", XBBDEF (in_rtx, i)->index); 540 #endif 541 break; 542 543 default: 544 gcc_unreachable (); 545 } 546 547 switch (GET_CODE (in_rtx)) 548 { 549 #ifndef GENERATOR_FILE 550 case MEM: 551 if (__builtin_expect (final_insns_dump_p, false)) 552 fprintf (outfile, " ["); 553 else 554 fprintf (outfile, " [" HOST_WIDE_INT_PRINT_DEC, 555 (HOST_WIDE_INT) MEM_ALIAS_SET (in_rtx)); 556 557 if (MEM_EXPR (in_rtx)) 558 print_mem_expr (outfile, MEM_EXPR (in_rtx)); 559 560 if (MEM_OFFSET (in_rtx)) 561 fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, 562 INTVAL (MEM_OFFSET (in_rtx))); 563 564 if (MEM_SIZE (in_rtx)) 565 fprintf (outfile, " S" HOST_WIDE_INT_PRINT_DEC, 566 INTVAL (MEM_SIZE (in_rtx))); 567 568 if (MEM_ALIGN (in_rtx) != 1) 569 fprintf (outfile, " A%u", MEM_ALIGN (in_rtx)); 570 571 if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (in_rtx))) 572 fprintf (outfile, " AS%u", MEM_ADDR_SPACE (in_rtx)); 573 574 fputc (']', outfile); 575 break; 576 577 case CONST_DOUBLE: 578 if (FLOAT_MODE_P (GET_MODE (in_rtx))) 579 { 580 char s[60]; 581 582 real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx), 583 sizeof (s), 0, 1); 584 fprintf (outfile, " %s", s); 585 586 real_to_hexadecimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx), 587 sizeof (s), 0, 1); 588 fprintf (outfile, " [%s]", s); 589 } 590 break; 591 #endif 592 593 case CODE_LABEL: 594 fprintf (outfile, " [%d uses]", LABEL_NUSES (in_rtx)); 595 switch (LABEL_KIND (in_rtx)) 596 { 597 case LABEL_NORMAL: break; 598 case LABEL_STATIC_ENTRY: fputs (" [entry]", outfile); break; 599 case LABEL_GLOBAL_ENTRY: fputs (" [global entry]", outfile); break; 600 case LABEL_WEAK_ENTRY: fputs (" [weak entry]", outfile); break; 601 default: gcc_unreachable (); 602 } 603 break; 604 605 default: 606 break; 607 } 608 609 if (dump_for_graph 610 && (is_insn || NOTE_P (in_rtx) 611 || LABEL_P (in_rtx) || BARRIER_P (in_rtx))) 612 sawclose = 0; 613 else 614 { 615 fputc (')', outfile); 616 sawclose = 1; 617 } 618 } 619 620 /* Print an rtx on the current line of FILE. Initially indent IND 621 characters. */ 622 623 void 624 print_inline_rtx (FILE *outf, const_rtx x, int ind) 625 { 626 int oldsaw = sawclose; 627 int oldindent = indent; 628 629 sawclose = 0; 630 indent = ind; 631 outfile = outf; 632 print_rtx (x); 633 sawclose = oldsaw; 634 indent = oldindent; 635 } 636 637 /* Call this function from the debugger to see what X looks like. */ 638 639 void 640 debug_rtx (const_rtx x) 641 { 642 outfile = stderr; 643 sawclose = 0; 644 print_rtx (x); 645 fprintf (stderr, "\n"); 646 } 647 648 /* Count of rtx's to print with debug_rtx_list. 649 This global exists because gdb user defined commands have no arguments. */ 650 651 int debug_rtx_count = 0; /* 0 is treated as equivalent to 1 */ 652 653 /* Call this function to print list from X on. 654 655 N is a count of the rtx's to print. Positive values print from the specified 656 rtx on. Negative values print a window around the rtx. 657 EG: -5 prints 2 rtx's on either side (in addition to the specified rtx). */ 658 659 void 660 debug_rtx_list (const_rtx x, int n) 661 { 662 int i,count; 663 const_rtx insn; 664 665 count = n == 0 ? 1 : n < 0 ? -n : n; 666 667 /* If we are printing a window, back up to the start. */ 668 669 if (n < 0) 670 for (i = count / 2; i > 0; i--) 671 { 672 if (PREV_INSN (x) == 0) 673 break; 674 x = PREV_INSN (x); 675 } 676 677 for (i = count, insn = x; i > 0 && insn != 0; i--, insn = NEXT_INSN (insn)) 678 { 679 debug_rtx (insn); 680 fprintf (stderr, "\n"); 681 } 682 } 683 684 /* Call this function to print an rtx list from START to END inclusive. */ 685 686 void 687 debug_rtx_range (const_rtx start, const_rtx end) 688 { 689 while (1) 690 { 691 debug_rtx (start); 692 fprintf (stderr, "\n"); 693 if (!start || start == end) 694 break; 695 start = NEXT_INSN (start); 696 } 697 } 698 699 /* Call this function to search an rtx list to find one with insn uid UID, 700 and then call debug_rtx_list to print it, using DEBUG_RTX_COUNT. 701 The found insn is returned to enable further debugging analysis. */ 702 703 const_rtx 704 debug_rtx_find (const_rtx x, int uid) 705 { 706 while (x != 0 && INSN_UID (x) != uid) 707 x = NEXT_INSN (x); 708 if (x != 0) 709 { 710 debug_rtx_list (x, debug_rtx_count); 711 return x; 712 } 713 else 714 { 715 fprintf (stderr, "insn uid %d not found\n", uid); 716 return 0; 717 } 718 } 719 720 /* External entry point for printing a chain of insns 721 starting with RTX_FIRST onto file OUTF. 722 A blank line separates insns. 723 724 If RTX_FIRST is not an insn, then it alone is printed, with no newline. */ 725 726 void 727 print_rtl (FILE *outf, const_rtx rtx_first) 728 { 729 const_rtx tmp_rtx; 730 731 outfile = outf; 732 sawclose = 0; 733 734 if (rtx_first == 0) 735 { 736 fputs (print_rtx_head, outf); 737 fputs ("(nil)\n", outf); 738 } 739 else 740 switch (GET_CODE (rtx_first)) 741 { 742 case INSN: 743 case JUMP_INSN: 744 case CALL_INSN: 745 case NOTE: 746 case CODE_LABEL: 747 case BARRIER: 748 for (tmp_rtx = rtx_first; tmp_rtx != 0; tmp_rtx = NEXT_INSN (tmp_rtx)) 749 { 750 fputs (print_rtx_head, outfile); 751 print_rtx (tmp_rtx); 752 fprintf (outfile, "\n"); 753 } 754 break; 755 756 default: 757 fputs (print_rtx_head, outfile); 758 print_rtx (rtx_first); 759 } 760 } 761 762 /* Like print_rtx, except specify a file. */ 763 /* Return nonzero if we actually printed anything. */ 764 765 int 766 print_rtl_single (FILE *outf, const_rtx x) 767 { 768 outfile = outf; 769 sawclose = 0; 770 fputs (print_rtx_head, outfile); 771 print_rtx (x); 772 putc ('\n', outf); 773 return 1; 774 } 775 776 777 /* Like print_rtl except without all the detail; for example, 778 if RTX is a CONST_INT then print in decimal format. */ 779 780 void 781 print_simple_rtl (FILE *outf, const_rtx x) 782 { 783 flag_simple = 1; 784 print_rtl (outf, x); 785 flag_simple = 0; 786 } 787