1 /* Printing of RTL in "slim", mnemonic like form.
2 Copyright (C) 1992-2012
3 Free Software Foundation, Inc.
4 Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
5 and currently maintained by, Jim Wilson (wilson@cygnus.com)
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* Historically this form of RTL dumping was introduced along with
24 the Haifa instruction scheduling pass, hence the name of this file.
25 But there is nothing in this file left that is scheduler-specific. */
29 #include "coretypes.h"
32 #include "tree.h" /* FIXME: To dump INSN_VAR_LOCATION_DECL. */
34 #include "hard-reg-set.h"
35 #include "basic-block.h"
36 #include "insn-attr.h"
37 #include "dumpfile.h" /* for the TDF_* flags */
39 static char *safe_concat (char *, char *, const char *);
44 safe_concat (char *buf
, char *cur
, const char *str
)
46 char *end
= buf
+ BUF_LEN
- 2; /* Leave room for null. */
55 while (cur
< end
&& (c
= *str
++) != '\0')
62 /* This recognizes rtx, I classified as expressions. These are always
63 represent some action on values or results of other expression, that
64 may be stored in objects representing values. */
67 print_exp (char *buf
, const_rtx x
, int verbose
)
72 const char *fun
= (char *) 0;
77 for (i
= 0; i
< 4; i
++)
87 if (CONST_INT_P (XEXP (x
, 1))
88 && INTVAL (XEXP (x
, 1)) < 0)
91 op
[1] = GEN_INT (-INTVAL (XEXP (x
, 1)));
248 fun
= (verbose
) ? "sign_extract" : "sxt";
254 fun
= (verbose
) ? "zero_extract" : "zxt";
260 fun
= (verbose
) ? "sign_extend" : "sxn";
264 fun
= (verbose
) ? "zero_extend" : "zxn";
268 fun
= (verbose
) ? "float_extend" : "fxn";
272 fun
= (verbose
) ? "trunc" : "trn";
276 fun
= (verbose
) ? "float_trunc" : "ftr";
280 fun
= (verbose
) ? "float" : "flt";
284 fun
= (verbose
) ? "uns_float" : "ufl";
292 fun
= (verbose
) ? "uns_fix" : "ufx";
313 op
[0] = XEXP (XEXP (x
, 1), 0);
315 op
[1] = XEXP (XEXP (x
, 1), 1);
319 op
[0] = XEXP (XEXP (x
, 1), 0);
321 op
[1] = XEXP (XEXP (x
, 1), 1);
343 op
[0] = TRAP_CONDITION (x
);
352 case UNSPEC_VOLATILE
:
354 cur
= safe_concat (buf
, cur
, "unspec");
355 if (GET_CODE (x
) == UNSPEC_VOLATILE
)
356 cur
= safe_concat (buf
, cur
, "/v");
357 cur
= safe_concat (buf
, cur
, "[");
359 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
361 print_pattern (tmp
, XVECEXP (x
, 0, i
), verbose
);
362 cur
= safe_concat (buf
, cur
, sep
);
363 cur
= safe_concat (buf
, cur
, tmp
);
366 cur
= safe_concat (buf
, cur
, "] ");
367 sprintf (tmp
, "%d", XINT (x
, 1));
368 cur
= safe_concat (buf
, cur
, tmp
);
373 /* Most unhandled codes can be printed as pseudo-functions. */
374 if (GET_RTX_CLASS (GET_CODE (x
)) == RTX_UNARY
)
376 fun
= GET_RTX_NAME (GET_CODE (x
));
379 else if (GET_RTX_CLASS (GET_CODE (x
)) == RTX_COMPARE
380 || GET_RTX_CLASS (GET_CODE (x
)) == RTX_COMM_COMPARE
381 || GET_RTX_CLASS (GET_CODE (x
)) == RTX_BIN_ARITH
382 || GET_RTX_CLASS (GET_CODE (x
)) == RTX_COMM_ARITH
)
384 fun
= GET_RTX_NAME (GET_CODE (x
));
388 else if (GET_RTX_CLASS (GET_CODE (x
)) == RTX_TERNARY
)
390 fun
= GET_RTX_NAME (GET_CODE (x
));
396 /* Give up, just print the RTX name. */
397 st
[0] = GET_RTX_NAME (GET_CODE (x
));
402 /* Print this as a function? */
405 cur
= safe_concat (buf
, cur
, fun
);
406 cur
= safe_concat (buf
, cur
, "(");
409 for (i
= 0; i
< 4; i
++)
412 cur
= safe_concat (buf
, cur
, st
[i
]);
417 cur
= safe_concat (buf
, cur
, ",");
419 print_value (tmp
, op
[i
], verbose
);
420 cur
= safe_concat (buf
, cur
, tmp
);
425 cur
= safe_concat (buf
, cur
, ")");
428 /* Prints rtxes, I customarily classified as values. They're constants,
429 registers, labels, symbols and memory accesses. */
432 print_value (char *buf
, const_rtx x
, int verbose
)
439 safe_concat (buf
, buf
, "(nil)");
442 switch (GET_CODE (x
))
445 sprintf (t
, HOST_WIDE_INT_PRINT_HEX
,
446 (unsigned HOST_WIDE_INT
) INTVAL (x
));
447 cur
= safe_concat (buf
, cur
, t
);
450 if (FLOAT_MODE_P (GET_MODE (x
)))
451 real_to_decimal (t
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (t
), 0, 1);
454 "<" HOST_WIDE_INT_PRINT_HEX
"," HOST_WIDE_INT_PRINT_HEX
">",
455 (unsigned HOST_WIDE_INT
) CONST_DOUBLE_LOW (x
),
456 (unsigned HOST_WIDE_INT
) CONST_DOUBLE_HIGH (x
));
457 cur
= safe_concat (buf
, cur
, t
);
460 fixed_to_decimal (t
, CONST_FIXED_VALUE (x
), sizeof (t
));
461 cur
= safe_concat (buf
, cur
, t
);
464 cur
= safe_concat (buf
, cur
, "\"");
465 cur
= safe_concat (buf
, cur
, XSTR (x
, 0));
466 cur
= safe_concat (buf
, cur
, "\"");
469 cur
= safe_concat (buf
, cur
, "`");
470 cur
= safe_concat (buf
, cur
, XSTR (x
, 0));
471 cur
= safe_concat (buf
, cur
, "'");
474 sprintf (t
, "L%d", INSN_UID (XEXP (x
, 0)));
475 cur
= safe_concat (buf
, cur
, t
);
478 print_value (t
, XEXP (x
, 0), verbose
);
479 cur
= safe_concat (buf
, cur
, "const(");
480 cur
= safe_concat (buf
, cur
, t
);
481 cur
= safe_concat (buf
, cur
, ")");
484 print_value (t
, XEXP (x
, 0), verbose
);
485 cur
= safe_concat (buf
, cur
, "high(");
486 cur
= safe_concat (buf
, cur
, t
);
487 cur
= safe_concat (buf
, cur
, ")");
490 if (REGNO (x
) < FIRST_PSEUDO_REGISTER
)
492 int c
= reg_names
[REGNO (x
)][0];
494 cur
= safe_concat (buf
, cur
, "%");
496 cur
= safe_concat (buf
, cur
, reg_names
[REGNO (x
)]);
500 sprintf (t
, "r%d", REGNO (x
));
501 cur
= safe_concat (buf
, cur
, t
);
505 sprintf (t
, ":%s", GET_MODE_NAME (GET_MODE (x
)));
506 cur
= safe_concat (buf
, cur
, t
);
510 print_value (t
, SUBREG_REG (x
), verbose
);
511 cur
= safe_concat (buf
, cur
, t
);
512 sprintf (t
, "#%d", SUBREG_BYTE (x
));
513 cur
= safe_concat (buf
, cur
, t
);
515 case STRICT_LOW_PART
:
516 print_value (t
, XEXP (x
, 0), verbose
);
517 cur
= safe_concat (buf
, cur
, "strict_low_part(");
518 cur
= safe_concat (buf
, cur
, t
);
519 cur
= safe_concat (buf
, cur
, ")");
522 cur
= safe_concat (buf
, cur
, "scratch");
525 cur
= safe_concat (buf
, cur
, "cc0");
528 cur
= safe_concat (buf
, cur
, "pc");
531 print_value (t
, XEXP (x
, 0), verbose
);
532 cur
= safe_concat (buf
, cur
, "[");
533 cur
= safe_concat (buf
, cur
, t
);
534 cur
= safe_concat (buf
, cur
, "]");
537 sprintf (t
, "D#%i", DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x
)));
538 cur
= safe_concat (buf
, cur
, t
);
541 print_exp (t
, x
, verbose
);
542 cur
= safe_concat (buf
, cur
, t
);
547 /* Print X, an RTL value node, to file F in slim format. Include
548 additional information if VERBOSE is nonzero.
550 Value nodes are constants, registers, labels, symbols and
554 dump_value_slim (FILE *f
, const_rtx x
, int verbose
)
558 print_value (buf
, x
, verbose
);
559 fprintf (f
, "%s", buf
);
562 /* The next step in insn detalization, its pattern recognition. */
565 print_pattern (char *buf
, const_rtx x
, int verbose
)
567 char t1
[BUF_LEN
], t2
[BUF_LEN
], t3
[BUF_LEN
];
571 sprintf (buf
, "(nil)");
575 switch (GET_CODE (x
))
578 print_value (t1
, SET_DEST (x
), verbose
);
579 print_value (t2
, SET_SRC (x
), verbose
);
580 sprintf (buf
, "%s=%s", t1
, t2
);
585 sprintf (buf
, GET_RTX_NAME (GET_CODE (x
)));
588 print_exp (buf
, x
, verbose
);
592 print_value (t1
, XEXP (x
, 0), verbose
);
593 sprintf (buf
, "%s %s", GET_RTX_NAME (GET_CODE (x
)), t1
);
596 print_value (t1
, PAT_VAR_LOCATION_LOC (x
), verbose
);
597 sprintf (buf
, "loc %s", t1
);
600 if (GET_CODE (COND_EXEC_TEST (x
)) == NE
601 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
602 print_value (t1
, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
603 else if (GET_CODE (COND_EXEC_TEST (x
)) == EQ
604 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
607 print_value (t1
+ 1, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
610 print_value (t1
, COND_EXEC_TEST (x
), verbose
);
611 print_pattern (t2
, COND_EXEC_CODE (x
), verbose
);
612 sprintf (buf
, "(%s) %s", t1
, t2
);
619 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
621 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
622 sprintf (t3
, "%s%s;", t1
, t2
);
625 sprintf (buf
, "%s}", t1
);
632 sprintf (t1
, "sequence{");
633 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
635 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
636 sprintf (t3
, "%s%s;", t1
, t2
);
639 sprintf (buf
, "%s}", t1
);
643 sprintf (buf
, "asm {%s}", XSTR (x
, 0));
648 print_value (buf
, XEXP (x
, 0), verbose
);
651 print_value (t1
, TRAP_CONDITION (x
), verbose
);
652 sprintf (buf
, "trap_if %s", t1
);
655 case UNSPEC_VOLATILE
:
656 /* Fallthru -- leave UNSPECs to print_exp. */
658 print_value (buf
, x
, verbose
);
660 } /* print_pattern */
662 /* This is the main function in slim rtl visualization mechanism.
664 X is an insn, to be printed into BUF.
666 This function tries to print it properly in human-readable form,
667 resembling assembler mnemonics (instead of the older Lisp-style
670 If VERBOSE is TRUE, insns are printed with more complete (but
671 longer) pattern names and with extra information, and prefixed
672 with their INSN_UIDs. */
675 print_insn (char *buf
, const_rtx x
, int verbose
)
677 /* Collect the string to output for X in t1. t2 is a scratch area. */
678 char t1
[BUF_LEN
], t2
[BUF_LEN
];
680 switch (GET_CODE (x
))
683 print_pattern (t1
, PATTERN (x
), verbose
);
688 const char *name
= "?";
690 if (DECL_P (INSN_VAR_LOCATION_DECL (x
)))
692 tree id
= DECL_NAME (INSN_VAR_LOCATION_DECL (x
));
695 name
= IDENTIFIER_POINTER (id
);
696 else if (TREE_CODE (INSN_VAR_LOCATION_DECL (x
))
699 sprintf (idbuf
, "D#%i",
700 DEBUG_TEMP_UID (INSN_VAR_LOCATION_DECL (x
)));
705 sprintf (idbuf
, "D.%i",
706 DECL_UID (INSN_VAR_LOCATION_DECL (x
)));
710 if (VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (x
)))
711 sprintf (t1
, "debug %s optimized away", name
);
714 print_pattern (t2
, INSN_VAR_LOCATION_LOC (x
), verbose
);
715 sprintf (t1
, "debug %s => %s", name
, t2
);
721 print_pattern (t1
, PATTERN (x
), verbose
);
724 if (GET_CODE (PATTERN (x
)) == PARALLEL
)
725 print_pattern (t1
, XVECEXP (PATTERN (x
), 0, 0), verbose
);
727 print_pattern (t1
, PATTERN (x
), verbose
);
730 sprintf (t1
, "L%d:", INSN_UID (x
));
733 sprintf (t1
, "barrier");
737 switch (NOTE_KIND (x
))
739 case NOTE_INSN_EH_REGION_BEG
:
740 case NOTE_INSN_EH_REGION_END
:
741 sprintf (t2
, "%d", NOTE_EH_HANDLER (x
));
744 case NOTE_INSN_BLOCK_BEG
:
745 case NOTE_INSN_BLOCK_END
:
746 sprintf (t2
, "%d", BLOCK_NUMBER (NOTE_BLOCK (x
)));
749 case NOTE_INSN_BASIC_BLOCK
:
750 sprintf (t2
, "%d", NOTE_BASIC_BLOCK (x
)->index
);
753 case NOTE_INSN_DELETED_LABEL
:
754 case NOTE_INSN_DELETED_DEBUG_LABEL
:
756 const char *label
= NOTE_DELETED_LABEL_NAME (x
);
759 sprintf (t2
, "(\"%s\")", label
);
763 case NOTE_INSN_VAR_LOCATION
:
764 case NOTE_INSN_CALL_ARG_LOCATION
:
765 /* It's safe here to use t1 for scratch because the output
766 is printed in t2 and put back in t1 at the bottom of
767 the inner switch statement. */
768 print_pattern (t1
, NOTE_VAR_LOCATION (x
), verbose
);
769 sprintf (t2
, "{%s}", t1
);
776 sprintf (t1
, "%s %s", GET_NOTE_INSN_NAME (NOTE_KIND (x
)), t2
);
780 sprintf (t1
, "<What %s?>", GET_RTX_NAME (GET_CODE (x
)));
785 sprintf (buf
, " %4d: %s", INSN_UID (x
), t1
);
787 sprintf (buf
, "%s", t1
);
790 /* Emit a slim dump of X (an insn) to the file F, including any register
791 note attached to the instruction. */
793 dump_insn_slim (FILE *f
, const_rtx x
)
795 char t
[BUF_LEN
+ 32];
798 print_insn (t
, x
, 1);
799 fputs (print_rtx_head
, f
);
802 if (INSN_P (x
) && REG_NOTES (x
))
803 for (note
= REG_NOTES (x
); note
; note
= XEXP (note
, 1))
805 fputs (print_rtx_head
, f
);
806 print_pattern (t
, XEXP (note
, 0), 1);
807 fprintf (f
, " %s: %s\n",
808 GET_REG_NOTE_NAME (REG_NOTE_KIND (note
)), t
);
812 /* Same as above, but stop at LAST or when COUNT == 0.
813 If COUNT < 0 it will stop only at LAST or NULL rtx. */
816 dump_rtl_slim (FILE *f
, const_rtx first
, const_rtx last
,
817 int count
, int flags ATTRIBUTE_UNUSED
)
819 const_rtx insn
, tail
;
821 tail
= last
? NEXT_INSN (last
) : NULL_RTX
;
823 (insn
!= NULL
) && (insn
!= tail
) && (count
!= 0);
824 insn
= NEXT_INSN (insn
))
826 dump_insn_slim (f
, insn
);
832 /* Emit a slim dump of X (an insn) to stderr. */
833 extern void debug_insn_slim (const_rtx
);
835 debug_insn_slim (const_rtx x
)
837 dump_insn_slim (stderr
, x
);
840 /* Same as above, but using dump_rtl_slim. */
841 extern void debug_rtl_slim (FILE *, const_rtx
, const_rtx
, int, int);
843 debug_rtl_slim (const_rtx first
, const_rtx last
, int count
, int flags
)
845 dump_rtl_slim (stderr
, first
, last
, count
, flags
);
848 extern void debug_bb_slim (basic_block
);
850 debug_bb_slim (basic_block bb
)
852 dump_bb (stderr
, bb
, 0, TDF_SLIM
| TDF_BLOCKS
);
855 extern void debug_bb_n_slim (int);
857 debug_bb_n_slim (int n
)
859 basic_block bb
= BASIC_BLOCK (n
);