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