13ad841b2Smrg /* Print RTL functions for GCC.
2*4c3eb207Smrg Copyright (C) 2016-2020 Free Software Foundation, Inc.
33ad841b2Smrg
43ad841b2Smrg This file is part of GCC.
53ad841b2Smrg
63ad841b2Smrg GCC is free software; you can redistribute it and/or modify it under
73ad841b2Smrg the terms of the GNU General Public License as published by the Free
83ad841b2Smrg Software Foundation; either version 3, or (at your option) any later
93ad841b2Smrg version.
103ad841b2Smrg
113ad841b2Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
123ad841b2Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
133ad841b2Smrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
143ad841b2Smrg for more details.
153ad841b2Smrg
163ad841b2Smrg You should have received a copy of the GNU General Public License
173ad841b2Smrg along with GCC; see the file COPYING3. If not see
183ad841b2Smrg <http://www.gnu.org/licenses/>. */
193ad841b2Smrg
203ad841b2Smrg #include "config.h"
213ad841b2Smrg #include "system.h"
223ad841b2Smrg #include "coretypes.h"
233ad841b2Smrg #include "tm.h"
243ad841b2Smrg #include "rtl.h"
253ad841b2Smrg #include "alias.h"
263ad841b2Smrg #include "tree.h"
273ad841b2Smrg #include "flags.h"
283ad841b2Smrg #include "predict.h"
293ad841b2Smrg #include "function.h"
303ad841b2Smrg #include "basic-block.h"
313ad841b2Smrg #include "print-rtl.h"
323ad841b2Smrg #include "langhooks.h"
333ad841b2Smrg #include "memmodel.h"
343ad841b2Smrg #include "emit-rtl.h"
353ad841b2Smrg #include "varasm.h"
363ad841b2Smrg
373ad841b2Smrg /* Print an "(edge-from)" or "(edge-to)" directive describing E
383ad841b2Smrg to OUTFILE. */
393ad841b2Smrg
403ad841b2Smrg static void
print_edge(FILE * outfile,edge e,bool from)413ad841b2Smrg print_edge (FILE *outfile, edge e, bool from)
423ad841b2Smrg {
433ad841b2Smrg fprintf (outfile, " (%s ", from ? "edge-from" : "edge-to");
443ad841b2Smrg basic_block bb = from ? e->src : e->dest;
453ad841b2Smrg gcc_assert (bb);
463ad841b2Smrg switch (bb->index)
473ad841b2Smrg {
483ad841b2Smrg case ENTRY_BLOCK:
493ad841b2Smrg fprintf (outfile, "entry");
503ad841b2Smrg break;
513ad841b2Smrg case EXIT_BLOCK:
523ad841b2Smrg fprintf (outfile, "exit");
533ad841b2Smrg break;
543ad841b2Smrg default:
553ad841b2Smrg fprintf (outfile, "%i", bb->index);
563ad841b2Smrg break;
573ad841b2Smrg }
583ad841b2Smrg
593ad841b2Smrg /* Express edge flags as a string with " | " separator.
603ad841b2Smrg e.g. (flags "FALLTHRU | DFS_BACK"). */
613ad841b2Smrg if (e->flags)
623ad841b2Smrg {
633ad841b2Smrg fprintf (outfile, " (flags \"");
643ad841b2Smrg bool seen_flag = false;
653ad841b2Smrg #define DEF_EDGE_FLAG(NAME,IDX) \
663ad841b2Smrg do { \
673ad841b2Smrg if (e->flags & EDGE_##NAME) \
683ad841b2Smrg { \
693ad841b2Smrg if (seen_flag) \
703ad841b2Smrg fprintf (outfile, " | "); \
713ad841b2Smrg fprintf (outfile, "%s", (#NAME)); \
723ad841b2Smrg seen_flag = true; \
733ad841b2Smrg } \
743ad841b2Smrg } while (0);
753ad841b2Smrg #include "cfg-flags.def"
763ad841b2Smrg #undef DEF_EDGE_FLAG
773ad841b2Smrg
783ad841b2Smrg fprintf (outfile, "\")");
793ad841b2Smrg }
803ad841b2Smrg
813ad841b2Smrg fprintf (outfile, ")\n");
823ad841b2Smrg }
833ad841b2Smrg
843ad841b2Smrg /* If BB is non-NULL, print the start of a "(block)" directive for it
853ad841b2Smrg to OUTFILE, otherwise do nothing. */
863ad841b2Smrg
873ad841b2Smrg static void
begin_any_block(FILE * outfile,basic_block bb)883ad841b2Smrg begin_any_block (FILE *outfile, basic_block bb)
893ad841b2Smrg {
903ad841b2Smrg if (!bb)
913ad841b2Smrg return;
923ad841b2Smrg
933ad841b2Smrg edge e;
943ad841b2Smrg edge_iterator ei;
953ad841b2Smrg
963ad841b2Smrg fprintf (outfile, " (block %i\n", bb->index);
973ad841b2Smrg FOR_EACH_EDGE (e, ei, bb->preds)
983ad841b2Smrg print_edge (outfile, e, true);
993ad841b2Smrg }
1003ad841b2Smrg
1013ad841b2Smrg /* If BB is non-NULL, print the end of a "(block)" directive for it
1023ad841b2Smrg to OUTFILE, otherwise do nothing. */
1033ad841b2Smrg
1043ad841b2Smrg static void
end_any_block(FILE * outfile,basic_block bb)1053ad841b2Smrg end_any_block (FILE *outfile, basic_block bb)
1063ad841b2Smrg {
1073ad841b2Smrg if (!bb)
1083ad841b2Smrg return;
1093ad841b2Smrg
1103ad841b2Smrg edge e;
1113ad841b2Smrg edge_iterator ei;
1123ad841b2Smrg
1133ad841b2Smrg FOR_EACH_EDGE (e, ei, bb->succs)
1143ad841b2Smrg print_edge (outfile, e, false);
1153ad841b2Smrg fprintf (outfile, " ) ;; block %i\n", bb->index);
1163ad841b2Smrg }
1173ad841b2Smrg
1183ad841b2Smrg /* Determine if INSN is of a kind that can have a basic block. */
1193ad841b2Smrg
1203ad841b2Smrg static bool
can_have_basic_block_p(const rtx_insn * insn)1213ad841b2Smrg can_have_basic_block_p (const rtx_insn *insn)
1223ad841b2Smrg {
1233ad841b2Smrg rtx_code code = GET_CODE (insn);
1243ad841b2Smrg if (code == BARRIER)
1253ad841b2Smrg return false;
1263ad841b2Smrg gcc_assert (GET_RTX_FORMAT (code)[2] == 'B');
1273ad841b2Smrg return true;
1283ad841b2Smrg }
1293ad841b2Smrg
1303ad841b2Smrg /* Subroutine of print_param. Write the name of ARG, if any, to OUTFILE. */
1313ad841b2Smrg
1323ad841b2Smrg static void
print_any_param_name(FILE * outfile,tree arg)1333ad841b2Smrg print_any_param_name (FILE *outfile, tree arg)
1343ad841b2Smrg {
1353ad841b2Smrg if (DECL_NAME (arg))
1363ad841b2Smrg fprintf (outfile, " \"%s\"", IDENTIFIER_POINTER (DECL_NAME (arg)));
1373ad841b2Smrg }
1383ad841b2Smrg
1393ad841b2Smrg /* Print a "(param)" directive for ARG to OUTFILE. */
1403ad841b2Smrg
1413ad841b2Smrg static void
print_param(FILE * outfile,rtx_writer & w,tree arg)1423ad841b2Smrg print_param (FILE *outfile, rtx_writer &w, tree arg)
1433ad841b2Smrg {
1443ad841b2Smrg fprintf (outfile, " (param");
1453ad841b2Smrg print_any_param_name (outfile, arg);
1463ad841b2Smrg fprintf (outfile, "\n");
1473ad841b2Smrg
1483ad841b2Smrg /* Print the value of DECL_RTL (without lazy-evaluation). */
1493ad841b2Smrg fprintf (outfile, " (DECL_RTL ");
1503ad841b2Smrg w.print_rtx (DECL_RTL_IF_SET (arg));
1513ad841b2Smrg w.finish_directive ();
1523ad841b2Smrg
1533ad841b2Smrg /* Print DECL_INCOMING_RTL. */
1543ad841b2Smrg fprintf (outfile, " (DECL_RTL_INCOMING ");
1553ad841b2Smrg w.print_rtx (DECL_INCOMING_RTL (arg));
1563ad841b2Smrg fprintf (outfile, ")");
1573ad841b2Smrg
1583ad841b2Smrg w.finish_directive ();
1593ad841b2Smrg }
1603ad841b2Smrg
1613ad841b2Smrg /* Write FN to OUTFILE in a form suitable for parsing, with indentation
1623ad841b2Smrg and comments to make the structure easy for a human to grok. Track
1633ad841b2Smrg the basic blocks of insns in the chain, wrapping those that are within
1643ad841b2Smrg blocks within "(block)" directives.
1653ad841b2Smrg
1663ad841b2Smrg If COMPACT, then instructions are printed in a compact form:
1673ad841b2Smrg - INSN_UIDs are omitted, except for jumps and CODE_LABELs,
1683ad841b2Smrg - INSN_CODEs are omitted,
1693ad841b2Smrg - register numbers are omitted for hard and virtual regs, and
1703ad841b2Smrg non-virtual pseudos are offset relative to the first such reg, and
1713ad841b2Smrg printed with a '%' sigil e.g. "%0" for (LAST_VIRTUAL_REGISTER + 1),
1723ad841b2Smrg - insn names are prefixed with "c" (e.g. "cinsn", "cnote", etc)
1733ad841b2Smrg
1743ad841b2Smrg Example output (with COMPACT==true):
1753ad841b2Smrg
1763ad841b2Smrg (function "times_two"
1773ad841b2Smrg (param "i"
1783ad841b2Smrg (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars)
1793ad841b2Smrg (const_int -4)) [1 i+0 S4 A32]))
1803ad841b2Smrg (DECL_RTL_INCOMING (reg:SI di [ i ])))
1813ad841b2Smrg (insn-chain
1823ad841b2Smrg (cnote 1 NOTE_INSN_DELETED)
1833ad841b2Smrg (block 2
1843ad841b2Smrg (edge-from entry (flags "FALLTHRU"))
1853ad841b2Smrg (cnote 4 [bb 2] NOTE_INSN_BASIC_BLOCK)
1863ad841b2Smrg (cinsn 2 (set (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars)
1873ad841b2Smrg (const_int -4)) [1 i+0 S4 A32])
1883ad841b2Smrg (reg:SI di [ i ])) "t.c":2)
1893ad841b2Smrg (cnote 3 NOTE_INSN_FUNCTION_BEG)
1903ad841b2Smrg (cinsn 6 (set (reg:SI <2>)
1913ad841b2Smrg (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars)
1923ad841b2Smrg (const_int -4)) [1 i+0 S4 A32])) "t.c":3)
1933ad841b2Smrg (cinsn 7 (parallel [
1943ad841b2Smrg (set (reg:SI <0> [ _2 ])
1953ad841b2Smrg (ashift:SI (reg:SI <2>)
1963ad841b2Smrg (const_int 1)))
1973ad841b2Smrg (clobber (reg:CC flags))
1983ad841b2Smrg ]) "t.c":3
1993ad841b2Smrg (expr_list:REG_EQUAL (ashift:SI (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars)
2003ad841b2Smrg (const_int -4)) [1 i+0 S4 A32])
2013ad841b2Smrg (const_int 1))))
2023ad841b2Smrg (cinsn 10 (set (reg:SI <1> [ <retval> ])
2033ad841b2Smrg (reg:SI <0> [ _2 ])) "t.c":3)
2043ad841b2Smrg (cinsn 14 (set (reg/i:SI ax)
2053ad841b2Smrg (reg:SI <1> [ <retval> ])) "t.c":4)
2063ad841b2Smrg (cinsn 15 (use (reg/i:SI ax)) "t.c":4)
2073ad841b2Smrg (edge-to exit (flags "FALLTHRU"))
2083ad841b2Smrg ) ;; block 2
2093ad841b2Smrg ) ;; insn-chain
2103ad841b2Smrg (crtl
2113ad841b2Smrg (return_rtx
2123ad841b2Smrg (reg/i:SI ax)
2133ad841b2Smrg ) ;; return_rtx
2143ad841b2Smrg ) ;; crtl
2153ad841b2Smrg ) ;; function "times_two"
2163ad841b2Smrg */
2173ad841b2Smrg
2183ad841b2Smrg DEBUG_FUNCTION void
print_rtx_function(FILE * outfile,function * fn,bool compact)2193ad841b2Smrg print_rtx_function (FILE *outfile, function *fn, bool compact)
2203ad841b2Smrg {
2213ad841b2Smrg rtx_reuse_manager r;
2223ad841b2Smrg rtx_writer w (outfile, 0, false, compact, &r);
2233ad841b2Smrg
2243ad841b2Smrg /* Support "reuse_rtx" in the dump. */
2253ad841b2Smrg for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
2263ad841b2Smrg r.preprocess (insn);
2273ad841b2Smrg
2283ad841b2Smrg tree fdecl = fn->decl;
2293ad841b2Smrg
230cef8759bSmrg const char *dname = lang_hooks.decl_printable_name (fdecl, 1);
2313ad841b2Smrg
2323ad841b2Smrg fprintf (outfile, "(function \"%s\"\n", dname);
2333ad841b2Smrg
2343ad841b2Smrg /* Params. */
2353ad841b2Smrg for (tree arg = DECL_ARGUMENTS (fdecl); arg; arg = DECL_CHAIN (arg))
2363ad841b2Smrg print_param (outfile, w, arg);
2373ad841b2Smrg
2383ad841b2Smrg /* The instruction chain. */
2393ad841b2Smrg fprintf (outfile, " (insn-chain\n");
2403ad841b2Smrg basic_block curr_bb = NULL;
2413ad841b2Smrg for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
2423ad841b2Smrg {
2433ad841b2Smrg basic_block insn_bb;
2443ad841b2Smrg if (can_have_basic_block_p (insn))
2453ad841b2Smrg insn_bb = BLOCK_FOR_INSN (insn);
2463ad841b2Smrg else
2473ad841b2Smrg insn_bb = NULL;
2483ad841b2Smrg if (curr_bb != insn_bb)
2493ad841b2Smrg {
2503ad841b2Smrg end_any_block (outfile, curr_bb);
2513ad841b2Smrg curr_bb = insn_bb;
2523ad841b2Smrg begin_any_block (outfile, curr_bb);
2533ad841b2Smrg }
2543ad841b2Smrg w.print_rtl_single_with_indent (insn, curr_bb ? 6 : 4);
2553ad841b2Smrg }
2563ad841b2Smrg end_any_block (outfile, curr_bb);
2573ad841b2Smrg fprintf (outfile, " ) ;; insn-chain\n");
2583ad841b2Smrg
2593ad841b2Smrg /* Additional RTL state. */
2603ad841b2Smrg fprintf (outfile, " (crtl\n");
2613ad841b2Smrg fprintf (outfile, " (return_rtx \n");
2623ad841b2Smrg w.print_rtl_single_with_indent (crtl->return_rtx, 6);
2633ad841b2Smrg fprintf (outfile, " ) ;; return_rtx\n");
2643ad841b2Smrg fprintf (outfile, " ) ;; crtl\n");
2653ad841b2Smrg
2663ad841b2Smrg fprintf (outfile, ") ;; function \"%s\"\n", dname);
2673ad841b2Smrg }
268