1 /* Print RTL for GCC. 2 Copyright (C) 1987-2020 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free 8 Software Foundation; either version 3, or (at your option) any later 9 version. 10 11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12 WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GCC; see the file COPYING3. If not see 18 <http://www.gnu.org/licenses/>. */ 19 20 /* This file is compiled twice: once for the generator programs, 21 once for the compiler. */ 22 #ifdef GENERATOR_FILE 23 #include "bconfig.h" 24 #else 25 #include "config.h" 26 #endif 27 28 #include "system.h" 29 #include "coretypes.h" 30 #include "tm.h" 31 #include "rtl.h" 32 33 /* These headers all define things which are not available in 34 generator programs. */ 35 #ifndef GENERATOR_FILE 36 #include "alias.h" 37 #include "tree.h" 38 #include "basic-block.h" 39 #include "print-tree.h" 40 #include "flags.h" 41 #include "predict.h" 42 #include "function.h" 43 #include "cfg.h" 44 #include "basic-block.h" 45 #include "diagnostic.h" 46 #include "tree-pretty-print.h" 47 #include "alloc-pool.h" 48 #include "cselib.h" 49 #include "dumpfile.h" /* for dump_flags */ 50 #include "dwarf2out.h" 51 #include "pretty-print.h" 52 #endif 53 54 #include "print-rtl.h" 55 #include "rtl-iter.h" 56 57 /* Disable warnings about quoting issues in the pp_xxx calls below 58 that (intentionally) don't follow GCC diagnostic conventions. */ 59 #if __GNUC__ >= 10 60 # pragma GCC diagnostic push 61 # pragma GCC diagnostic ignored "-Wformat-diag" 62 #endif 63 64 /* String printed at beginning of each RTL when it is dumped. 65 This string is set to ASM_COMMENT_START when the RTL is dumped in 66 the assembly output file. */ 67 const char *print_rtx_head = ""; 68 69 #ifdef GENERATOR_FILE 70 /* These are defined from the .opt file when not used in generator 71 programs. */ 72 73 /* Nonzero means suppress output of instruction numbers 74 in debugging dumps. 75 This must be defined here so that programs like gencodes can be linked. */ 76 int flag_dump_unnumbered = 0; 77 78 /* Nonzero means suppress output of instruction numbers for previous 79 and next insns in debugging dumps. 80 This must be defined here so that programs like gencodes can be linked. */ 81 int flag_dump_unnumbered_links = 0; 82 #endif 83 84 /* Constructor for rtx_writer. */ 85 86 rtx_writer::rtx_writer (FILE *outf, int ind, bool simple, bool compact, 87 rtx_reuse_manager *reuse_manager) 88 : m_outfile (outf), m_sawclose (0), m_indent (ind), 89 m_in_call_function_usage (false), m_simple (simple), m_compact (compact), 90 m_rtx_reuse_manager (reuse_manager) 91 { 92 } 93 94 #ifndef GENERATOR_FILE 95 96 /* rtx_reuse_manager's ctor. */ 97 98 rtx_reuse_manager::rtx_reuse_manager () 99 : m_next_id (0) 100 { 101 } 102 103 /* Determine if X is of a kind suitable for dumping via reuse_rtx. */ 104 105 static bool 106 uses_rtx_reuse_p (const_rtx x) 107 { 108 if (x == NULL) 109 return false; 110 111 switch (GET_CODE (x)) 112 { 113 case DEBUG_EXPR: 114 case VALUE: 115 case SCRATCH: 116 return true; 117 118 /* We don't use reuse_rtx for consts. */ 119 CASE_CONST_UNIQUE: 120 default: 121 return false; 122 } 123 } 124 125 /* Traverse X and its descendents, determining if we see any rtx more than 126 once. Any rtx suitable for "reuse_rtx" that is seen more than once is 127 assigned an ID. */ 128 129 void 130 rtx_reuse_manager::preprocess (const_rtx x) 131 { 132 subrtx_iterator::array_type array; 133 FOR_EACH_SUBRTX (iter, array, x, NONCONST) 134 if (uses_rtx_reuse_p (*iter)) 135 { 136 if (int *count = m_rtx_occurrence_count.get (*iter)) 137 { 138 if (*(count++) == 1) 139 m_rtx_reuse_ids.put (*iter, m_next_id++); 140 } 141 else 142 m_rtx_occurrence_count.put (*iter, 1); 143 } 144 } 145 146 /* Return true iff X has been assigned a reuse ID. If it has, 147 and OUT is non-NULL, then write the reuse ID to *OUT. */ 148 149 bool 150 rtx_reuse_manager::has_reuse_id (const_rtx x, int *out) 151 { 152 int *id = m_rtx_reuse_ids.get (x); 153 if (id) 154 { 155 if (out) 156 *out = *id; 157 return true; 158 } 159 else 160 return false; 161 } 162 163 /* Determine if set_seen_def has been called for the given reuse ID. */ 164 165 bool 166 rtx_reuse_manager::seen_def_p (int reuse_id) 167 { 168 return bitmap_bit_p (m_defs_seen, reuse_id); 169 } 170 171 /* Record that the definition of the given reuse ID has been seen. */ 172 173 void 174 rtx_reuse_manager::set_seen_def (int reuse_id) 175 { 176 bitmap_set_bit (m_defs_seen, reuse_id); 177 } 178 179 #endif /* #ifndef GENERATOR_FILE */ 180 181 #ifndef GENERATOR_FILE 182 void 183 print_mem_expr (FILE *outfile, const_tree expr) 184 { 185 fputc (' ', outfile); 186 print_generic_expr (outfile, CONST_CAST_TREE (expr), dump_flags); 187 } 188 #endif 189 190 /* Print X to FILE. */ 191 192 static void 193 print_poly_int (FILE *file, poly_int64 x) 194 { 195 HOST_WIDE_INT const_x; 196 if (x.is_constant (&const_x)) 197 fprintf (file, HOST_WIDE_INT_PRINT_DEC, const_x); 198 else 199 { 200 fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC, x.coeffs[0]); 201 for (int i = 1; i < NUM_POLY_INT_COEFFS; ++i) 202 fprintf (file, ", " HOST_WIDE_INT_PRINT_DEC, x.coeffs[i]); 203 fprintf (file, "]"); 204 } 205 } 206 207 /* Subroutine of print_rtx_operand for handling code '0'. 208 0 indicates a field for internal use that should not be printed. 209 However there are various special cases, such as the third field 210 of a NOTE, where it indicates that the field has several different 211 valid contents. */ 212 213 void 214 rtx_writer::print_rtx_operand_code_0 (const_rtx in_rtx ATTRIBUTE_UNUSED, 215 int idx ATTRIBUTE_UNUSED) 216 { 217 #ifndef GENERATOR_FILE 218 if (idx == 1 && GET_CODE (in_rtx) == SYMBOL_REF) 219 { 220 int flags = SYMBOL_REF_FLAGS (in_rtx); 221 if (flags) 222 fprintf (m_outfile, " [flags %#x]", flags); 223 tree decl = SYMBOL_REF_DECL (in_rtx); 224 if (decl) 225 print_node_brief (m_outfile, "", decl, dump_flags); 226 } 227 else if (idx == 3 && NOTE_P (in_rtx)) 228 { 229 switch (NOTE_KIND (in_rtx)) 230 { 231 case NOTE_INSN_EH_REGION_BEG: 232 case NOTE_INSN_EH_REGION_END: 233 if (flag_dump_unnumbered) 234 fprintf (m_outfile, " #"); 235 else 236 fprintf (m_outfile, " %d", NOTE_EH_HANDLER (in_rtx)); 237 m_sawclose = 1; 238 break; 239 240 case NOTE_INSN_BLOCK_BEG: 241 case NOTE_INSN_BLOCK_END: 242 dump_addr (m_outfile, " ", NOTE_BLOCK (in_rtx)); 243 m_sawclose = 1; 244 break; 245 246 case NOTE_INSN_BASIC_BLOCK: 247 { 248 basic_block bb = NOTE_BASIC_BLOCK (in_rtx); 249 if (bb != 0) 250 fprintf (m_outfile, " [bb %d]", bb->index); 251 break; 252 } 253 254 case NOTE_INSN_DELETED_LABEL: 255 case NOTE_INSN_DELETED_DEBUG_LABEL: 256 { 257 const char *label = NOTE_DELETED_LABEL_NAME (in_rtx); 258 if (label) 259 fprintf (m_outfile, " (\"%s\")", label); 260 else 261 fprintf (m_outfile, " \"\""); 262 } 263 break; 264 265 case NOTE_INSN_SWITCH_TEXT_SECTIONS: 266 { 267 basic_block bb = NOTE_BASIC_BLOCK (in_rtx); 268 if (bb != 0) 269 fprintf (m_outfile, " [bb %d]", bb->index); 270 break; 271 } 272 273 case NOTE_INSN_VAR_LOCATION: 274 fputc (' ', m_outfile); 275 print_rtx (NOTE_VAR_LOCATION (in_rtx)); 276 break; 277 278 case NOTE_INSN_CFI: 279 fputc ('\n', m_outfile); 280 output_cfi_directive (m_outfile, NOTE_CFI (in_rtx)); 281 fputc ('\t', m_outfile); 282 break; 283 284 case NOTE_INSN_BEGIN_STMT: 285 case NOTE_INSN_INLINE_ENTRY: 286 #ifndef GENERATOR_FILE 287 { 288 expanded_location xloc 289 = expand_location (NOTE_MARKER_LOCATION (in_rtx)); 290 fprintf (m_outfile, " %s:%i", xloc.file, xloc.line); 291 } 292 #endif 293 break; 294 295 default: 296 break; 297 } 298 } 299 else if (idx == 7 && JUMP_P (in_rtx) && JUMP_LABEL (in_rtx) != NULL 300 && !m_compact) 301 { 302 /* Output the JUMP_LABEL reference. */ 303 fprintf (m_outfile, "\n%s%*s -> ", print_rtx_head, m_indent * 2, ""); 304 if (GET_CODE (JUMP_LABEL (in_rtx)) == RETURN) 305 fprintf (m_outfile, "return"); 306 else if (GET_CODE (JUMP_LABEL (in_rtx)) == SIMPLE_RETURN) 307 fprintf (m_outfile, "simple_return"); 308 else 309 fprintf (m_outfile, "%d", INSN_UID (JUMP_LABEL (in_rtx))); 310 } 311 else if (idx == 0 && GET_CODE (in_rtx) == VALUE) 312 { 313 cselib_val *val = CSELIB_VAL_PTR (in_rtx); 314 315 fprintf (m_outfile, " %u:%u", val->uid, val->hash); 316 dump_addr (m_outfile, " @", in_rtx); 317 dump_addr (m_outfile, "/", (void*)val); 318 } 319 else if (idx == 0 && GET_CODE (in_rtx) == DEBUG_EXPR) 320 { 321 fprintf (m_outfile, " D#%i", 322 DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (in_rtx))); 323 } 324 else if (idx == 0 && GET_CODE (in_rtx) == ENTRY_VALUE) 325 { 326 m_indent += 2; 327 if (!m_sawclose) 328 fprintf (m_outfile, " "); 329 print_rtx (ENTRY_VALUE_EXP (in_rtx)); 330 m_indent -= 2; 331 } 332 #endif 333 } 334 335 /* Subroutine of print_rtx_operand for handling code 'e'. 336 Also called by print_rtx_operand_code_u for handling code 'u' 337 for LABEL_REFs when they don't reference a CODE_LABEL. */ 338 339 void 340 rtx_writer::print_rtx_operand_code_e (const_rtx in_rtx, int idx) 341 { 342 m_indent += 2; 343 if (idx == 6 && INSN_P (in_rtx)) 344 /* Put REG_NOTES on their own line. */ 345 fprintf (m_outfile, "\n%s%*s", 346 print_rtx_head, m_indent * 2, ""); 347 if (!m_sawclose) 348 fprintf (m_outfile, " "); 349 if (idx == 7 && CALL_P (in_rtx)) 350 { 351 m_in_call_function_usage = true; 352 print_rtx (XEXP (in_rtx, idx)); 353 m_in_call_function_usage = false; 354 } 355 else 356 print_rtx (XEXP (in_rtx, idx)); 357 m_indent -= 2; 358 } 359 360 /* Subroutine of print_rtx_operand for handling codes 'E' and 'V'. */ 361 362 void 363 rtx_writer::print_rtx_operand_codes_E_and_V (const_rtx in_rtx, int idx) 364 { 365 m_indent += 2; 366 if (m_sawclose) 367 { 368 fprintf (m_outfile, "\n%s%*s", 369 print_rtx_head, m_indent * 2, ""); 370 m_sawclose = 0; 371 } 372 fputs (" [", m_outfile); 373 if (XVEC (in_rtx, idx) != NULL) 374 { 375 m_indent += 2; 376 if (XVECLEN (in_rtx, idx)) 377 m_sawclose = 1; 378 379 for (int j = 0; j < XVECLEN (in_rtx, idx); j++) 380 { 381 int j1; 382 383 print_rtx (XVECEXP (in_rtx, idx, j)); 384 for (j1 = j + 1; j1 < XVECLEN (in_rtx, idx); j1++) 385 if (XVECEXP (in_rtx, idx, j) != XVECEXP (in_rtx, idx, j1)) 386 break; 387 388 if (j1 != j + 1) 389 { 390 fprintf (m_outfile, " repeated x%i", j1 - j); 391 j = j1 - 1; 392 } 393 } 394 395 m_indent -= 2; 396 } 397 if (m_sawclose) 398 fprintf (m_outfile, "\n%s%*s", print_rtx_head, m_indent * 2, ""); 399 400 fputs ("]", m_outfile); 401 m_sawclose = 1; 402 m_indent -= 2; 403 } 404 405 /* Subroutine of print_rtx_operand for handling code 'i'. */ 406 407 void 408 rtx_writer::print_rtx_operand_code_i (const_rtx in_rtx, int idx) 409 { 410 if (idx == 4 && INSN_P (in_rtx)) 411 { 412 #ifndef GENERATOR_FILE 413 const rtx_insn *in_insn = as_a <const rtx_insn *> (in_rtx); 414 415 /* Pretty-print insn locations. Ignore scoping as it is mostly 416 redundant with line number information and do not print anything 417 when there is no location information available. */ 418 if (INSN_HAS_LOCATION (in_insn)) 419 { 420 expanded_location xloc = insn_location (in_insn); 421 fprintf (m_outfile, " \"%s\":%i:%i", xloc.file, xloc.line, 422 xloc.column); 423 } 424 #endif 425 } 426 else if (idx == 6 && GET_CODE (in_rtx) == ASM_OPERANDS) 427 { 428 #ifndef GENERATOR_FILE 429 if (ASM_OPERANDS_SOURCE_LOCATION (in_rtx) != UNKNOWN_LOCATION) 430 fprintf (m_outfile, " %s:%i", 431 LOCATION_FILE (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)), 432 LOCATION_LINE (ASM_OPERANDS_SOURCE_LOCATION (in_rtx))); 433 #endif 434 } 435 else if (idx == 1 && GET_CODE (in_rtx) == ASM_INPUT) 436 { 437 #ifndef GENERATOR_FILE 438 if (ASM_INPUT_SOURCE_LOCATION (in_rtx) != UNKNOWN_LOCATION) 439 fprintf (m_outfile, " %s:%i", 440 LOCATION_FILE (ASM_INPUT_SOURCE_LOCATION (in_rtx)), 441 LOCATION_LINE (ASM_INPUT_SOURCE_LOCATION (in_rtx))); 442 #endif 443 } 444 else if (idx == 5 && NOTE_P (in_rtx)) 445 { 446 /* This field is only used for NOTE_INSN_DELETED_LABEL, and 447 other times often contains garbage from INSN->NOTE death. */ 448 if (NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_LABEL 449 || NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_DEBUG_LABEL) 450 fprintf (m_outfile, " %d", XINT (in_rtx, idx)); 451 } 452 #if !defined(GENERATOR_FILE) && NUM_UNSPECV_VALUES > 0 453 else if (idx == 1 454 && GET_CODE (in_rtx) == UNSPEC_VOLATILE 455 && XINT (in_rtx, 1) >= 0 456 && XINT (in_rtx, 1) < NUM_UNSPECV_VALUES) 457 fprintf (m_outfile, " %s", unspecv_strings[XINT (in_rtx, 1)]); 458 #endif 459 #if !defined(GENERATOR_FILE) && NUM_UNSPEC_VALUES > 0 460 else if (idx == 1 461 && (GET_CODE (in_rtx) == UNSPEC 462 || GET_CODE (in_rtx) == UNSPEC_VOLATILE) 463 && XINT (in_rtx, 1) >= 0 464 && XINT (in_rtx, 1) < NUM_UNSPEC_VALUES) 465 fprintf (m_outfile, " %s", unspec_strings[XINT (in_rtx, 1)]); 466 #endif 467 else 468 { 469 int value = XINT (in_rtx, idx); 470 const char *name; 471 int is_insn = INSN_P (in_rtx); 472 473 /* Don't print INSN_CODEs in compact mode. */ 474 if (m_compact && is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, idx)) 475 { 476 m_sawclose = 0; 477 return; 478 } 479 480 if (flag_dump_unnumbered 481 && (is_insn || NOTE_P (in_rtx))) 482 fputc ('#', m_outfile); 483 else 484 fprintf (m_outfile, " %d", value); 485 486 if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, idx) 487 && XINT (in_rtx, idx) >= 0 488 && (name = get_insn_name (XINT (in_rtx, idx))) != NULL) 489 fprintf (m_outfile, " {%s}", name); 490 m_sawclose = 0; 491 } 492 } 493 494 /* Subroutine of print_rtx_operand for handling code 'r'. */ 495 496 void 497 rtx_writer::print_rtx_operand_code_r (const_rtx in_rtx) 498 { 499 int is_insn = INSN_P (in_rtx); 500 unsigned int regno = REGNO (in_rtx); 501 502 #ifndef GENERATOR_FILE 503 /* For hard registers and virtuals, always print the 504 regno, except in compact mode. */ 505 if (regno <= LAST_VIRTUAL_REGISTER && !m_compact) 506 fprintf (m_outfile, " %d", regno); 507 if (regno < FIRST_PSEUDO_REGISTER) 508 fprintf (m_outfile, " %s", reg_names[regno]); 509 else if (regno <= LAST_VIRTUAL_REGISTER) 510 { 511 if (regno == VIRTUAL_INCOMING_ARGS_REGNUM) 512 fprintf (m_outfile, " virtual-incoming-args"); 513 else if (regno == VIRTUAL_STACK_VARS_REGNUM) 514 fprintf (m_outfile, " virtual-stack-vars"); 515 else if (regno == VIRTUAL_STACK_DYNAMIC_REGNUM) 516 fprintf (m_outfile, " virtual-stack-dynamic"); 517 else if (regno == VIRTUAL_OUTGOING_ARGS_REGNUM) 518 fprintf (m_outfile, " virtual-outgoing-args"); 519 else if (regno == VIRTUAL_CFA_REGNUM) 520 fprintf (m_outfile, " virtual-cfa"); 521 else if (regno == VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM) 522 fprintf (m_outfile, " virtual-preferred-stack-boundary"); 523 else 524 fprintf (m_outfile, " virtual-reg-%d", regno-FIRST_VIRTUAL_REGISTER); 525 } 526 else 527 #endif 528 if (flag_dump_unnumbered && is_insn) 529 fputc ('#', m_outfile); 530 else if (m_compact) 531 { 532 /* In compact mode, print pseudos with '< and '>' wrapping the regno, 533 offseting it by (LAST_VIRTUAL_REGISTER + 1), so that the 534 first non-virtual pseudo is dumped as "<0>". */ 535 gcc_assert (regno > LAST_VIRTUAL_REGISTER); 536 fprintf (m_outfile, " <%d>", regno - (LAST_VIRTUAL_REGISTER + 1)); 537 } 538 else 539 fprintf (m_outfile, " %d", regno); 540 541 #ifndef GENERATOR_FILE 542 if (REG_ATTRS (in_rtx)) 543 { 544 fputs (" [", m_outfile); 545 if (regno != ORIGINAL_REGNO (in_rtx)) 546 fprintf (m_outfile, "orig:%i", ORIGINAL_REGNO (in_rtx)); 547 if (REG_EXPR (in_rtx)) 548 print_mem_expr (m_outfile, REG_EXPR (in_rtx)); 549 550 if (maybe_ne (REG_OFFSET (in_rtx), 0)) 551 { 552 fprintf (m_outfile, "+"); 553 print_poly_int (m_outfile, REG_OFFSET (in_rtx)); 554 } 555 fputs (" ]", m_outfile); 556 } 557 if (regno != ORIGINAL_REGNO (in_rtx)) 558 fprintf (m_outfile, " [%d]", ORIGINAL_REGNO (in_rtx)); 559 #endif 560 } 561 562 /* Subroutine of print_rtx_operand for handling code 'u'. */ 563 564 void 565 rtx_writer::print_rtx_operand_code_u (const_rtx in_rtx, int idx) 566 { 567 /* Don't print insn UIDs for PREV/NEXT_INSN in compact mode. */ 568 if (m_compact && INSN_CHAIN_CODE_P (GET_CODE (in_rtx)) && idx < 2) 569 return; 570 571 if (XEXP (in_rtx, idx) != NULL) 572 { 573 rtx sub = XEXP (in_rtx, idx); 574 enum rtx_code subc = GET_CODE (sub); 575 576 if (GET_CODE (in_rtx) == LABEL_REF) 577 { 578 if (subc == NOTE 579 && NOTE_KIND (sub) == NOTE_INSN_DELETED_LABEL) 580 { 581 if (flag_dump_unnumbered) 582 fprintf (m_outfile, " [# deleted]"); 583 else 584 fprintf (m_outfile, " [%d deleted]", INSN_UID (sub)); 585 m_sawclose = 0; 586 return; 587 } 588 589 if (subc != CODE_LABEL) 590 { 591 print_rtx_operand_code_e (in_rtx, idx); 592 return; 593 } 594 } 595 596 if (flag_dump_unnumbered 597 || (flag_dump_unnumbered_links && idx <= 1 598 && (INSN_P (in_rtx) || NOTE_P (in_rtx) 599 || LABEL_P (in_rtx) || BARRIER_P (in_rtx)))) 600 fputs (" #", m_outfile); 601 else 602 fprintf (m_outfile, " %d", INSN_UID (sub)); 603 } 604 else 605 fputs (" 0", m_outfile); 606 m_sawclose = 0; 607 } 608 609 /* Subroutine of print_rtx. Print operand IDX of IN_RTX. */ 610 611 void 612 rtx_writer::print_rtx_operand (const_rtx in_rtx, int idx) 613 { 614 const char *format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)); 615 616 switch (format_ptr[idx]) 617 { 618 const char *str; 619 620 case 'T': 621 str = XTMPL (in_rtx, idx); 622 goto string; 623 624 case 'S': 625 case 's': 626 str = XSTR (in_rtx, idx); 627 string: 628 629 if (str == 0) 630 fputs (" (nil)", m_outfile); 631 else 632 fprintf (m_outfile, " (\"%s\")", str); 633 m_sawclose = 1; 634 break; 635 636 case '0': 637 print_rtx_operand_code_0 (in_rtx, idx); 638 break; 639 640 case 'e': 641 print_rtx_operand_code_e (in_rtx, idx); 642 break; 643 644 case 'E': 645 case 'V': 646 print_rtx_operand_codes_E_and_V (in_rtx, idx); 647 break; 648 649 case 'w': 650 if (! m_simple) 651 fprintf (m_outfile, " "); 652 fprintf (m_outfile, HOST_WIDE_INT_PRINT_DEC, XWINT (in_rtx, idx)); 653 if (! m_simple && !m_compact) 654 fprintf (m_outfile, " [" HOST_WIDE_INT_PRINT_HEX "]", 655 (unsigned HOST_WIDE_INT) XWINT (in_rtx, idx)); 656 break; 657 658 case 'i': 659 print_rtx_operand_code_i (in_rtx, idx); 660 break; 661 662 case 'p': 663 fprintf (m_outfile, " "); 664 print_poly_int (m_outfile, SUBREG_BYTE (in_rtx)); 665 break; 666 667 case 'r': 668 print_rtx_operand_code_r (in_rtx); 669 break; 670 671 /* Print NOTE_INSN names rather than integer codes. */ 672 673 case 'n': 674 fprintf (m_outfile, " %s", GET_NOTE_INSN_NAME (XINT (in_rtx, idx))); 675 m_sawclose = 0; 676 break; 677 678 case 'u': 679 print_rtx_operand_code_u (in_rtx, idx); 680 break; 681 682 case 't': 683 #ifndef GENERATOR_FILE 684 if (idx == 0 && GET_CODE (in_rtx) == DEBUG_IMPLICIT_PTR) 685 print_mem_expr (m_outfile, DEBUG_IMPLICIT_PTR_DECL (in_rtx)); 686 else if (idx == 0 && GET_CODE (in_rtx) == DEBUG_PARAMETER_REF) 687 print_mem_expr (m_outfile, DEBUG_PARAMETER_REF_DECL (in_rtx)); 688 else 689 dump_addr (m_outfile, " ", XTREE (in_rtx, idx)); 690 #endif 691 break; 692 693 case '*': 694 fputs (" Unknown", m_outfile); 695 m_sawclose = 0; 696 break; 697 698 case 'B': 699 /* Don't print basic block ids in compact mode. */ 700 if (m_compact) 701 break; 702 #ifndef GENERATOR_FILE 703 if (XBBDEF (in_rtx, idx)) 704 fprintf (m_outfile, " %i", XBBDEF (in_rtx, idx)->index); 705 #endif 706 break; 707 708 default: 709 gcc_unreachable (); 710 } 711 } 712 713 /* Subroutine of rtx_writer::print_rtx. 714 In compact mode, determine if operand IDX of IN_RTX is interesting 715 to dump, or (if in a trailing position) it can be omitted. */ 716 717 bool 718 rtx_writer::operand_has_default_value_p (const_rtx in_rtx, int idx) 719 { 720 const char *format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)); 721 722 switch (format_ptr[idx]) 723 { 724 case 'e': 725 case 'u': 726 return XEXP (in_rtx, idx) == NULL_RTX; 727 728 case 's': 729 return XSTR (in_rtx, idx) == NULL; 730 731 case '0': 732 switch (GET_CODE (in_rtx)) 733 { 734 case JUMP_INSN: 735 /* JUMP_LABELs are always omitted in compact mode, so treat 736 any value here as omittable, so that earlier operands can 737 potentially be omitted also. */ 738 return m_compact; 739 740 default: 741 return false; 742 743 } 744 745 default: 746 return false; 747 } 748 } 749 750 /* Print IN_RTX onto m_outfile. This is the recursive part of printing. */ 751 752 void 753 rtx_writer::print_rtx (const_rtx in_rtx) 754 { 755 int idx = 0; 756 757 if (m_sawclose) 758 { 759 if (m_simple) 760 fputc (' ', m_outfile); 761 else 762 fprintf (m_outfile, "\n%s%*s", print_rtx_head, m_indent * 2, ""); 763 m_sawclose = 0; 764 } 765 766 if (in_rtx == 0) 767 { 768 fputs ("(nil)", m_outfile); 769 m_sawclose = 1; 770 return; 771 } 772 else if (GET_CODE (in_rtx) > NUM_RTX_CODE) 773 { 774 fprintf (m_outfile, "(??? bad code %d\n%s%*s)", GET_CODE (in_rtx), 775 print_rtx_head, m_indent * 2, ""); 776 m_sawclose = 1; 777 return; 778 } 779 780 fputc ('(', m_outfile); 781 782 /* Print name of expression code. */ 783 784 /* Handle reuse. */ 785 #ifndef GENERATOR_FILE 786 if (m_rtx_reuse_manager) 787 { 788 int reuse_id; 789 if (m_rtx_reuse_manager->has_reuse_id (in_rtx, &reuse_id)) 790 { 791 /* Have we already seen the defn of this rtx? */ 792 if (m_rtx_reuse_manager->seen_def_p (reuse_id)) 793 { 794 fprintf (m_outfile, "reuse_rtx %i)", reuse_id); 795 m_sawclose = 1; 796 return; 797 } 798 else 799 { 800 /* First time we've seen this reused-rtx. */ 801 fprintf (m_outfile, "%i|", reuse_id); 802 m_rtx_reuse_manager->set_seen_def (reuse_id); 803 } 804 } 805 } 806 #endif /* #ifndef GENERATOR_FILE */ 807 808 /* In compact mode, prefix the code of insns with "c", 809 giving "cinsn", "cnote" etc. */ 810 if (m_compact && is_a <const rtx_insn *, const struct rtx_def> (in_rtx)) 811 { 812 /* "ccode_label" is slightly awkward, so special-case it as 813 just "clabel". */ 814 rtx_code code = GET_CODE (in_rtx); 815 if (code == CODE_LABEL) 816 fprintf (m_outfile, "clabel"); 817 else 818 fprintf (m_outfile, "c%s", GET_RTX_NAME (code)); 819 } 820 else if (m_simple && CONST_INT_P (in_rtx)) 821 ; /* no code. */ 822 else 823 fprintf (m_outfile, "%s", GET_RTX_NAME (GET_CODE (in_rtx))); 824 825 if (! m_simple) 826 { 827 if (RTX_FLAG (in_rtx, in_struct)) 828 fputs ("/s", m_outfile); 829 830 if (RTX_FLAG (in_rtx, volatil)) 831 fputs ("/v", m_outfile); 832 833 if (RTX_FLAG (in_rtx, unchanging)) 834 fputs ("/u", m_outfile); 835 836 if (RTX_FLAG (in_rtx, frame_related)) 837 fputs ("/f", m_outfile); 838 839 if (RTX_FLAG (in_rtx, jump)) 840 fputs ("/j", m_outfile); 841 842 if (RTX_FLAG (in_rtx, call)) 843 fputs ("/c", m_outfile); 844 845 if (RTX_FLAG (in_rtx, return_val)) 846 fputs ("/i", m_outfile); 847 848 /* Print REG_NOTE names for EXPR_LIST and INSN_LIST. */ 849 if ((GET_CODE (in_rtx) == EXPR_LIST 850 || GET_CODE (in_rtx) == INSN_LIST 851 || GET_CODE (in_rtx) == INT_LIST) 852 && (int)GET_MODE (in_rtx) < REG_NOTE_MAX 853 && !m_in_call_function_usage) 854 fprintf (m_outfile, ":%s", 855 GET_REG_NOTE_NAME (GET_MODE (in_rtx))); 856 857 /* For other rtl, print the mode if it's not VOID. */ 858 else if (GET_MODE (in_rtx) != VOIDmode) 859 fprintf (m_outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx))); 860 861 #ifndef GENERATOR_FILE 862 if (GET_CODE (in_rtx) == VAR_LOCATION) 863 { 864 if (TREE_CODE (PAT_VAR_LOCATION_DECL (in_rtx)) == STRING_CST) 865 fputs (" <debug string placeholder>", m_outfile); 866 else 867 print_mem_expr (m_outfile, PAT_VAR_LOCATION_DECL (in_rtx)); 868 fputc (' ', m_outfile); 869 print_rtx (PAT_VAR_LOCATION_LOC (in_rtx)); 870 if (PAT_VAR_LOCATION_STATUS (in_rtx) 871 == VAR_INIT_STATUS_UNINITIALIZED) 872 fprintf (m_outfile, " [uninit]"); 873 m_sawclose = 1; 874 idx = GET_RTX_LENGTH (VAR_LOCATION); 875 } 876 #endif 877 } 878 879 #ifndef GENERATOR_FILE 880 if (CONST_DOUBLE_AS_FLOAT_P (in_rtx)) 881 idx = 5; 882 #endif 883 884 /* For insns, print the INSN_UID. */ 885 if (INSN_CHAIN_CODE_P (GET_CODE (in_rtx))) 886 { 887 if (flag_dump_unnumbered) 888 fprintf (m_outfile, " #"); 889 else 890 fprintf (m_outfile, " %d", INSN_UID (in_rtx)); 891 } 892 893 /* Determine which is the final operand to print. 894 In compact mode, skip trailing operands that have the default values 895 e.g. trailing "(nil)" values. */ 896 int limit = GET_RTX_LENGTH (GET_CODE (in_rtx)); 897 if (m_compact) 898 while (limit > idx && operand_has_default_value_p (in_rtx, limit - 1)) 899 limit--; 900 901 /* Get the format string and skip the first elements if we have handled 902 them already. */ 903 904 for (; idx < limit; idx++) 905 print_rtx_operand (in_rtx, idx); 906 907 switch (GET_CODE (in_rtx)) 908 { 909 #ifndef GENERATOR_FILE 910 case MEM: 911 if (__builtin_expect (final_insns_dump_p, false)) 912 fprintf (m_outfile, " ["); 913 else 914 fprintf (m_outfile, " [" HOST_WIDE_INT_PRINT_DEC, 915 (HOST_WIDE_INT) MEM_ALIAS_SET (in_rtx)); 916 917 if (MEM_EXPR (in_rtx)) 918 print_mem_expr (m_outfile, MEM_EXPR (in_rtx)); 919 else 920 fputc (' ', m_outfile); 921 922 if (MEM_OFFSET_KNOWN_P (in_rtx)) 923 { 924 fprintf (m_outfile, "+"); 925 print_poly_int (m_outfile, MEM_OFFSET (in_rtx)); 926 } 927 928 if (MEM_SIZE_KNOWN_P (in_rtx)) 929 { 930 fprintf (m_outfile, " S"); 931 print_poly_int (m_outfile, MEM_SIZE (in_rtx)); 932 } 933 934 if (MEM_ALIGN (in_rtx) != 1) 935 fprintf (m_outfile, " A%u", MEM_ALIGN (in_rtx)); 936 937 if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (in_rtx))) 938 fprintf (m_outfile, " AS%u", MEM_ADDR_SPACE (in_rtx)); 939 940 fputc (']', m_outfile); 941 break; 942 943 case CONST_DOUBLE: 944 if (FLOAT_MODE_P (GET_MODE (in_rtx))) 945 { 946 char s[60]; 947 948 real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx), 949 sizeof (s), 0, 1); 950 fprintf (m_outfile, " %s", s); 951 952 real_to_hexadecimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx), 953 sizeof (s), 0, 1); 954 fprintf (m_outfile, " [%s]", s); 955 } 956 break; 957 958 case CONST_WIDE_INT: 959 fprintf (m_outfile, " "); 960 cwi_output_hex (m_outfile, in_rtx); 961 break; 962 963 case CONST_POLY_INT: 964 fprintf (m_outfile, " ["); 965 print_dec (CONST_POLY_INT_COEFFS (in_rtx)[0], m_outfile, SIGNED); 966 for (unsigned int i = 1; i < NUM_POLY_INT_COEFFS; ++i) 967 { 968 fprintf (m_outfile, ", "); 969 print_dec (CONST_POLY_INT_COEFFS (in_rtx)[i], m_outfile, SIGNED); 970 } 971 fprintf (m_outfile, "]"); 972 break; 973 #endif 974 975 case CODE_LABEL: 976 if (!m_compact) 977 fprintf (m_outfile, " [%d uses]", LABEL_NUSES (in_rtx)); 978 switch (LABEL_KIND (in_rtx)) 979 { 980 case LABEL_NORMAL: break; 981 case LABEL_STATIC_ENTRY: fputs (" [entry]", m_outfile); break; 982 case LABEL_GLOBAL_ENTRY: fputs (" [global entry]", m_outfile); break; 983 case LABEL_WEAK_ENTRY: fputs (" [weak entry]", m_outfile); break; 984 default: gcc_unreachable (); 985 } 986 break; 987 988 default: 989 break; 990 } 991 992 fputc (')', m_outfile); 993 m_sawclose = 1; 994 } 995 996 /* Emit a closing parenthesis and newline. */ 997 998 void 999 rtx_writer::finish_directive () 1000 { 1001 fprintf (m_outfile, ")\n"); 1002 m_sawclose = 0; 1003 } 1004 1005 /* Print an rtx on the current line of FILE. Initially indent IND 1006 characters. */ 1007 1008 void 1009 print_inline_rtx (FILE *outf, const_rtx x, int ind) 1010 { 1011 rtx_writer w (outf, ind, false, false, NULL); 1012 w.print_rtx (x); 1013 } 1014 1015 /* Call this function from the debugger to see what X looks like. */ 1016 1017 DEBUG_FUNCTION void 1018 debug_rtx (const_rtx x) 1019 { 1020 rtx_writer w (stderr, 0, false, false, NULL); 1021 w.print_rtx (x); 1022 fprintf (stderr, "\n"); 1023 } 1024 1025 /* Dump rtx REF. */ 1026 1027 DEBUG_FUNCTION void 1028 debug (const rtx_def &ref) 1029 { 1030 debug_rtx (&ref); 1031 } 1032 1033 DEBUG_FUNCTION void 1034 debug (const rtx_def *ptr) 1035 { 1036 if (ptr) 1037 debug (*ptr); 1038 else 1039 fprintf (stderr, "<nil>\n"); 1040 } 1041 1042 /* Like debug_rtx but with no newline, as debug_helper will add one. 1043 1044 Note: No debug_slim(rtx_insn *) variant implemented, as this 1045 function can serve for both rtx and rtx_insn. */ 1046 1047 static void 1048 debug_slim (const_rtx x) 1049 { 1050 rtx_writer w (stderr, 0, false, false, NULL); 1051 w.print_rtx (x); 1052 } 1053 1054 DEFINE_DEBUG_VEC (rtx_def *) 1055 DEFINE_DEBUG_VEC (rtx_insn *) 1056 DEFINE_DEBUG_HASH_SET (rtx_def *) 1057 DEFINE_DEBUG_HASH_SET (rtx_insn *) 1058 1059 /* Count of rtx's to print with debug_rtx_list. 1060 This global exists because gdb user defined commands have no arguments. */ 1061 1062 DEBUG_VARIABLE int debug_rtx_count = 0; /* 0 is treated as equivalent to 1 */ 1063 1064 /* Call this function to print list from X on. 1065 1066 N is a count of the rtx's to print. Positive values print from the specified 1067 rtx_insn on. Negative values print a window around the rtx_insn. 1068 EG: -5 prints 2 rtx_insn's on either side (in addition to the specified 1069 rtx_insn). */ 1070 1071 DEBUG_FUNCTION void 1072 debug_rtx_list (const rtx_insn *x, int n) 1073 { 1074 int i,count; 1075 const rtx_insn *insn; 1076 1077 count = n == 0 ? 1 : n < 0 ? -n : n; 1078 1079 /* If we are printing a window, back up to the start. */ 1080 1081 if (n < 0) 1082 for (i = count / 2; i > 0; i--) 1083 { 1084 if (PREV_INSN (x) == 0) 1085 break; 1086 x = PREV_INSN (x); 1087 } 1088 1089 for (i = count, insn = x; i > 0 && insn != 0; i--, insn = NEXT_INSN (insn)) 1090 { 1091 debug_rtx (insn); 1092 fprintf (stderr, "\n"); 1093 } 1094 } 1095 1096 /* Call this function to print an rtx_insn list from START to END 1097 inclusive. */ 1098 1099 DEBUG_FUNCTION void 1100 debug_rtx_range (const rtx_insn *start, const rtx_insn *end) 1101 { 1102 while (1) 1103 { 1104 debug_rtx (start); 1105 fprintf (stderr, "\n"); 1106 if (!start || start == end) 1107 break; 1108 start = NEXT_INSN (start); 1109 } 1110 } 1111 1112 /* Call this function to search an rtx_insn list to find one with insn uid UID, 1113 and then call debug_rtx_list to print it, using DEBUG_RTX_COUNT. 1114 The found insn is returned to enable further debugging analysis. */ 1115 1116 DEBUG_FUNCTION const rtx_insn * 1117 debug_rtx_find (const rtx_insn *x, int uid) 1118 { 1119 while (x != 0 && INSN_UID (x) != uid) 1120 x = NEXT_INSN (x); 1121 if (x != 0) 1122 { 1123 debug_rtx_list (x, debug_rtx_count); 1124 return x; 1125 } 1126 else 1127 { 1128 fprintf (stderr, "insn uid %d not found\n", uid); 1129 return 0; 1130 } 1131 } 1132 1133 /* External entry point for printing a chain of insns 1134 starting with RTX_FIRST. 1135 A blank line separates insns. 1136 1137 If RTX_FIRST is not an insn, then it alone is printed, with no newline. */ 1138 1139 void 1140 rtx_writer::print_rtl (const_rtx rtx_first) 1141 { 1142 const rtx_insn *tmp_rtx; 1143 1144 if (rtx_first == 0) 1145 { 1146 fputs (print_rtx_head, m_outfile); 1147 fputs ("(nil)\n", m_outfile); 1148 } 1149 else 1150 switch (GET_CODE (rtx_first)) 1151 { 1152 case INSN: 1153 case JUMP_INSN: 1154 case CALL_INSN: 1155 case NOTE: 1156 case CODE_LABEL: 1157 case JUMP_TABLE_DATA: 1158 case BARRIER: 1159 for (tmp_rtx = as_a <const rtx_insn *> (rtx_first); 1160 tmp_rtx != 0; 1161 tmp_rtx = NEXT_INSN (tmp_rtx)) 1162 { 1163 fputs (print_rtx_head, m_outfile); 1164 print_rtx (tmp_rtx); 1165 fprintf (m_outfile, "\n"); 1166 } 1167 break; 1168 1169 default: 1170 fputs (print_rtx_head, m_outfile); 1171 print_rtx (rtx_first); 1172 } 1173 } 1174 1175 /* External entry point for printing a chain of insns 1176 starting with RTX_FIRST onto file OUTF. 1177 A blank line separates insns. 1178 1179 If RTX_FIRST is not an insn, then it alone is printed, with no newline. */ 1180 1181 void 1182 print_rtl (FILE *outf, const_rtx rtx_first) 1183 { 1184 rtx_writer w (outf, 0, false, false, NULL); 1185 w.print_rtl (rtx_first); 1186 } 1187 1188 /* Like print_rtx, except specify a file. */ 1189 /* Return nonzero if we actually printed anything. */ 1190 1191 int 1192 print_rtl_single (FILE *outf, const_rtx x) 1193 { 1194 rtx_writer w (outf, 0, false, false, NULL); 1195 return w.print_rtl_single_with_indent (x, 0); 1196 } 1197 1198 /* Like print_rtl_single, except specify an indentation. */ 1199 1200 int 1201 rtx_writer::print_rtl_single_with_indent (const_rtx x, int ind) 1202 { 1203 char *s_indent = (char *) alloca ((size_t) ind + 1); 1204 memset ((void *) s_indent, ' ', (size_t) ind); 1205 s_indent[ind] = '\0'; 1206 fputs (s_indent, m_outfile); 1207 fputs (print_rtx_head, m_outfile); 1208 1209 int old_indent = m_indent; 1210 m_indent = ind; 1211 m_sawclose = 0; 1212 print_rtx (x); 1213 putc ('\n', m_outfile); 1214 m_indent = old_indent; 1215 return 1; 1216 } 1217 1218 1219 /* Like print_rtl except without all the detail; for example, 1220 if RTX is a CONST_INT then print in decimal format. */ 1221 1222 void 1223 print_simple_rtl (FILE *outf, const_rtx x) 1224 { 1225 rtx_writer w (outf, 0, true, false, NULL); 1226 w.print_rtl (x); 1227 } 1228 1229 /* Print the elements of VEC to FILE. */ 1230 1231 void 1232 print_rtx_insn_vec (FILE *file, const vec<rtx_insn *> &vec) 1233 { 1234 fputc('{', file); 1235 1236 unsigned int len = vec.length (); 1237 for (unsigned int i = 0; i < len; i++) 1238 { 1239 print_rtl (file, vec[i]); 1240 if (i < len - 1) 1241 fputs (", ", file); 1242 } 1243 1244 fputc ('}', file); 1245 } 1246 1247 #ifndef GENERATOR_FILE 1248 /* The functions below try to print RTL in a form resembling assembler 1249 mnemonics. Because this form is more concise than the "traditional" form 1250 of RTL printing in Lisp-style, the form printed by this file is called 1251 "slim". RTL dumps in slim format can be obtained by appending the "-slim" 1252 option to -fdump-rtl-<pass>. Control flow graph output as a DOT file is 1253 always printed in slim form. 1254 1255 The normal interface to the functionality provided in this pretty-printer 1256 is through the dump_*_slim functions to print to a stream, or via the 1257 print_*_slim functions to print into a user's pretty-printer. 1258 1259 It is also possible to obtain a string for a single pattern as a string 1260 pointer, via str_pattern_slim, but this usage is discouraged. */ 1261 1262 /* For insns we print patterns, and for some patterns we print insns... */ 1263 static void print_insn_with_notes (pretty_printer *, const rtx_insn *); 1264 1265 /* This recognizes rtx'en classified as expressions. These are always 1266 represent some action on values or results of other expression, that 1267 may be stored in objects representing values. */ 1268 1269 static void 1270 print_exp (pretty_printer *pp, const_rtx x, int verbose) 1271 { 1272 const char *st[4]; 1273 const char *fun; 1274 rtx op[4]; 1275 int i; 1276 1277 fun = (char *) 0; 1278 for (i = 0; i < 4; i++) 1279 { 1280 st[i] = (char *) 0; 1281 op[i] = NULL_RTX; 1282 } 1283 1284 switch (GET_CODE (x)) 1285 { 1286 case PLUS: 1287 op[0] = XEXP (x, 0); 1288 if (CONST_INT_P (XEXP (x, 1)) 1289 && INTVAL (XEXP (x, 1)) < 0) 1290 { 1291 st[1] = "-"; 1292 op[1] = GEN_INT (-INTVAL (XEXP (x, 1))); 1293 } 1294 else 1295 { 1296 st[1] = "+"; 1297 op[1] = XEXP (x, 1); 1298 } 1299 break; 1300 case LO_SUM: 1301 op[0] = XEXP (x, 0); 1302 st[1] = "+low("; 1303 op[1] = XEXP (x, 1); 1304 st[2] = ")"; 1305 break; 1306 case MINUS: 1307 op[0] = XEXP (x, 0); 1308 st[1] = "-"; 1309 op[1] = XEXP (x, 1); 1310 break; 1311 case COMPARE: 1312 fun = "cmp"; 1313 op[0] = XEXP (x, 0); 1314 op[1] = XEXP (x, 1); 1315 break; 1316 case NEG: 1317 st[0] = "-"; 1318 op[0] = XEXP (x, 0); 1319 break; 1320 case FMA: 1321 st[0] = "{"; 1322 op[0] = XEXP (x, 0); 1323 st[1] = "*"; 1324 op[1] = XEXP (x, 1); 1325 st[2] = "+"; 1326 op[2] = XEXP (x, 2); 1327 st[3] = "}"; 1328 break; 1329 case MULT: 1330 op[0] = XEXP (x, 0); 1331 st[1] = "*"; 1332 op[1] = XEXP (x, 1); 1333 break; 1334 case DIV: 1335 op[0] = XEXP (x, 0); 1336 st[1] = "/"; 1337 op[1] = XEXP (x, 1); 1338 break; 1339 case UDIV: 1340 fun = "udiv"; 1341 op[0] = XEXP (x, 0); 1342 op[1] = XEXP (x, 1); 1343 break; 1344 case MOD: 1345 op[0] = XEXP (x, 0); 1346 st[1] = "%"; 1347 op[1] = XEXP (x, 1); 1348 break; 1349 case UMOD: 1350 fun = "umod"; 1351 op[0] = XEXP (x, 0); 1352 op[1] = XEXP (x, 1); 1353 break; 1354 case SMIN: 1355 fun = "smin"; 1356 op[0] = XEXP (x, 0); 1357 op[1] = XEXP (x, 1); 1358 break; 1359 case SMAX: 1360 fun = "smax"; 1361 op[0] = XEXP (x, 0); 1362 op[1] = XEXP (x, 1); 1363 break; 1364 case UMIN: 1365 fun = "umin"; 1366 op[0] = XEXP (x, 0); 1367 op[1] = XEXP (x, 1); 1368 break; 1369 case UMAX: 1370 fun = "umax"; 1371 op[0] = XEXP (x, 0); 1372 op[1] = XEXP (x, 1); 1373 break; 1374 case NOT: 1375 st[0] = "~"; 1376 op[0] = XEXP (x, 0); 1377 break; 1378 case AND: 1379 op[0] = XEXP (x, 0); 1380 st[1] = "&"; 1381 op[1] = XEXP (x, 1); 1382 break; 1383 case IOR: 1384 op[0] = XEXP (x, 0); 1385 st[1] = "|"; 1386 op[1] = XEXP (x, 1); 1387 break; 1388 case XOR: 1389 op[0] = XEXP (x, 0); 1390 st[1] = "^"; 1391 op[1] = XEXP (x, 1); 1392 break; 1393 case ASHIFT: 1394 op[0] = XEXP (x, 0); 1395 st[1] = "<<"; 1396 op[1] = XEXP (x, 1); 1397 break; 1398 case LSHIFTRT: 1399 op[0] = XEXP (x, 0); 1400 st[1] = " 0>>"; 1401 op[1] = XEXP (x, 1); 1402 break; 1403 case ASHIFTRT: 1404 op[0] = XEXP (x, 0); 1405 st[1] = ">>"; 1406 op[1] = XEXP (x, 1); 1407 break; 1408 case ROTATE: 1409 op[0] = XEXP (x, 0); 1410 st[1] = "<-<"; 1411 op[1] = XEXP (x, 1); 1412 break; 1413 case ROTATERT: 1414 op[0] = XEXP (x, 0); 1415 st[1] = ">->"; 1416 op[1] = XEXP (x, 1); 1417 break; 1418 case NE: 1419 op[0] = XEXP (x, 0); 1420 st[1] = "!="; 1421 op[1] = XEXP (x, 1); 1422 break; 1423 case EQ: 1424 op[0] = XEXP (x, 0); 1425 st[1] = "=="; 1426 op[1] = XEXP (x, 1); 1427 break; 1428 case GE: 1429 op[0] = XEXP (x, 0); 1430 st[1] = ">="; 1431 op[1] = XEXP (x, 1); 1432 break; 1433 case GT: 1434 op[0] = XEXP (x, 0); 1435 st[1] = ">"; 1436 op[1] = XEXP (x, 1); 1437 break; 1438 case LE: 1439 op[0] = XEXP (x, 0); 1440 st[1] = "<="; 1441 op[1] = XEXP (x, 1); 1442 break; 1443 case LT: 1444 op[0] = XEXP (x, 0); 1445 st[1] = "<"; 1446 op[1] = XEXP (x, 1); 1447 break; 1448 case SIGN_EXTRACT: 1449 fun = (verbose) ? "sign_extract" : "sxt"; 1450 op[0] = XEXP (x, 0); 1451 op[1] = XEXP (x, 1); 1452 op[2] = XEXP (x, 2); 1453 break; 1454 case ZERO_EXTRACT: 1455 fun = (verbose) ? "zero_extract" : "zxt"; 1456 op[0] = XEXP (x, 0); 1457 op[1] = XEXP (x, 1); 1458 op[2] = XEXP (x, 2); 1459 break; 1460 case SIGN_EXTEND: 1461 fun = (verbose) ? "sign_extend" : "sxn"; 1462 op[0] = XEXP (x, 0); 1463 break; 1464 case ZERO_EXTEND: 1465 fun = (verbose) ? "zero_extend" : "zxn"; 1466 op[0] = XEXP (x, 0); 1467 break; 1468 case FLOAT_EXTEND: 1469 fun = (verbose) ? "float_extend" : "fxn"; 1470 op[0] = XEXP (x, 0); 1471 break; 1472 case TRUNCATE: 1473 fun = (verbose) ? "trunc" : "trn"; 1474 op[0] = XEXP (x, 0); 1475 break; 1476 case FLOAT_TRUNCATE: 1477 fun = (verbose) ? "float_trunc" : "ftr"; 1478 op[0] = XEXP (x, 0); 1479 break; 1480 case FLOAT: 1481 fun = (verbose) ? "float" : "flt"; 1482 op[0] = XEXP (x, 0); 1483 break; 1484 case UNSIGNED_FLOAT: 1485 fun = (verbose) ? "uns_float" : "ufl"; 1486 op[0] = XEXP (x, 0); 1487 break; 1488 case FIX: 1489 fun = "fix"; 1490 op[0] = XEXP (x, 0); 1491 break; 1492 case UNSIGNED_FIX: 1493 fun = (verbose) ? "uns_fix" : "ufx"; 1494 op[0] = XEXP (x, 0); 1495 break; 1496 case PRE_DEC: 1497 st[0] = "--"; 1498 op[0] = XEXP (x, 0); 1499 break; 1500 case PRE_INC: 1501 st[0] = "++"; 1502 op[0] = XEXP (x, 0); 1503 break; 1504 case POST_DEC: 1505 op[0] = XEXP (x, 0); 1506 st[1] = "--"; 1507 break; 1508 case POST_INC: 1509 op[0] = XEXP (x, 0); 1510 st[1] = "++"; 1511 break; 1512 case PRE_MODIFY: 1513 st[0] = "pre "; 1514 op[0] = XEXP (XEXP (x, 1), 0); 1515 st[1] = "+="; 1516 op[1] = XEXP (XEXP (x, 1), 1); 1517 break; 1518 case POST_MODIFY: 1519 st[0] = "post "; 1520 op[0] = XEXP (XEXP (x, 1), 0); 1521 st[1] = "+="; 1522 op[1] = XEXP (XEXP (x, 1), 1); 1523 break; 1524 case CALL: 1525 st[0] = "call "; 1526 op[0] = XEXP (x, 0); 1527 if (verbose) 1528 { 1529 st[1] = " argc:"; 1530 op[1] = XEXP (x, 1); 1531 } 1532 break; 1533 case IF_THEN_ELSE: 1534 st[0] = "{("; 1535 op[0] = XEXP (x, 0); 1536 st[1] = ")?"; 1537 op[1] = XEXP (x, 1); 1538 st[2] = ":"; 1539 op[2] = XEXP (x, 2); 1540 st[3] = "}"; 1541 break; 1542 case TRAP_IF: 1543 fun = "trap_if"; 1544 op[0] = TRAP_CONDITION (x); 1545 break; 1546 case PREFETCH: 1547 fun = "prefetch"; 1548 op[0] = XEXP (x, 0); 1549 op[1] = XEXP (x, 1); 1550 op[2] = XEXP (x, 2); 1551 break; 1552 case UNSPEC: 1553 case UNSPEC_VOLATILE: 1554 { 1555 pp_string (pp, "unspec"); 1556 if (GET_CODE (x) == UNSPEC_VOLATILE) 1557 pp_string (pp, "/v"); 1558 pp_left_bracket (pp); 1559 for (i = 0; i < XVECLEN (x, 0); i++) 1560 { 1561 if (i != 0) 1562 pp_comma (pp); 1563 print_pattern (pp, XVECEXP (x, 0, i), verbose); 1564 } 1565 pp_string (pp, "] "); 1566 pp_decimal_int (pp, XINT (x, 1)); 1567 } 1568 break; 1569 default: 1570 { 1571 /* Most unhandled codes can be printed as pseudo-functions. */ 1572 if (GET_RTX_CLASS (GET_CODE (x)) == RTX_UNARY) 1573 { 1574 fun = GET_RTX_NAME (GET_CODE (x)); 1575 op[0] = XEXP (x, 0); 1576 } 1577 else if (GET_RTX_CLASS (GET_CODE (x)) == RTX_COMPARE 1578 || GET_RTX_CLASS (GET_CODE (x)) == RTX_COMM_COMPARE 1579 || GET_RTX_CLASS (GET_CODE (x)) == RTX_BIN_ARITH 1580 || GET_RTX_CLASS (GET_CODE (x)) == RTX_COMM_ARITH) 1581 { 1582 fun = GET_RTX_NAME (GET_CODE (x)); 1583 op[0] = XEXP (x, 0); 1584 op[1] = XEXP (x, 1); 1585 } 1586 else if (GET_RTX_CLASS (GET_CODE (x)) == RTX_TERNARY) 1587 { 1588 fun = GET_RTX_NAME (GET_CODE (x)); 1589 op[0] = XEXP (x, 0); 1590 op[1] = XEXP (x, 1); 1591 op[2] = XEXP (x, 2); 1592 } 1593 else 1594 /* Give up, just print the RTX name. */ 1595 st[0] = GET_RTX_NAME (GET_CODE (x)); 1596 } 1597 break; 1598 } 1599 1600 /* Print this as a function? */ 1601 if (fun) 1602 { 1603 pp_string (pp, fun); 1604 pp_left_paren (pp); 1605 } 1606 1607 for (i = 0; i < 4; i++) 1608 { 1609 if (st[i]) 1610 pp_string (pp, st[i]); 1611 1612 if (op[i]) 1613 { 1614 if (fun && i != 0) 1615 pp_comma (pp); 1616 print_value (pp, op[i], verbose); 1617 } 1618 } 1619 1620 if (fun) 1621 pp_right_paren (pp); 1622 } /* print_exp */ 1623 1624 /* Prints rtxes, I customarily classified as values. They're constants, 1625 registers, labels, symbols and memory accesses. */ 1626 1627 void 1628 print_value (pretty_printer *pp, const_rtx x, int verbose) 1629 { 1630 char tmp[1024]; 1631 1632 if (!x) 1633 { 1634 pp_string (pp, "(nil)"); 1635 return; 1636 } 1637 switch (GET_CODE (x)) 1638 { 1639 case CONST_INT: 1640 pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX, 1641 (unsigned HOST_WIDE_INT) INTVAL (x)); 1642 break; 1643 1644 case CONST_WIDE_INT: 1645 { 1646 const char *sep = "<"; 1647 int i; 1648 for (i = CONST_WIDE_INT_NUNITS (x) - 1; i >= 0; i--) 1649 { 1650 pp_string (pp, sep); 1651 sep = ","; 1652 sprintf (tmp, HOST_WIDE_INT_PRINT_HEX, 1653 (unsigned HOST_WIDE_INT) CONST_WIDE_INT_ELT (x, i)); 1654 pp_string (pp, tmp); 1655 } 1656 pp_greater (pp); 1657 } 1658 break; 1659 1660 case CONST_POLY_INT: 1661 pp_left_bracket (pp); 1662 pp_wide_int (pp, CONST_POLY_INT_COEFFS (x)[0], SIGNED); 1663 for (unsigned int i = 1; i < NUM_POLY_INT_COEFFS; ++i) 1664 { 1665 pp_string (pp, ", "); 1666 pp_wide_int (pp, CONST_POLY_INT_COEFFS (x)[i], SIGNED); 1667 } 1668 pp_right_bracket (pp); 1669 break; 1670 1671 case CONST_DOUBLE: 1672 if (FLOAT_MODE_P (GET_MODE (x))) 1673 { 1674 real_to_decimal (tmp, CONST_DOUBLE_REAL_VALUE (x), 1675 sizeof (tmp), 0, 1); 1676 pp_string (pp, tmp); 1677 } 1678 else 1679 pp_printf (pp, "<%wx,%wx>", 1680 (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x), 1681 (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (x)); 1682 break; 1683 case CONST_FIXED: 1684 fixed_to_decimal (tmp, CONST_FIXED_VALUE (x), sizeof (tmp)); 1685 pp_string (pp, tmp); 1686 break; 1687 case CONST_STRING: 1688 pp_string (pp, "\""); 1689 pretty_print_string (pp, XSTR (x, 0), strlen (XSTR (x, 0))); 1690 pp_string (pp, "\""); 1691 break; 1692 case SYMBOL_REF: 1693 pp_printf (pp, "`%s'", XSTR (x, 0)); 1694 break; 1695 case LABEL_REF: 1696 pp_printf (pp, "L%d", INSN_UID (label_ref_label (x))); 1697 break; 1698 case CONST: 1699 case HIGH: 1700 case STRICT_LOW_PART: 1701 pp_printf (pp, "%s(", GET_RTX_NAME (GET_CODE (x))); 1702 print_value (pp, XEXP (x, 0), verbose); 1703 pp_right_paren (pp); 1704 break; 1705 case REG: 1706 if (REGNO (x) < FIRST_PSEUDO_REGISTER) 1707 { 1708 if (ISDIGIT (reg_names[REGNO (x)][0])) 1709 pp_modulo (pp); 1710 pp_string (pp, reg_names[REGNO (x)]); 1711 } 1712 else 1713 pp_printf (pp, "r%d", REGNO (x)); 1714 if (verbose) 1715 pp_printf (pp, ":%s", GET_MODE_NAME (GET_MODE (x))); 1716 break; 1717 case SUBREG: 1718 print_value (pp, SUBREG_REG (x), verbose); 1719 pp_printf (pp, "#"); 1720 pp_wide_integer (pp, SUBREG_BYTE (x)); 1721 break; 1722 case SCRATCH: 1723 case CC0: 1724 case PC: 1725 pp_string (pp, GET_RTX_NAME (GET_CODE (x))); 1726 break; 1727 case MEM: 1728 pp_left_bracket (pp); 1729 print_value (pp, XEXP (x, 0), verbose); 1730 pp_right_bracket (pp); 1731 break; 1732 case DEBUG_EXPR: 1733 pp_printf (pp, "D#%i", DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x))); 1734 break; 1735 default: 1736 print_exp (pp, x, verbose); 1737 break; 1738 } 1739 } /* print_value */ 1740 1741 /* The next step in insn detalization, its pattern recognition. */ 1742 1743 void 1744 print_pattern (pretty_printer *pp, const_rtx x, int verbose) 1745 { 1746 if (! x) 1747 { 1748 pp_string (pp, "(nil)"); 1749 return; 1750 } 1751 1752 switch (GET_CODE (x)) 1753 { 1754 case SET: 1755 print_value (pp, SET_DEST (x), verbose); 1756 pp_equal (pp); 1757 print_value (pp, SET_SRC (x), verbose); 1758 break; 1759 case RETURN: 1760 case SIMPLE_RETURN: 1761 case EH_RETURN: 1762 pp_string (pp, GET_RTX_NAME (GET_CODE (x))); 1763 break; 1764 case CALL: 1765 print_exp (pp, x, verbose); 1766 break; 1767 case CLOBBER: 1768 case USE: 1769 pp_printf (pp, "%s ", GET_RTX_NAME (GET_CODE (x))); 1770 print_value (pp, XEXP (x, 0), verbose); 1771 break; 1772 case VAR_LOCATION: 1773 pp_string (pp, "loc "); 1774 print_value (pp, PAT_VAR_LOCATION_LOC (x), verbose); 1775 break; 1776 case COND_EXEC: 1777 pp_left_paren (pp); 1778 if (GET_CODE (COND_EXEC_TEST (x)) == NE 1779 && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx) 1780 print_value (pp, XEXP (COND_EXEC_TEST (x), 0), verbose); 1781 else if (GET_CODE (COND_EXEC_TEST (x)) == EQ 1782 && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx) 1783 { 1784 pp_exclamation (pp); 1785 print_value (pp, XEXP (COND_EXEC_TEST (x), 0), verbose); 1786 } 1787 else 1788 print_value (pp, COND_EXEC_TEST (x), verbose); 1789 pp_string (pp, ") "); 1790 print_pattern (pp, COND_EXEC_CODE (x), verbose); 1791 break; 1792 case PARALLEL: 1793 { 1794 int i; 1795 1796 pp_left_brace (pp); 1797 for (i = 0; i < XVECLEN (x, 0); i++) 1798 { 1799 print_pattern (pp, XVECEXP (x, 0, i), verbose); 1800 pp_semicolon (pp); 1801 } 1802 pp_right_brace (pp); 1803 } 1804 break; 1805 case SEQUENCE: 1806 { 1807 const rtx_sequence *seq = as_a <const rtx_sequence *> (x); 1808 pp_string (pp, "sequence{"); 1809 if (INSN_P (seq->element (0))) 1810 { 1811 /* Print the sequence insns indented. */ 1812 const char * save_print_rtx_head = print_rtx_head; 1813 char indented_print_rtx_head[32]; 1814 1815 pp_newline (pp); 1816 gcc_assert (strlen (print_rtx_head) < sizeof (indented_print_rtx_head) - 4); 1817 snprintf (indented_print_rtx_head, 1818 sizeof (indented_print_rtx_head), 1819 "%s ", print_rtx_head); 1820 print_rtx_head = indented_print_rtx_head; 1821 for (int i = 0; i < seq->len (); i++) 1822 print_insn_with_notes (pp, seq->insn (i)); 1823 pp_printf (pp, "%s ", save_print_rtx_head); 1824 print_rtx_head = save_print_rtx_head; 1825 } 1826 else 1827 { 1828 for (int i = 0; i < seq->len (); i++) 1829 { 1830 print_pattern (pp, seq->element (i), verbose); 1831 pp_semicolon (pp); 1832 } 1833 } 1834 pp_right_brace (pp); 1835 } 1836 break; 1837 case ASM_INPUT: 1838 pp_printf (pp, "asm {%s}", XSTR (x, 0)); 1839 break; 1840 case ADDR_VEC: 1841 for (int i = 0; i < XVECLEN (x, 0); i++) 1842 { 1843 print_value (pp, XVECEXP (x, 0, i), verbose); 1844 pp_semicolon (pp); 1845 } 1846 break; 1847 case ADDR_DIFF_VEC: 1848 for (int i = 0; i < XVECLEN (x, 1); i++) 1849 { 1850 print_value (pp, XVECEXP (x, 1, i), verbose); 1851 pp_semicolon (pp); 1852 } 1853 break; 1854 case TRAP_IF: 1855 pp_string (pp, "trap_if "); 1856 print_value (pp, TRAP_CONDITION (x), verbose); 1857 break; 1858 case UNSPEC: 1859 case UNSPEC_VOLATILE: 1860 /* Fallthru -- leave UNSPECs to print_exp. */ 1861 default: 1862 print_value (pp, x, verbose); 1863 } 1864 } /* print_pattern */ 1865 1866 /* This is the main function in slim rtl visualization mechanism. 1867 1868 X is an insn, to be printed into PP. 1869 1870 This function tries to print it properly in human-readable form, 1871 resembling assembler mnemonics (instead of the older Lisp-style 1872 form). 1873 1874 If VERBOSE is TRUE, insns are printed with more complete (but 1875 longer) pattern names and with extra information, and prefixed 1876 with their INSN_UIDs. */ 1877 1878 void 1879 print_insn (pretty_printer *pp, const rtx_insn *x, int verbose) 1880 { 1881 if (verbose) 1882 { 1883 /* Blech, pretty-print can't print integers with a specified width. */ 1884 char uid_prefix[32]; 1885 snprintf (uid_prefix, sizeof uid_prefix, " %4d: ", INSN_UID (x)); 1886 pp_string (pp, uid_prefix); 1887 } 1888 1889 switch (GET_CODE (x)) 1890 { 1891 case INSN: 1892 print_pattern (pp, PATTERN (x), verbose); 1893 break; 1894 1895 case DEBUG_INSN: 1896 { 1897 if (DEBUG_MARKER_INSN_P (x)) 1898 { 1899 switch (INSN_DEBUG_MARKER_KIND (x)) 1900 { 1901 case NOTE_INSN_BEGIN_STMT: 1902 pp_string (pp, "debug begin stmt marker"); 1903 break; 1904 1905 case NOTE_INSN_INLINE_ENTRY: 1906 pp_string (pp, "debug inline entry marker"); 1907 break; 1908 1909 default: 1910 gcc_unreachable (); 1911 } 1912 break; 1913 } 1914 1915 const char *name = "?"; 1916 char idbuf[32]; 1917 1918 if (DECL_P (INSN_VAR_LOCATION_DECL (x))) 1919 { 1920 tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (x)); 1921 if (id) 1922 name = IDENTIFIER_POINTER (id); 1923 else if (TREE_CODE (INSN_VAR_LOCATION_DECL (x)) 1924 == DEBUG_EXPR_DECL) 1925 { 1926 sprintf (idbuf, "D#%i", 1927 DEBUG_TEMP_UID (INSN_VAR_LOCATION_DECL (x))); 1928 name = idbuf; 1929 } 1930 else 1931 { 1932 sprintf (idbuf, "D.%i", 1933 DECL_UID (INSN_VAR_LOCATION_DECL (x))); 1934 name = idbuf; 1935 } 1936 } 1937 pp_printf (pp, "debug %s => ", name); 1938 if (VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (x))) 1939 pp_string (pp, "optimized away"); 1940 else 1941 print_pattern (pp, INSN_VAR_LOCATION_LOC (x), verbose); 1942 } 1943 break; 1944 1945 case JUMP_INSN: 1946 print_pattern (pp, PATTERN (x), verbose); 1947 break; 1948 case CALL_INSN: 1949 if (GET_CODE (PATTERN (x)) == PARALLEL) 1950 print_pattern (pp, XVECEXP (PATTERN (x), 0, 0), verbose); 1951 else 1952 print_pattern (pp, PATTERN (x), verbose); 1953 break; 1954 case CODE_LABEL: 1955 pp_printf (pp, "L%d:", INSN_UID (x)); 1956 break; 1957 case JUMP_TABLE_DATA: 1958 pp_string (pp, "jump_table_data{\n"); 1959 print_pattern (pp, PATTERN (x), verbose); 1960 pp_right_brace (pp); 1961 break; 1962 case BARRIER: 1963 pp_string (pp, "barrier"); 1964 break; 1965 case NOTE: 1966 { 1967 pp_string (pp, GET_NOTE_INSN_NAME (NOTE_KIND (x))); 1968 switch (NOTE_KIND (x)) 1969 { 1970 case NOTE_INSN_EH_REGION_BEG: 1971 case NOTE_INSN_EH_REGION_END: 1972 pp_printf (pp, " %d", NOTE_EH_HANDLER (x)); 1973 break; 1974 1975 case NOTE_INSN_BLOCK_BEG: 1976 case NOTE_INSN_BLOCK_END: 1977 pp_printf (pp, " %d", BLOCK_NUMBER (NOTE_BLOCK (x))); 1978 break; 1979 1980 case NOTE_INSN_BASIC_BLOCK: 1981 pp_printf (pp, " %d", NOTE_BASIC_BLOCK (x)->index); 1982 break; 1983 1984 case NOTE_INSN_DELETED_LABEL: 1985 case NOTE_INSN_DELETED_DEBUG_LABEL: 1986 { 1987 const char *label = NOTE_DELETED_LABEL_NAME (x); 1988 if (label == NULL) 1989 label = ""; 1990 pp_printf (pp, " (\"%s\")", label); 1991 } 1992 break; 1993 1994 case NOTE_INSN_VAR_LOCATION: 1995 pp_left_brace (pp); 1996 print_pattern (pp, NOTE_VAR_LOCATION (x), verbose); 1997 pp_right_brace (pp); 1998 break; 1999 2000 default: 2001 break; 2002 } 2003 break; 2004 } 2005 default: 2006 gcc_unreachable (); 2007 } 2008 } /* print_insn */ 2009 2010 /* Pretty-print a slim dump of X (an insn) to PP, including any register 2011 note attached to the instruction. */ 2012 2013 static void 2014 print_insn_with_notes (pretty_printer *pp, const rtx_insn *x) 2015 { 2016 pp_string (pp, print_rtx_head); 2017 print_insn (pp, x, 1); 2018 pp_newline (pp); 2019 if (INSN_P (x) && REG_NOTES (x)) 2020 for (rtx note = REG_NOTES (x); note; note = XEXP (note, 1)) 2021 { 2022 pp_printf (pp, "%s %s ", print_rtx_head, 2023 GET_REG_NOTE_NAME (REG_NOTE_KIND (note))); 2024 if (GET_CODE (note) == INT_LIST) 2025 pp_printf (pp, "%d", XINT (note, 0)); 2026 else 2027 print_pattern (pp, XEXP (note, 0), 1); 2028 pp_newline (pp); 2029 } 2030 } 2031 2032 /* Print X, an RTL value node, to file F in slim format. Include 2033 additional information if VERBOSE is nonzero. 2034 2035 Value nodes are constants, registers, labels, symbols and 2036 memory. */ 2037 2038 void 2039 dump_value_slim (FILE *f, const_rtx x, int verbose) 2040 { 2041 pretty_printer rtl_slim_pp; 2042 rtl_slim_pp.buffer->stream = f; 2043 print_value (&rtl_slim_pp, x, verbose); 2044 pp_flush (&rtl_slim_pp); 2045 } 2046 2047 /* Emit a slim dump of X (an insn) to the file F, including any register 2048 note attached to the instruction. */ 2049 void 2050 dump_insn_slim (FILE *f, const rtx_insn *x) 2051 { 2052 pretty_printer rtl_slim_pp; 2053 rtl_slim_pp.buffer->stream = f; 2054 print_insn_with_notes (&rtl_slim_pp, x); 2055 pp_flush (&rtl_slim_pp); 2056 } 2057 2058 /* Same as above, but stop at LAST or when COUNT == 0. 2059 If COUNT < 0 it will stop only at LAST or NULL rtx. */ 2060 2061 void 2062 dump_rtl_slim (FILE *f, const rtx_insn *first, const rtx_insn *last, 2063 int count, int flags ATTRIBUTE_UNUSED) 2064 { 2065 const rtx_insn *insn, *tail; 2066 pretty_printer rtl_slim_pp; 2067 rtl_slim_pp.buffer->stream = f; 2068 2069 tail = last ? NEXT_INSN (last) : NULL; 2070 for (insn = first; 2071 (insn != NULL) && (insn != tail) && (count != 0); 2072 insn = NEXT_INSN (insn)) 2073 { 2074 print_insn_with_notes (&rtl_slim_pp, insn); 2075 if (count > 0) 2076 count--; 2077 } 2078 2079 pp_flush (&rtl_slim_pp); 2080 } 2081 2082 /* Dumps basic block BB to pretty-printer PP in slim form and without and 2083 no indentation, for use as a label of a DOT graph record-node. */ 2084 2085 void 2086 rtl_dump_bb_for_graph (pretty_printer *pp, basic_block bb) 2087 { 2088 rtx_insn *insn; 2089 bool first = true; 2090 2091 /* TODO: inter-bb stuff. */ 2092 FOR_BB_INSNS (bb, insn) 2093 { 2094 if (! first) 2095 { 2096 pp_bar (pp); 2097 pp_write_text_to_stream (pp); 2098 } 2099 first = false; 2100 print_insn_with_notes (pp, insn); 2101 pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true); 2102 } 2103 } 2104 2105 /* Pretty-print pattern X of some insn in non-verbose mode. 2106 Return a string pointer to the pretty-printer buffer. 2107 2108 This function is only exported exists only to accommodate some older users 2109 of the slim RTL pretty printers. Please do not use it for new code. */ 2110 2111 const char * 2112 str_pattern_slim (const_rtx x) 2113 { 2114 pretty_printer rtl_slim_pp; 2115 print_pattern (&rtl_slim_pp, x, 0); 2116 return ggc_strdup (pp_formatted_text (&rtl_slim_pp)); 2117 } 2118 2119 /* Emit a slim dump of X (an insn) to stderr. */ 2120 extern void debug_insn_slim (const rtx_insn *); 2121 DEBUG_FUNCTION void 2122 debug_insn_slim (const rtx_insn *x) 2123 { 2124 dump_insn_slim (stderr, x); 2125 } 2126 2127 /* Same as above, but using dump_rtl_slim. */ 2128 extern void debug_rtl_slim (FILE *, const rtx_insn *, const rtx_insn *, 2129 int, int); 2130 DEBUG_FUNCTION void 2131 debug_rtl_slim (const rtx_insn *first, const rtx_insn *last, int count, 2132 int flags) 2133 { 2134 dump_rtl_slim (stderr, first, last, count, flags); 2135 } 2136 2137 extern void debug_bb_slim (basic_block); 2138 DEBUG_FUNCTION void 2139 debug_bb_slim (basic_block bb) 2140 { 2141 dump_bb (stderr, bb, 0, TDF_SLIM | TDF_BLOCKS); 2142 } 2143 2144 extern void debug_bb_n_slim (int); 2145 DEBUG_FUNCTION void 2146 debug_bb_n_slim (int n) 2147 { 2148 basic_block bb = BASIC_BLOCK_FOR_FN (cfun, n); 2149 debug_bb_slim (bb); 2150 } 2151 2152 #endif 2153 2154 #if __GNUC__ >= 10 2155 # pragma GCC diagnostic pop 2156 #endif 2157