sched-vis.c 22 KB
Newer Older
1
/* Printing of RTL in "slim", mnemonic like form.
2
   Copyright (C) 1992-2013 Free Software Foundation, Inc.
3 4 5
   Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
   and currently maintained by, Jim Wilson (wilson@cygnus.com)

6
This file is part of GCC.
7

8 9
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
10
Software Foundation; either version 3, or (at your option) any later
11
version.
12

13 14
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 16 17 18
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
19 20
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
21 22 23 24

/* Historically this form of RTL dumping was introduced along with
   the Haifa instruction scheduling pass, hence the name of this file.
   But there is nothing in this file left that is scheduler-specific.  */
25 26 27

#include "config.h"
#include "system.h"
28 29
#include "coretypes.h"
#include "tm.h"
30
#include "rtl.h"
31
#include "tree.h"	/* FIXME: To dump INSN_VAR_LOCATION_DECL.  */
32
#include "basic-block.h"
33
#include "dumpfile.h"	/* for the TDF_* flags */
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
#include "pretty-print.h"

/* The functions in this file try to print RTL in a form resembling assembler
   mnemonics.  Because this form is more concise than the "traditional" form
   of RTL printing in Lisp-style, the form printed by this file is called
   "slim".  RTL dumps in slim format can be obtained by appending the "-slim"
   option to -fdump-rtl-<pass>.  Control flow graph output as a DOT file is
   always printed in slim form.

   The normal interface to the functionality provided in this pretty-printer
   is through the dump_*_slim functions to print to a stream, or via the
   print_*_slim functions to print into a user's pretty-printer.
   
   It is also possible to obtain a string for a single pattern as a string
   pointer, via str_pattern_slim, but this usage is discouraged.  */

/* A pretty-printer for slim rtl printing.  */
static bool rtl_slim_pp_initialized = false;
static pretty_printer rtl_slim_pp;

54 55 56
/* For insns we print patterns, and for some patterns we print insns...  */
static void print_insn_with_notes (pretty_printer *, const_rtx);

57
/* This recognizes rtx'en classified as expressions.  These are always
58 59 60 61
   represent some action on values or results of other expression, that
   may be stored in objects representing values.  */

static void
62
print_exp (pretty_printer *pp, const_rtx x, int verbose)
63 64
{
  const char *st[4];
65
  const char *fun;
66 67 68
  rtx op[4];
  int i;

69
  fun = (char *) 0;
70 71 72 73 74 75 76 77 78 79
  for (i = 0; i < 4; i++)
    {
      st[i] = (char *) 0;
      op[i] = NULL_RTX;
    }

  switch (GET_CODE (x))
    {
    case PLUS:
      op[0] = XEXP (x, 0);
Shujing Zhao committed
80
      if (CONST_INT_P (XEXP (x, 1))
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
	  && INTVAL (XEXP (x, 1)) < 0)
	{
	  st[1] = "-";
	  op[1] = GEN_INT (-INTVAL (XEXP (x, 1)));
	}
      else
	{
	  st[1] = "+";
	  op[1] = XEXP (x, 1);
	}
      break;
    case LO_SUM:
      op[0] = XEXP (x, 0);
      st[1] = "+low(";
      op[1] = XEXP (x, 1);
      st[2] = ")";
      break;
    case MINUS:
      op[0] = XEXP (x, 0);
      st[1] = "-";
      op[1] = XEXP (x, 1);
      break;
    case COMPARE:
      fun = "cmp";
      op[0] = XEXP (x, 0);
      op[1] = XEXP (x, 1);
      break;
    case NEG:
      st[0] = "-";
      op[0] = XEXP (x, 0);
      break;
112 113 114 115 116 117 118 119 120
    case FMA:
      st[0] = "{";
      op[0] = XEXP (x, 0);
      st[1] = "*";
      op[1] = XEXP (x, 1);
      st[2] = "+";
      op[2] = XEXP (x, 2);
      st[3] = "}";
      break;
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
    case MULT:
      op[0] = XEXP (x, 0);
      st[1] = "*";
      op[1] = XEXP (x, 1);
      break;
    case DIV:
      op[0] = XEXP (x, 0);
      st[1] = "/";
      op[1] = XEXP (x, 1);
      break;
    case UDIV:
      fun = "udiv";
      op[0] = XEXP (x, 0);
      op[1] = XEXP (x, 1);
      break;
    case MOD:
      op[0] = XEXP (x, 0);
      st[1] = "%";
      op[1] = XEXP (x, 1);
      break;
    case UMOD:
      fun = "umod";
      op[0] = XEXP (x, 0);
      op[1] = XEXP (x, 1);
      break;
    case SMIN:
      fun = "smin";
      op[0] = XEXP (x, 0);
      op[1] = XEXP (x, 1);
      break;
    case SMAX:
      fun = "smax";
      op[0] = XEXP (x, 0);
      op[1] = XEXP (x, 1);
      break;
    case UMIN:
      fun = "umin";
      op[0] = XEXP (x, 0);
      op[1] = XEXP (x, 1);
      break;
    case UMAX:
      fun = "umax";
      op[0] = XEXP (x, 0);
      op[1] = XEXP (x, 1);
      break;
    case NOT:
      st[0] = "!";
      op[0] = XEXP (x, 0);
      break;
    case AND:
      op[0] = XEXP (x, 0);
      st[1] = "&";
      op[1] = XEXP (x, 1);
      break;
    case IOR:
      op[0] = XEXP (x, 0);
      st[1] = "|";
      op[1] = XEXP (x, 1);
      break;
    case XOR:
      op[0] = XEXP (x, 0);
      st[1] = "^";
      op[1] = XEXP (x, 1);
      break;
    case ASHIFT:
      op[0] = XEXP (x, 0);
      st[1] = "<<";
      op[1] = XEXP (x, 1);
      break;
    case LSHIFTRT:
      op[0] = XEXP (x, 0);
      st[1] = " 0>>";
      op[1] = XEXP (x, 1);
      break;
    case ASHIFTRT:
      op[0] = XEXP (x, 0);
      st[1] = ">>";
      op[1] = XEXP (x, 1);
      break;
    case ROTATE:
      op[0] = XEXP (x, 0);
      st[1] = "<-<";
      op[1] = XEXP (x, 1);
      break;
    case ROTATERT:
      op[0] = XEXP (x, 0);
      st[1] = ">->";
      op[1] = XEXP (x, 1);
      break;
    case NE:
      op[0] = XEXP (x, 0);
      st[1] = "!=";
      op[1] = XEXP (x, 1);
      break;
215
    case EQ:
216
      op[0] = XEXP (x, 0);
217
      st[1] = "==";
218 219 220 221 222 223 224
      op[1] = XEXP (x, 1);
      break;
    case GE:
      op[0] = XEXP (x, 0);
      st[1] = ">=";
      op[1] = XEXP (x, 1);
      break;
225
    case GT:
226
      op[0] = XEXP (x, 0);
227
      st[1] = ">";
228 229 230 231 232 233 234
      op[1] = XEXP (x, 1);
      break;
    case LE:
      op[0] = XEXP (x, 0);
      st[1] = "<=";
      op[1] = XEXP (x, 1);
      break;
235
    case LT:
236
      op[0] = XEXP (x, 0);
237
      st[1] = "<";
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
      op[1] = XEXP (x, 1);
      break;
    case SIGN_EXTRACT:
      fun = (verbose) ? "sign_extract" : "sxt";
      op[0] = XEXP (x, 0);
      op[1] = XEXP (x, 1);
      op[2] = XEXP (x, 2);
      break;
    case ZERO_EXTRACT:
      fun = (verbose) ? "zero_extract" : "zxt";
      op[0] = XEXP (x, 0);
      op[1] = XEXP (x, 1);
      op[2] = XEXP (x, 2);
      break;
    case SIGN_EXTEND:
      fun = (verbose) ? "sign_extend" : "sxn";
      op[0] = XEXP (x, 0);
      break;
    case ZERO_EXTEND:
      fun = (verbose) ? "zero_extend" : "zxn";
      op[0] = XEXP (x, 0);
      break;
    case FLOAT_EXTEND:
      fun = (verbose) ? "float_extend" : "fxn";
      op[0] = XEXP (x, 0);
      break;
    case TRUNCATE:
      fun = (verbose) ? "trunc" : "trn";
      op[0] = XEXP (x, 0);
      break;
    case FLOAT_TRUNCATE:
      fun = (verbose) ? "float_trunc" : "ftr";
      op[0] = XEXP (x, 0);
      break;
    case FLOAT:
      fun = (verbose) ? "float" : "flt";
      op[0] = XEXP (x, 0);
      break;
    case UNSIGNED_FLOAT:
      fun = (verbose) ? "uns_float" : "ufl";
      op[0] = XEXP (x, 0);
      break;
    case FIX:
      fun = "fix";
      op[0] = XEXP (x, 0);
      break;
    case UNSIGNED_FIX:
      fun = (verbose) ? "uns_fix" : "ufx";
      op[0] = XEXP (x, 0);
      break;
    case PRE_DEC:
      st[0] = "--";
      op[0] = XEXP (x, 0);
      break;
    case PRE_INC:
      st[0] = "++";
      op[0] = XEXP (x, 0);
      break;
    case POST_DEC:
      op[0] = XEXP (x, 0);
      st[1] = "--";
      break;
    case POST_INC:
      op[0] = XEXP (x, 0);
      st[1] = "++";
      break;
304 305 306 307 308 309 310 311 312 313 314 315
    case PRE_MODIFY:
      st[0] = "pre ";
      op[0] = XEXP (XEXP (x, 1), 0);
      st[1] = "+=";
      op[1] = XEXP (XEXP (x, 1), 1);
      break;
    case POST_MODIFY:
      st[0] = "post ";
      op[0] = XEXP (XEXP (x, 1), 0);
      st[1] = "+=";
      op[1] = XEXP (XEXP (x, 1), 1);
      break;
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
    case CALL:
      st[0] = "call ";
      op[0] = XEXP (x, 0);
      if (verbose)
	{
	  st[1] = " argc:";
	  op[1] = XEXP (x, 1);
	}
      break;
    case IF_THEN_ELSE:
      st[0] = "{(";
      op[0] = XEXP (x, 0);
      st[1] = ")?";
      op[1] = XEXP (x, 1);
      st[2] = ":";
      op[2] = XEXP (x, 2);
      st[3] = "}";
      break;
    case TRAP_IF:
      fun = "trap_if";
      op[0] = TRAP_CONDITION (x);
      break;
338 339 340 341 342 343
    case PREFETCH:
      fun = "prefetch";
      op[0] = XEXP (x, 0);
      op[1] = XEXP (x, 1);
      op[2] = XEXP (x, 2);
      break;
344 345 346
    case UNSPEC:
    case UNSPEC_VOLATILE:
      {
347
	pp_string (pp, "unspec");
348
	if (GET_CODE (x) == UNSPEC_VOLATILE)
349 350
	  pp_string (pp, "/v");
	pp_character (pp, '[');
351 352
	for (i = 0; i < XVECLEN (x, 0); i++)
	  {
353 354 355
	    if (i != 0)
	      pp_character (pp, ',');
	    print_pattern (pp, XVECEXP (x, 0, i), verbose);
356
	  }
357 358
	pp_string (pp, "] ");
	pp_decimal_int (pp, XINT (x, 1));
359 360 361
      }
      break;
    default:
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
      {
	/* Most unhandled codes can be printed as pseudo-functions.  */
        if (GET_RTX_CLASS (GET_CODE (x)) == RTX_UNARY)
	  {
	    fun = GET_RTX_NAME (GET_CODE (x));
	    op[0] = XEXP (x, 0);
	  }
        else if (GET_RTX_CLASS (GET_CODE (x)) == RTX_COMPARE
		 || GET_RTX_CLASS (GET_CODE (x)) == RTX_COMM_COMPARE
		 || GET_RTX_CLASS (GET_CODE (x)) == RTX_BIN_ARITH
		 || GET_RTX_CLASS (GET_CODE (x)) == RTX_COMM_ARITH)
	  {
	    fun = GET_RTX_NAME (GET_CODE (x));
	    op[0] = XEXP (x, 0);
	    op[1] = XEXP (x, 1);
	  }
        else if (GET_RTX_CLASS (GET_CODE (x)) == RTX_TERNARY)
	  {
	    fun = GET_RTX_NAME (GET_CODE (x));
	    op[0] = XEXP (x, 0);
	    op[1] = XEXP (x, 1);
	    op[2] = XEXP (x, 2);
	  }
	else
	  /* Give up, just print the RTX name.  */
	  st[0] = GET_RTX_NAME (GET_CODE (x));
      }
389 390 391 392 393 394
      break;
    }

  /* Print this as a function?  */
  if (fun)
    {
395 396
      pp_string (pp, fun);
      pp_character (pp, '(');
397 398 399 400 401
    }

  for (i = 0; i < 4; i++)
    {
      if (st[i])
402
        pp_string (pp, st[i]);
403 404 405 406

      if (op[i])
	{
	  if (fun && i != 0)
407 408
	    pp_character (pp, ',');
	  print_value (pp, op[i], verbose);
409 410 411 412
	}
    }

  if (fun)
413
    pp_character (pp, ')');
414 415
}		/* print_exp */

416
/* Prints rtxes, I customarily classified as values.  They're constants,
417 418
   registers, labels, symbols and memory accesses.  */

419
void
420
print_value (pretty_printer *pp, const_rtx x, int verbose)
421
{
422
  char tmp[1024];
423

424 425
  if (!x)
    {
426
      pp_string (pp, "(nil)");
427 428
      return;
    }
429 430 431
  switch (GET_CODE (x))
    {
    case CONST_INT:
432 433
      pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
		 (unsigned HOST_WIDE_INT) INTVAL (x));
434 435
      break;
    case CONST_DOUBLE:
436
      if (FLOAT_MODE_P (GET_MODE (x)))
437 438 439 440 441
	{
	  real_to_decimal (tmp, CONST_DOUBLE_REAL_VALUE (x),
			   sizeof (tmp), 0, 1);
	  pp_string (pp, tmp);
	}
442
      else
443 444 445
	pp_printf (pp, "<%wx,%wx>",
		   (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x),
		   (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (x));
446
      break;
447
    case CONST_FIXED:
448 449
      fixed_to_decimal (tmp, CONST_FIXED_VALUE (x), sizeof (tmp));
      pp_string (pp, tmp);
450
      break;
451
    case CONST_STRING:
452
      pp_printf (pp, "\"%s\"", XSTR (x, 0));
453 454
      break;
    case SYMBOL_REF:
455
      pp_printf (pp, "`%s'", XSTR (x, 0));
456 457
      break;
    case LABEL_REF:
458
      pp_printf (pp, "L%d", INSN_UID (XEXP (x, 0)));
459 460 461
      break;
    case CONST:
    case HIGH:
462 463 464 465
    case STRICT_LOW_PART:
      pp_printf (pp, "%s(", GET_RTX_NAME (GET_CODE (x)));
      print_value (pp, XEXP (x, 0), verbose);
      pp_character (pp, ')');
466 467 468 469
      break;
    case REG:
      if (REGNO (x) < FIRST_PSEUDO_REGISTER)
	{
470 471 472
	  if (ISDIGIT (reg_names[REGNO (x)][0]))
	    pp_character (pp, '%');
	  pp_string (pp, reg_names[REGNO (x)]);
473 474
	}
      else
475
	pp_printf (pp, "r%d", REGNO (x));
476
      if (verbose)
477
	pp_printf (pp, ":%s", GET_MODE_NAME (GET_MODE (x)));
478 479
      break;
    case SUBREG:
480 481
      print_value (pp, SUBREG_REG (x), verbose);
      pp_printf (pp, "#%d", SUBREG_BYTE (x));
482
      break;
483 484 485
    case SCRATCH:
    case CC0:
    case PC:
486
      pp_string (pp, GET_RTX_NAME (GET_CODE (x)));
487 488
      break;
    case MEM:
489 490 491
      pp_character (pp, '[');
      print_value (pp, XEXP (x, 0), verbose);
      pp_character (pp, ']');
492
      break;
493
    case DEBUG_EXPR:
494
      pp_printf (pp, "D#%i", DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x)));
495
      break;
496
    default:
497
      print_exp (pp, x, verbose);
498 499 500 501 502 503
      break;
    }
}				/* print_value */

/* The next step in insn detalization, its pattern recognition.  */

504
void
505
print_pattern (pretty_printer *pp, const_rtx x, int verbose)
506
{
507 508
  if (! x)
    {
509
      pp_string (pp, "(nil)");
510 511 512
      return;
    }

513 514 515
  switch (GET_CODE (x))
    {
    case SET:
516 517 518
      print_value (pp, SET_DEST (x), verbose);
      pp_character (pp, '=');
      print_value (pp, SET_SRC (x), verbose);
519 520
      break;
    case RETURN:
521
    case SIMPLE_RETURN:
522
    case EH_RETURN:
523
      pp_string (pp, GET_RTX_NAME (GET_CODE (x)));
524
      break;
525
    case CALL:
526
      print_exp (pp, x, verbose);
527 528 529
      break;
    case CLOBBER:
    case USE:
530 531
      pp_printf (pp, "%s ", GET_RTX_NAME (GET_CODE (x)));
      print_value (pp, XEXP (x, 0), verbose);
532
      break;
533
    case VAR_LOCATION:
534 535
      pp_string (pp, "loc ");
      print_value (pp, PAT_VAR_LOCATION_LOC (x), verbose);
536
      break;
537
    case COND_EXEC:
538
      pp_character (pp, '(');
539 540
      if (GET_CODE (COND_EXEC_TEST (x)) == NE
	  && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
541
	print_value (pp, XEXP (COND_EXEC_TEST (x), 0), verbose);
542
      else if (GET_CODE (COND_EXEC_TEST (x)) == EQ
Kazu Hirata committed
543 544
	       && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
	{
545 546
	  pp_character (pp, '!');
	  print_value (pp, XEXP (COND_EXEC_TEST (x), 0), verbose);
547 548
	}
      else
549 550 551
	print_value (pp, COND_EXEC_TEST (x), verbose);
      pp_string (pp, ") ");
      print_pattern (pp, COND_EXEC_CODE (x), verbose);
552 553 554 555 556
      break;
    case PARALLEL:
      {
	int i;

557
	pp_character (pp, '{');
558 559
	for (i = 0; i < XVECLEN (x, 0); i++)
	  {
560 561
	    print_pattern (pp, XVECEXP (x, 0, i), verbose);
	    pp_character (pp, ';');
562
	  }
563
	pp_character (pp, '}');
564 565 566
      }
      break;
    case SEQUENCE:
567
      {
568
	pp_string (pp, "sequence{");
569
	if (INSN_P (XVECEXP (x, 0, 0)))
570
	  {
571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
	    /* Print the sequence insns indented.  */
	    const char * save_print_rtx_head = print_rtx_head;
	    char indented_print_rtx_head[32];

	    pp_newline (pp);
	    gcc_assert (strlen (print_rtx_head) < sizeof (indented_print_rtx_head) - 4);
	    snprintf (indented_print_rtx_head,
		      sizeof (indented_print_rtx_head),
		      "%s     ", print_rtx_head);
	    print_rtx_head = indented_print_rtx_head;
	    for (int i = 0; i < XVECLEN (x, 0); i++)
	      print_insn_with_notes (pp, XVECEXP (x, 0, i));
	    pp_printf (pp, "%s      ", save_print_rtx_head);
	    print_rtx_head = save_print_rtx_head;
	  }
	else
	  {
	    for (int i = 0; i < XVECLEN (x, 0); i++)
	      {
		print_pattern (pp, XVECEXP (x, 0, i), verbose);
		pp_character (pp, ';');
	      }
593
	  }
594
	pp_character (pp, '}');
595 596
      }
      break;
597
    case ASM_INPUT:
598
      pp_printf (pp, "asm {%s}", XSTR (x, 0));
599 600
      break;
    case ADDR_VEC:
601
      /* Fall through.  */
602
    case ADDR_DIFF_VEC:
603
      print_value (pp, XEXP (x, 0), verbose);
604 605
      break;
    case TRAP_IF:
606 607
      pp_string (pp, "trap_if ");
      print_value (pp, TRAP_CONDITION (x), verbose);
608 609 610
      break;
    case UNSPEC:
    case UNSPEC_VOLATILE:
611
      /* Fallthru -- leave UNSPECs to print_exp.  */
612
    default:
613
      print_value (pp, x, verbose);
614 615 616
    }
}				/* print_pattern */

617 618
/* This is the main function in slim rtl visualization mechanism.

619
   X is an insn, to be printed into PP.
620 621 622 623 624 625 626 627

   This function tries to print it properly in human-readable form,
   resembling assembler mnemonics (instead of the older Lisp-style
   form).

   If VERBOSE is TRUE, insns are printed with more complete (but
   longer) pattern names and with extra information, and prefixed
   with their INSN_UIDs.  */
628

629
void
630
print_insn (pretty_printer *pp, const_rtx x, int verbose)
631
{
632 633 634 635 636 637 638
  if (verbose)
    {
      /* Blech, pretty-print can't print integers with a specified width.  */
      char uid_prefix[32];
      snprintf (uid_prefix, sizeof uid_prefix, " %4d: ", INSN_UID (x));
      pp_string (pp, uid_prefix);
    }
639 640 641 642

  switch (GET_CODE (x))
    {
    case INSN:
643
      print_pattern (pp, PATTERN (x), verbose);
644
      break;
645 646 647 648 649

    case DEBUG_INSN:
      {
	const char *name = "?";

650
	if (DECL_P (INSN_VAR_LOCATION_DECL (x)))
651
	  {
652
	    tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (x));
653
	    char idbuf[32];
654 655
	    if (id)
	      name = IDENTIFIER_POINTER (id);
656
	    else if (TREE_CODE (INSN_VAR_LOCATION_DECL (x))
657 658 659
		     == DEBUG_EXPR_DECL)
	      {
		sprintf (idbuf, "D#%i",
660
			 DEBUG_TEMP_UID (INSN_VAR_LOCATION_DECL (x)));
661 662
		name = idbuf;
	      }
663 664 665
	    else
	      {
		sprintf (idbuf, "D.%i",
666
			 DECL_UID (INSN_VAR_LOCATION_DECL (x)));
667 668 669
		name = idbuf;
	      }
	  }
670
	pp_printf (pp, "debug %s => ", name);
671
	if (VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (x)))
672
	  pp_string (pp, "optimized away");
673
	else
674
	  print_pattern (pp, INSN_VAR_LOCATION_LOC (x), verbose);
675 676 677
      }
      break;

678
    case JUMP_INSN:
679
      print_pattern (pp, PATTERN (x), verbose);
680 681
      break;
    case CALL_INSN:
682
      if (GET_CODE (PATTERN (x)) == PARALLEL)
683
        print_pattern (pp, XVECEXP (PATTERN (x), 0, 0), verbose);
684
      else
685
	print_pattern (pp, PATTERN (x), verbose);
686 687
      break;
    case CODE_LABEL:
688
      pp_printf (pp, "L%d:", INSN_UID (x));
689
      break;
690 691 692 693 694
    case JUMP_TABLE_DATA:
      pp_string (pp, "jump_table_data{\n");
      print_pattern (pp, PATTERN (x), verbose);
      pp_string (pp, "}");
      break;
695
    case BARRIER:
696
      pp_string (pp, "barrier");
697 698
      break;
    case NOTE:
699
      {
700
	pp_string (pp, GET_NOTE_INSN_NAME (NOTE_KIND (x)));
701 702 703 704
	switch (NOTE_KIND (x))
	  {
	  case NOTE_INSN_EH_REGION_BEG:
	  case NOTE_INSN_EH_REGION_END:
705
	    pp_printf (pp, " %d", NOTE_EH_HANDLER (x));
706 707 708 709
	    break;

	  case NOTE_INSN_BLOCK_BEG:
	  case NOTE_INSN_BLOCK_END:
710
	    pp_printf (pp, " %d", BLOCK_NUMBER (NOTE_BLOCK (x)));
711 712 713
	    break;

	  case NOTE_INSN_BASIC_BLOCK:
714
	    pp_printf (pp, " %d", NOTE_BASIC_BLOCK (x)->index);
715 716 717 718 719 720 721 722
	    break;

	  case NOTE_INSN_DELETED_LABEL:
	  case NOTE_INSN_DELETED_DEBUG_LABEL:
	    {
	      const char *label = NOTE_DELETED_LABEL_NAME (x);
	      if (label == NULL)
		label = "";
723
	      pp_printf (pp, " (\"%s\")", label);
724 725 726 727
	    }
	    break;

	  case NOTE_INSN_VAR_LOCATION:
728
	  case NOTE_INSN_CALL_ARG_LOCATION:
729 730 731
	    pp_character (pp, '{');
	    print_pattern (pp, NOTE_VAR_LOCATION (x), verbose);
	    pp_character (pp, '}');
732 733 734 735 736 737 738
	    break;

	  default:
	    break;
	  }
	break;
      }
739
    default:
740
      gcc_unreachable ();
741
    }
742
}				/* print_insn */
743

744
/* Pretty-print a slim dump of X (an insn) to PP, including any register
745 746
   note attached to the instruction.  */

747
static void
748 749 750 751 752 753 754 755
print_insn_with_notes (pretty_printer *pp, const_rtx x)
{
  pp_string (pp, print_rtx_head);
  print_insn (pp, x, 1);
  pp_newline (pp);
  if (INSN_P (x) && REG_NOTES (x))
    for (rtx note = REG_NOTES (x); note; note = XEXP (note, 1))
      {
756
	pp_printf (pp, "%s      %s ", print_rtx_head,
757
		   GET_REG_NOTE_NAME (REG_NOTE_KIND (note)));
758
	print_pattern (pp, XEXP (note, 0), 1);
759 760 761 762 763 764 765 766 767 768 769 770 771 772
	pp_newline (pp);
      }
}

/* Return a pretty-print buffer set up to print to file F.  */

static pretty_printer *
init_rtl_slim_pretty_print (FILE *f)
{
  if (! rtl_slim_pp_initialized)
    {
      pp_construct (&rtl_slim_pp, /*prefix=*/NULL, /*linewidth=*/0);
      rtl_slim_pp_initialized = true;
    }
773
  else
774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793
    /* Clean out any data that str_insn_slim may have left here.  */
    pp_clear_output_area (&rtl_slim_pp);

  rtl_slim_pp.buffer->stream = f;
  return &rtl_slim_pp;
}

/* Print X, an RTL value node, to file F in slim format.  Include
   additional information if VERBOSE is nonzero.

   Value nodes are constants, registers, labels, symbols and
   memory.  */

void
dump_value_slim (FILE *f, const_rtx x, int verbose)
{
  pretty_printer *pp = init_rtl_slim_pretty_print (f);
  print_value (pp, x, verbose);
  pp_flush (pp);
}
794 795 796 797

/* Emit a slim dump of X (an insn) to the file F, including any register
   note attached to the instruction.  */
void
798
dump_insn_slim (FILE *f, const_rtx x)
799
{
800 801 802
  pretty_printer *pp = init_rtl_slim_pretty_print (f);
  print_insn_with_notes (pp, x);
  pp_flush (pp);
803 804
}

H.J. Lu committed
805
/* Same as above, but stop at LAST or when COUNT == 0.
806
   If COUNT < 0 it will stop only at LAST or NULL rtx.  */
807 808 809 810

void
dump_rtl_slim (FILE *f, const_rtx first, const_rtx last,
	       int count, int flags ATTRIBUTE_UNUSED)
811
{
812
  const_rtx insn, tail;
813
  pretty_printer *pp = init_rtl_slim_pretty_print (f);
814

815
  tail = last ? NEXT_INSN (last) : NULL_RTX;
H.J. Lu committed
816 817
  for (insn = first;
       (insn != NULL) && (insn != tail) && (count != 0);
818
       insn = NEXT_INSN (insn))
819
    {
820
      print_insn_with_notes (pp, insn);
821 822
      if (count > 0)
        count--;
823
    }
824 825 826 827

  pp_flush (pp);
}

828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850
/* Dumps basic block BB to pretty-printer PP in slim form and without and
   no indentation, for use as a label of a DOT graph record-node.  */

void
rtl_dump_bb_for_graph (pretty_printer *pp, basic_block bb)
{
  rtx insn;
  bool first = true;

  /* TODO: inter-bb stuff.  */
  FOR_BB_INSNS (bb, insn)
    {
      if (! first)
	{
	  pp_character (pp, '|');
	  pp_write_text_to_stream (pp);
	}
      first = false;
      print_insn_with_notes (pp, insn);
      pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
    }
}

851 852 853 854 855 856 857 858 859 860 861 862
/* Pretty-print pattern X of some insn in non-verbose mode.
   Return a string pointer to the pretty-printer buffer.

   This function is only exported exists only to accommodate some older users
   of the slim RTL pretty printers.  Please do not use it for new code.  */

const char *
str_pattern_slim (const_rtx x)
{
  pretty_printer *pp = init_rtl_slim_pretty_print (NULL);
  print_pattern (pp, x, 0);
  return pp_base_formatted_text (pp);
863
}
864

865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880
/* Emit a slim dump of X (an insn) to stderr.  */
extern void debug_insn_slim (const_rtx);
DEBUG_FUNCTION void
debug_insn_slim (const_rtx x)
{
  dump_insn_slim (stderr, x);
}

/* Same as above, but using dump_rtl_slim.  */
extern void debug_rtl_slim (FILE *, const_rtx, const_rtx, int, int);
DEBUG_FUNCTION void
debug_rtl_slim (const_rtx first, const_rtx last, int count, int flags)
{
  dump_rtl_slim (stderr, first, last, count, flags);
}

881
extern void debug_bb_slim (basic_block);
882
DEBUG_FUNCTION void
883
debug_bb_slim (basic_block bb)
884
{
885
  dump_bb (stderr, bb, 0, TDF_SLIM | TDF_BLOCKS);
886 887
}

888
extern void debug_bb_n_slim (int);
889
DEBUG_FUNCTION void
890 891
debug_bb_n_slim (int n)
{
892
  basic_block bb = BASIC_BLOCK (n);
893 894 895
  debug_bb_slim (bb);
}