1 /* Printing of RTL in "slim", mnemonic like form.
2 Copyright (C) 1992-2015 Free Software Foundation, Inc.
3 Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
4 and currently maintained by, Jim Wilson (wilson@cygnus.com)
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* Historically this form of RTL dumping was introduced along with
23 the Haifa instruction scheduling pass, hence the name of this file.
24 But there is nothing in this file left that is scheduler-specific. */
28 #include "coretypes.h"
34 #include "double-int.h"
40 #include "tree.h" /* FIXME: To dump INSN_VAR_LOCATION_DECL. */
46 #include "hard-reg-set.h"
49 #include "dominance.h"
51 #include "basic-block.h"
52 #include "dumpfile.h" /* for the TDF_* flags */
53 #include "pretty-print.h"
55 /* The functions in this file try to print RTL in a form resembling assembler
56 mnemonics. Because this form is more concise than the "traditional" form
57 of RTL printing in Lisp-style, the form printed by this file is called
58 "slim". RTL dumps in slim format can be obtained by appending the "-slim"
59 option to -fdump-rtl-<pass>. Control flow graph output as a DOT file is
60 always printed in slim form.
62 The normal interface to the functionality provided in this pretty-printer
63 is through the dump_*_slim functions to print to a stream, or via the
64 print_*_slim functions to print into a user's pretty-printer.
66 It is also possible to obtain a string for a single pattern as a string
67 pointer, via str_pattern_slim, but this usage is discouraged. */
69 /* For insns we print patterns, and for some patterns we print insns... */
70 static void print_insn_with_notes (pretty_printer
*, const rtx_insn
*);
72 /* This recognizes rtx'en classified as expressions. These are always
73 represent some action on values or results of other expression, that
74 may be stored in objects representing values. */
77 print_exp (pretty_printer
*pp
, const_rtx x
, int verbose
)
85 for (i
= 0; i
< 4; i
++)
95 if (CONST_INT_P (XEXP (x
, 1))
96 && INTVAL (XEXP (x
, 1)) < 0)
99 op
[1] = GEN_INT (-INTVAL (XEXP (x
, 1)));
256 fun
= (verbose
) ? "sign_extract" : "sxt";
262 fun
= (verbose
) ? "zero_extract" : "zxt";
268 fun
= (verbose
) ? "sign_extend" : "sxn";
272 fun
= (verbose
) ? "zero_extend" : "zxn";
276 fun
= (verbose
) ? "float_extend" : "fxn";
280 fun
= (verbose
) ? "trunc" : "trn";
284 fun
= (verbose
) ? "float_trunc" : "ftr";
288 fun
= (verbose
) ? "float" : "flt";
292 fun
= (verbose
) ? "uns_float" : "ufl";
300 fun
= (verbose
) ? "uns_fix" : "ufx";
321 op
[0] = XEXP (XEXP (x
, 1), 0);
323 op
[1] = XEXP (XEXP (x
, 1), 1);
327 op
[0] = XEXP (XEXP (x
, 1), 0);
329 op
[1] = XEXP (XEXP (x
, 1), 1);
351 op
[0] = TRAP_CONDITION (x
);
360 case UNSPEC_VOLATILE
:
362 pp_string (pp
, "unspec");
363 if (GET_CODE (x
) == UNSPEC_VOLATILE
)
364 pp_string (pp
, "/v");
365 pp_left_bracket (pp
);
366 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
370 print_pattern (pp
, XVECEXP (x
, 0, i
), verbose
);
372 pp_string (pp
, "] ");
373 pp_decimal_int (pp
, XINT (x
, 1));
378 /* Most unhandled codes can be printed as pseudo-functions. */
379 if (GET_RTX_CLASS (GET_CODE (x
)) == RTX_UNARY
)
381 fun
= GET_RTX_NAME (GET_CODE (x
));
384 else if (GET_RTX_CLASS (GET_CODE (x
)) == RTX_COMPARE
385 || GET_RTX_CLASS (GET_CODE (x
)) == RTX_COMM_COMPARE
386 || GET_RTX_CLASS (GET_CODE (x
)) == RTX_BIN_ARITH
387 || GET_RTX_CLASS (GET_CODE (x
)) == RTX_COMM_ARITH
)
389 fun
= GET_RTX_NAME (GET_CODE (x
));
393 else if (GET_RTX_CLASS (GET_CODE (x
)) == RTX_TERNARY
)
395 fun
= GET_RTX_NAME (GET_CODE (x
));
401 /* Give up, just print the RTX name. */
402 st
[0] = GET_RTX_NAME (GET_CODE (x
));
407 /* Print this as a function? */
414 for (i
= 0; i
< 4; i
++)
417 pp_string (pp
, st
[i
]);
423 print_value (pp
, op
[i
], verbose
);
431 /* Prints rtxes, I customarily classified as values. They're constants,
432 registers, labels, symbols and memory accesses. */
435 print_value (pretty_printer
*pp
, const_rtx x
, int verbose
)
441 pp_string (pp
, "(nil)");
444 switch (GET_CODE (x
))
447 pp_scalar (pp
, HOST_WIDE_INT_PRINT_HEX
,
448 (unsigned HOST_WIDE_INT
) INTVAL (x
));
453 const char *sep
= "<";
455 for (i
= CONST_WIDE_INT_NUNITS (x
) - 1; i
>= 0; i
--)
459 sprintf (tmp
, HOST_WIDE_INT_PRINT_HEX
,
460 (unsigned HOST_WIDE_INT
) CONST_WIDE_INT_ELT (x
, i
));
468 if (FLOAT_MODE_P (GET_MODE (x
)))
470 real_to_decimal (tmp
, CONST_DOUBLE_REAL_VALUE (x
),
475 pp_printf (pp
, "<%wx,%wx>",
476 (unsigned HOST_WIDE_INT
) CONST_DOUBLE_LOW (x
),
477 (unsigned HOST_WIDE_INT
) CONST_DOUBLE_HIGH (x
));
480 fixed_to_decimal (tmp
, CONST_FIXED_VALUE (x
), sizeof (tmp
));
484 pp_printf (pp
, "\"%s\"", XSTR (x
, 0));
487 pp_printf (pp
, "`%s'", XSTR (x
, 0));
490 pp_printf (pp
, "L%d", INSN_UID (LABEL_REF_LABEL (x
)));
494 case STRICT_LOW_PART
:
495 pp_printf (pp
, "%s(", GET_RTX_NAME (GET_CODE (x
)));
496 print_value (pp
, XEXP (x
, 0), verbose
);
500 if (REGNO (x
) < FIRST_PSEUDO_REGISTER
)
502 if (ISDIGIT (reg_names
[REGNO (x
)][0]))
504 pp_string (pp
, reg_names
[REGNO (x
)]);
507 pp_printf (pp
, "r%d", REGNO (x
));
509 pp_printf (pp
, ":%s", GET_MODE_NAME (GET_MODE (x
)));
512 print_value (pp
, SUBREG_REG (x
), verbose
);
513 pp_printf (pp
, "#%d", SUBREG_BYTE (x
));
518 pp_string (pp
, GET_RTX_NAME (GET_CODE (x
)));
521 pp_left_bracket (pp
);
522 print_value (pp
, XEXP (x
, 0), verbose
);
523 pp_right_bracket (pp
);
526 pp_printf (pp
, "D#%i", DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x
)));
529 print_exp (pp
, x
, verbose
);
534 /* The next step in insn detalization, its pattern recognition. */
537 print_pattern (pretty_printer
*pp
, const_rtx x
, int verbose
)
541 pp_string (pp
, "(nil)");
545 switch (GET_CODE (x
))
548 print_value (pp
, SET_DEST (x
), verbose
);
550 print_value (pp
, SET_SRC (x
), verbose
);
555 pp_string (pp
, GET_RTX_NAME (GET_CODE (x
)));
558 print_exp (pp
, x
, verbose
);
562 pp_printf (pp
, "%s ", GET_RTX_NAME (GET_CODE (x
)));
563 print_value (pp
, XEXP (x
, 0), verbose
);
566 pp_string (pp
, "loc ");
567 print_value (pp
, PAT_VAR_LOCATION_LOC (x
), verbose
);
571 if (GET_CODE (COND_EXEC_TEST (x
)) == NE
572 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
573 print_value (pp
, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
574 else if (GET_CODE (COND_EXEC_TEST (x
)) == EQ
575 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
578 print_value (pp
, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
581 print_value (pp
, COND_EXEC_TEST (x
), verbose
);
582 pp_string (pp
, ") ");
583 print_pattern (pp
, COND_EXEC_CODE (x
), verbose
);
590 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
592 print_pattern (pp
, XVECEXP (x
, 0, i
), verbose
);
600 const rtx_sequence
*seq
= as_a
<const rtx_sequence
*> (x
);
601 pp_string (pp
, "sequence{");
602 if (INSN_P (seq
->element (0)))
604 /* Print the sequence insns indented. */
605 const char * save_print_rtx_head
= print_rtx_head
;
606 char indented_print_rtx_head
[32];
609 gcc_assert (strlen (print_rtx_head
) < sizeof (indented_print_rtx_head
) - 4);
610 snprintf (indented_print_rtx_head
,
611 sizeof (indented_print_rtx_head
),
612 "%s ", print_rtx_head
);
613 print_rtx_head
= indented_print_rtx_head
;
614 for (int i
= 0; i
< seq
->len (); i
++)
615 print_insn_with_notes (pp
, seq
->insn (i
));
616 pp_printf (pp
, "%s ", save_print_rtx_head
);
617 print_rtx_head
= save_print_rtx_head
;
621 for (int i
= 0; i
< seq
->len (); i
++)
623 print_pattern (pp
, seq
->element (i
), verbose
);
631 pp_printf (pp
, "asm {%s}", XSTR (x
, 0));
634 for (int i
= 0; i
< XVECLEN (x
, 0); i
++)
636 print_value (pp
, XVECEXP (x
, 0, i
), verbose
);
641 for (int i
= 0; i
< XVECLEN (x
, 1); i
++)
643 print_value (pp
, XVECEXP (x
, 1, i
), verbose
);
648 pp_string (pp
, "trap_if ");
649 print_value (pp
, TRAP_CONDITION (x
), verbose
);
652 case UNSPEC_VOLATILE
:
653 /* Fallthru -- leave UNSPECs to print_exp. */
655 print_value (pp
, x
, verbose
);
657 } /* print_pattern */
659 /* This is the main function in slim rtl visualization mechanism.
661 X is an insn, to be printed into PP.
663 This function tries to print it properly in human-readable form,
664 resembling assembler mnemonics (instead of the older Lisp-style
667 If VERBOSE is TRUE, insns are printed with more complete (but
668 longer) pattern names and with extra information, and prefixed
669 with their INSN_UIDs. */
672 print_insn (pretty_printer
*pp
, const rtx_insn
*x
, int verbose
)
676 /* Blech, pretty-print can't print integers with a specified width. */
678 snprintf (uid_prefix
, sizeof uid_prefix
, " %4d: ", INSN_UID (x
));
679 pp_string (pp
, uid_prefix
);
682 switch (GET_CODE (x
))
685 print_pattern (pp
, PATTERN (x
), verbose
);
690 const char *name
= "?";
692 if (DECL_P (INSN_VAR_LOCATION_DECL (x
)))
694 tree id
= DECL_NAME (INSN_VAR_LOCATION_DECL (x
));
697 name
= IDENTIFIER_POINTER (id
);
698 else if (TREE_CODE (INSN_VAR_LOCATION_DECL (x
))
701 sprintf (idbuf
, "D#%i",
702 DEBUG_TEMP_UID (INSN_VAR_LOCATION_DECL (x
)));
707 sprintf (idbuf
, "D.%i",
708 DECL_UID (INSN_VAR_LOCATION_DECL (x
)));
712 pp_printf (pp
, "debug %s => ", name
);
713 if (VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (x
)))
714 pp_string (pp
, "optimized away");
716 print_pattern (pp
, INSN_VAR_LOCATION_LOC (x
), verbose
);
721 print_pattern (pp
, PATTERN (x
), verbose
);
724 if (GET_CODE (PATTERN (x
)) == PARALLEL
)
725 print_pattern (pp
, XVECEXP (PATTERN (x
), 0, 0), verbose
);
727 print_pattern (pp
, PATTERN (x
), verbose
);
730 pp_printf (pp
, "L%d:", INSN_UID (x
));
732 case JUMP_TABLE_DATA
:
733 pp_string (pp
, "jump_table_data{\n");
734 print_pattern (pp
, PATTERN (x
), verbose
);
738 pp_string (pp
, "barrier");
742 pp_string (pp
, GET_NOTE_INSN_NAME (NOTE_KIND (x
)));
743 switch (NOTE_KIND (x
))
745 case NOTE_INSN_EH_REGION_BEG
:
746 case NOTE_INSN_EH_REGION_END
:
747 pp_printf (pp
, " %d", NOTE_EH_HANDLER (x
));
750 case NOTE_INSN_BLOCK_BEG
:
751 case NOTE_INSN_BLOCK_END
:
752 pp_printf (pp
, " %d", BLOCK_NUMBER (NOTE_BLOCK (x
)));
755 case NOTE_INSN_BASIC_BLOCK
:
756 pp_printf (pp
, " %d", NOTE_BASIC_BLOCK (x
)->index
);
759 case NOTE_INSN_DELETED_LABEL
:
760 case NOTE_INSN_DELETED_DEBUG_LABEL
:
762 const char *label
= NOTE_DELETED_LABEL_NAME (x
);
765 pp_printf (pp
, " (\"%s\")", label
);
769 case NOTE_INSN_VAR_LOCATION
:
770 case NOTE_INSN_CALL_ARG_LOCATION
:
772 print_pattern (pp
, NOTE_VAR_LOCATION (x
), verbose
);
786 /* Pretty-print a slim dump of X (an insn) to PP, including any register
787 note attached to the instruction. */
790 print_insn_with_notes (pretty_printer
*pp
, const rtx_insn
*x
)
792 pp_string (pp
, print_rtx_head
);
793 print_insn (pp
, x
, 1);
795 if (INSN_P (x
) && REG_NOTES (x
))
796 for (rtx note
= REG_NOTES (x
); note
; note
= XEXP (note
, 1))
798 pp_printf (pp
, "%s %s ", print_rtx_head
,
799 GET_REG_NOTE_NAME (REG_NOTE_KIND (note
)));
800 if (GET_CODE (note
) == INT_LIST
)
801 pp_printf (pp
, "%d", XINT (note
, 0));
803 print_pattern (pp
, XEXP (note
, 0), 1);
808 /* Print X, an RTL value node, to file F in slim format. Include
809 additional information if VERBOSE is nonzero.
811 Value nodes are constants, registers, labels, symbols and
815 dump_value_slim (FILE *f
, const_rtx x
, int verbose
)
817 pretty_printer rtl_slim_pp
;
818 rtl_slim_pp
.buffer
->stream
= f
;
819 print_value (&rtl_slim_pp
, x
, verbose
);
820 pp_flush (&rtl_slim_pp
);
823 /* Emit a slim dump of X (an insn) to the file F, including any register
824 note attached to the instruction. */
826 dump_insn_slim (FILE *f
, const rtx_insn
*x
)
828 pretty_printer rtl_slim_pp
;
829 rtl_slim_pp
.buffer
->stream
= f
;
830 print_insn_with_notes (&rtl_slim_pp
, x
);
831 pp_flush (&rtl_slim_pp
);
834 /* Same as above, but stop at LAST or when COUNT == 0.
835 If COUNT < 0 it will stop only at LAST or NULL rtx. */
838 dump_rtl_slim (FILE *f
, const rtx_insn
*first
, const rtx_insn
*last
,
839 int count
, int flags ATTRIBUTE_UNUSED
)
841 const rtx_insn
*insn
, *tail
;
842 pretty_printer rtl_slim_pp
;
843 rtl_slim_pp
.buffer
->stream
= f
;
845 tail
= last
? NEXT_INSN (last
) : NULL
;
847 (insn
!= NULL
) && (insn
!= tail
) && (count
!= 0);
848 insn
= NEXT_INSN (insn
))
850 print_insn_with_notes (&rtl_slim_pp
, insn
);
855 pp_flush (&rtl_slim_pp
);
858 /* Dumps basic block BB to pretty-printer PP in slim form and without and
859 no indentation, for use as a label of a DOT graph record-node. */
862 rtl_dump_bb_for_graph (pretty_printer
*pp
, basic_block bb
)
867 /* TODO: inter-bb stuff. */
868 FOR_BB_INSNS (bb
, insn
)
873 pp_write_text_to_stream (pp
);
876 print_insn_with_notes (pp
, insn
);
877 pp_write_text_as_dot_label_to_stream (pp
, /*for_record=*/true);
881 /* Pretty-print pattern X of some insn in non-verbose mode.
882 Return a string pointer to the pretty-printer buffer.
884 This function is only exported exists only to accommodate some older users
885 of the slim RTL pretty printers. Please do not use it for new code. */
888 str_pattern_slim (const_rtx x
)
890 pretty_printer rtl_slim_pp
;
891 print_pattern (&rtl_slim_pp
, x
, 0);
892 return ggc_strdup (pp_formatted_text (&rtl_slim_pp
));
895 /* Emit a slim dump of X (an insn) to stderr. */
896 extern void debug_insn_slim (const rtx_insn
*);
898 debug_insn_slim (const rtx_insn
*x
)
900 dump_insn_slim (stderr
, x
);
903 /* Same as above, but using dump_rtl_slim. */
904 extern void debug_rtl_slim (FILE *, const rtx_insn
*, const rtx_insn
*,
907 debug_rtl_slim (const rtx_insn
*first
, const rtx_insn
*last
, int count
,
910 dump_rtl_slim (stderr
, first
, last
, count
, flags
);
913 extern void debug_bb_slim (basic_block
);
915 debug_bb_slim (basic_block bb
)
917 dump_bb (stderr
, bb
, 0, TDF_SLIM
| TDF_BLOCKS
);
920 extern void debug_bb_n_slim (int);
922 debug_bb_n_slim (int n
)
924 basic_block bb
= BASIC_BLOCK_FOR_FN (cfun
, n
);