xref: /dflybsd-src/contrib/gcc-8.0/gcc/print-rtl-function.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj /* Print RTL functions for GCC.
2*38fd1498Szrj    Copyright (C) 2016-2018 Free Software Foundation, Inc.
3*38fd1498Szrj 
4*38fd1498Szrj This file is part of GCC.
5*38fd1498Szrj 
6*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
7*38fd1498Szrj the terms of the GNU General Public License as published by the Free
8*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
9*38fd1498Szrj version.
10*38fd1498Szrj 
11*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14*38fd1498Szrj for more details.
15*38fd1498Szrj 
16*38fd1498Szrj You should have received a copy of the GNU General Public License
17*38fd1498Szrj along with GCC; see the file COPYING3.  If not see
18*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
19*38fd1498Szrj 
20*38fd1498Szrj #include "config.h"
21*38fd1498Szrj #include "system.h"
22*38fd1498Szrj #include "coretypes.h"
23*38fd1498Szrj #include "tm.h"
24*38fd1498Szrj #include "rtl.h"
25*38fd1498Szrj #include "alias.h"
26*38fd1498Szrj #include "tree.h"
27*38fd1498Szrj #include "flags.h"
28*38fd1498Szrj #include "predict.h"
29*38fd1498Szrj #include "function.h"
30*38fd1498Szrj #include "basic-block.h"
31*38fd1498Szrj #include "print-rtl.h"
32*38fd1498Szrj #include "langhooks.h"
33*38fd1498Szrj #include "memmodel.h"
34*38fd1498Szrj #include "emit-rtl.h"
35*38fd1498Szrj #include "varasm.h"
36*38fd1498Szrj 
37*38fd1498Szrj /* Print an "(edge-from)" or "(edge-to)" directive describing E
38*38fd1498Szrj    to OUTFILE.  */
39*38fd1498Szrj 
40*38fd1498Szrj static void
print_edge(FILE * outfile,edge e,bool from)41*38fd1498Szrj print_edge (FILE *outfile, edge e, bool from)
42*38fd1498Szrj {
43*38fd1498Szrj   fprintf (outfile, "      (%s ", from ? "edge-from" : "edge-to");
44*38fd1498Szrj   basic_block bb = from ? e->src : e->dest;
45*38fd1498Szrj   gcc_assert (bb);
46*38fd1498Szrj   switch (bb->index)
47*38fd1498Szrj     {
48*38fd1498Szrj     case ENTRY_BLOCK:
49*38fd1498Szrj       fprintf (outfile, "entry");
50*38fd1498Szrj       break;
51*38fd1498Szrj     case EXIT_BLOCK:
52*38fd1498Szrj       fprintf (outfile, "exit");
53*38fd1498Szrj       break;
54*38fd1498Szrj     default:
55*38fd1498Szrj       fprintf (outfile, "%i", bb->index);
56*38fd1498Szrj       break;
57*38fd1498Szrj     }
58*38fd1498Szrj 
59*38fd1498Szrj   /* Express edge flags as a string with " | " separator.
60*38fd1498Szrj      e.g. (flags "FALLTHRU | DFS_BACK").  */
61*38fd1498Szrj   if (e->flags)
62*38fd1498Szrj     {
63*38fd1498Szrj       fprintf (outfile, " (flags \"");
64*38fd1498Szrj       bool seen_flag = false;
65*38fd1498Szrj #define DEF_EDGE_FLAG(NAME,IDX)			\
66*38fd1498Szrj   do {						\
67*38fd1498Szrj     if (e->flags & EDGE_##NAME)			\
68*38fd1498Szrj       {						\
69*38fd1498Szrj 	if (seen_flag)				\
70*38fd1498Szrj 	  fprintf (outfile, " | ");		\
71*38fd1498Szrj 	fprintf (outfile, "%s", (#NAME));	\
72*38fd1498Szrj 	seen_flag = true;			\
73*38fd1498Szrj       }						\
74*38fd1498Szrj   } while (0);
75*38fd1498Szrj #include "cfg-flags.def"
76*38fd1498Szrj #undef DEF_EDGE_FLAG
77*38fd1498Szrj 
78*38fd1498Szrj       fprintf (outfile, "\")");
79*38fd1498Szrj     }
80*38fd1498Szrj 
81*38fd1498Szrj   fprintf (outfile, ")\n");
82*38fd1498Szrj }
83*38fd1498Szrj 
84*38fd1498Szrj /* If BB is non-NULL, print the start of a "(block)" directive for it
85*38fd1498Szrj    to OUTFILE, otherwise do nothing.  */
86*38fd1498Szrj 
87*38fd1498Szrj static void
begin_any_block(FILE * outfile,basic_block bb)88*38fd1498Szrj begin_any_block (FILE *outfile, basic_block bb)
89*38fd1498Szrj {
90*38fd1498Szrj   if (!bb)
91*38fd1498Szrj     return;
92*38fd1498Szrj 
93*38fd1498Szrj   edge e;
94*38fd1498Szrj   edge_iterator ei;
95*38fd1498Szrj 
96*38fd1498Szrj   fprintf (outfile, "    (block %i\n", bb->index);
97*38fd1498Szrj   FOR_EACH_EDGE (e, ei, bb->preds)
98*38fd1498Szrj     print_edge (outfile, e, true);
99*38fd1498Szrj }
100*38fd1498Szrj 
101*38fd1498Szrj /* If BB is non-NULL, print the end of a "(block)" directive for it
102*38fd1498Szrj    to OUTFILE, otherwise do nothing.  */
103*38fd1498Szrj 
104*38fd1498Szrj static void
end_any_block(FILE * outfile,basic_block bb)105*38fd1498Szrj end_any_block (FILE *outfile, basic_block bb)
106*38fd1498Szrj {
107*38fd1498Szrj   if (!bb)
108*38fd1498Szrj     return;
109*38fd1498Szrj 
110*38fd1498Szrj   edge e;
111*38fd1498Szrj   edge_iterator ei;
112*38fd1498Szrj 
113*38fd1498Szrj   FOR_EACH_EDGE (e, ei, bb->succs)
114*38fd1498Szrj     print_edge (outfile, e, false);
115*38fd1498Szrj   fprintf (outfile, "    ) ;; block %i\n", bb->index);
116*38fd1498Szrj }
117*38fd1498Szrj 
118*38fd1498Szrj /* Determine if INSN is of a kind that can have a basic block.  */
119*38fd1498Szrj 
120*38fd1498Szrj static bool
can_have_basic_block_p(const rtx_insn * insn)121*38fd1498Szrj can_have_basic_block_p (const rtx_insn *insn)
122*38fd1498Szrj {
123*38fd1498Szrj   rtx_code code = GET_CODE (insn);
124*38fd1498Szrj   if (code == BARRIER)
125*38fd1498Szrj     return false;
126*38fd1498Szrj   gcc_assert (GET_RTX_FORMAT (code)[2] == 'B');
127*38fd1498Szrj   return true;
128*38fd1498Szrj }
129*38fd1498Szrj 
130*38fd1498Szrj /* Subroutine of print_param.  Write the name of ARG, if any, to OUTFILE.  */
131*38fd1498Szrj 
132*38fd1498Szrj static void
print_any_param_name(FILE * outfile,tree arg)133*38fd1498Szrj print_any_param_name (FILE *outfile, tree arg)
134*38fd1498Szrj {
135*38fd1498Szrj   if (DECL_NAME (arg))
136*38fd1498Szrj     fprintf (outfile, " \"%s\"", IDENTIFIER_POINTER (DECL_NAME (arg)));
137*38fd1498Szrj }
138*38fd1498Szrj 
139*38fd1498Szrj /* Print a "(param)" directive for ARG to OUTFILE.  */
140*38fd1498Szrj 
141*38fd1498Szrj static void
print_param(FILE * outfile,rtx_writer & w,tree arg)142*38fd1498Szrj print_param (FILE *outfile, rtx_writer &w, tree arg)
143*38fd1498Szrj {
144*38fd1498Szrj   fprintf (outfile, "  (param");
145*38fd1498Szrj   print_any_param_name (outfile, arg);
146*38fd1498Szrj   fprintf (outfile, "\n");
147*38fd1498Szrj 
148*38fd1498Szrj   /* Print the value of DECL_RTL (without lazy-evaluation).  */
149*38fd1498Szrj   fprintf (outfile, "    (DECL_RTL ");
150*38fd1498Szrj   w.print_rtx (DECL_RTL_IF_SET (arg));
151*38fd1498Szrj   w.finish_directive ();
152*38fd1498Szrj 
153*38fd1498Szrj   /* Print DECL_INCOMING_RTL.  */
154*38fd1498Szrj   fprintf (outfile, "    (DECL_RTL_INCOMING ");
155*38fd1498Szrj   w.print_rtx (DECL_INCOMING_RTL (arg));
156*38fd1498Szrj   fprintf (outfile, ")");
157*38fd1498Szrj 
158*38fd1498Szrj   w.finish_directive ();
159*38fd1498Szrj }
160*38fd1498Szrj 
161*38fd1498Szrj /* Write FN to OUTFILE in a form suitable for parsing, with indentation
162*38fd1498Szrj    and comments to make the structure easy for a human to grok.  Track
163*38fd1498Szrj    the basic blocks of insns in the chain, wrapping those that are within
164*38fd1498Szrj    blocks within "(block)" directives.
165*38fd1498Szrj 
166*38fd1498Szrj    If COMPACT, then instructions are printed in a compact form:
167*38fd1498Szrj    - INSN_UIDs are omitted, except for jumps and CODE_LABELs,
168*38fd1498Szrj    - INSN_CODEs are omitted,
169*38fd1498Szrj    - register numbers are omitted for hard and virtual regs, and
170*38fd1498Szrj      non-virtual pseudos are offset relative to the first such reg, and
171*38fd1498Szrj      printed with a '%' sigil e.g. "%0" for (LAST_VIRTUAL_REGISTER + 1),
172*38fd1498Szrj    - insn names are prefixed with "c" (e.g. "cinsn", "cnote", etc)
173*38fd1498Szrj 
174*38fd1498Szrj    Example output (with COMPACT==true):
175*38fd1498Szrj 
176*38fd1498Szrj    (function "times_two"
177*38fd1498Szrj      (param "i"
178*38fd1498Szrj        (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars)
179*38fd1498Szrj 	   (const_int -4)) [1 i+0 S4 A32]))
180*38fd1498Szrj        (DECL_RTL_INCOMING (reg:SI di [ i ])))
181*38fd1498Szrj      (insn-chain
182*38fd1498Szrj        (cnote 1 NOTE_INSN_DELETED)
183*38fd1498Szrj        (block 2
184*38fd1498Szrj 	 (edge-from entry (flags "FALLTHRU"))
185*38fd1498Szrj 	 (cnote 4 [bb 2] NOTE_INSN_BASIC_BLOCK)
186*38fd1498Szrj 	 (cinsn 2 (set (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars)
187*38fd1498Szrj 			       (const_int -4)) [1 i+0 S4 A32])
188*38fd1498Szrj 		       (reg:SI di [ i ])) "t.c":2)
189*38fd1498Szrj 	 (cnote 3 NOTE_INSN_FUNCTION_BEG)
190*38fd1498Szrj 	 (cinsn 6 (set (reg:SI <2>)
191*38fd1498Szrj 		       (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars)
192*38fd1498Szrj 			       (const_int -4)) [1 i+0 S4 A32])) "t.c":3)
193*38fd1498Szrj 	 (cinsn 7 (parallel [
194*38fd1498Szrj 			   (set (reg:SI <0> [ _2 ])
195*38fd1498Szrj 			       (ashift:SI (reg:SI <2>)
196*38fd1498Szrj 				   (const_int 1)))
197*38fd1498Szrj 			   (clobber (reg:CC flags))
198*38fd1498Szrj 		       ]) "t.c":3
199*38fd1498Szrj 		    (expr_list:REG_EQUAL (ashift:SI (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars)
200*38fd1498Szrj 				   (const_int -4)) [1 i+0 S4 A32])
201*38fd1498Szrj 			   (const_int 1))))
202*38fd1498Szrj 	 (cinsn 10 (set (reg:SI <1> [ <retval> ])
203*38fd1498Szrj 		       (reg:SI <0> [ _2 ])) "t.c":3)
204*38fd1498Szrj 	 (cinsn 14 (set (reg/i:SI ax)
205*38fd1498Szrj 		       (reg:SI <1> [ <retval> ])) "t.c":4)
206*38fd1498Szrj 	 (cinsn 15 (use (reg/i:SI ax)) "t.c":4)
207*38fd1498Szrj 	 (edge-to exit (flags "FALLTHRU"))
208*38fd1498Szrj        ) ;; block 2
209*38fd1498Szrj      ) ;; insn-chain
210*38fd1498Szrj      (crtl
211*38fd1498Szrj        (return_rtx
212*38fd1498Szrj 	 (reg/i:SI ax)
213*38fd1498Szrj        ) ;; return_rtx
214*38fd1498Szrj      ) ;; crtl
215*38fd1498Szrj    ) ;; function "times_two"
216*38fd1498Szrj */
217*38fd1498Szrj 
218*38fd1498Szrj DEBUG_FUNCTION void
print_rtx_function(FILE * outfile,function * fn,bool compact)219*38fd1498Szrj print_rtx_function (FILE *outfile, function *fn, bool compact)
220*38fd1498Szrj {
221*38fd1498Szrj   rtx_reuse_manager r;
222*38fd1498Szrj   rtx_writer w (outfile, 0, false, compact, &r);
223*38fd1498Szrj 
224*38fd1498Szrj   /* Support "reuse_rtx" in the dump.  */
225*38fd1498Szrj   for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
226*38fd1498Szrj     r.preprocess (insn);
227*38fd1498Szrj 
228*38fd1498Szrj   tree fdecl = fn->decl;
229*38fd1498Szrj 
230*38fd1498Szrj   const char *dname = lang_hooks.decl_printable_name (fdecl, 1);
231*38fd1498Szrj 
232*38fd1498Szrj   fprintf (outfile, "(function \"%s\"\n", dname);
233*38fd1498Szrj 
234*38fd1498Szrj   /* Params.  */
235*38fd1498Szrj   for (tree arg = DECL_ARGUMENTS (fdecl); arg; arg = DECL_CHAIN (arg))
236*38fd1498Szrj     print_param (outfile, w, arg);
237*38fd1498Szrj 
238*38fd1498Szrj   /* The instruction chain.  */
239*38fd1498Szrj   fprintf (outfile, "  (insn-chain\n");
240*38fd1498Szrj   basic_block curr_bb = NULL;
241*38fd1498Szrj   for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
242*38fd1498Szrj     {
243*38fd1498Szrj       basic_block insn_bb;
244*38fd1498Szrj       if (can_have_basic_block_p (insn))
245*38fd1498Szrj 	insn_bb = BLOCK_FOR_INSN (insn);
246*38fd1498Szrj       else
247*38fd1498Szrj 	insn_bb = NULL;
248*38fd1498Szrj       if (curr_bb != insn_bb)
249*38fd1498Szrj 	{
250*38fd1498Szrj 	  end_any_block (outfile, curr_bb);
251*38fd1498Szrj 	  curr_bb = insn_bb;
252*38fd1498Szrj 	  begin_any_block (outfile, curr_bb);
253*38fd1498Szrj 	}
254*38fd1498Szrj       w.print_rtl_single_with_indent (insn, curr_bb ? 6 : 4);
255*38fd1498Szrj     }
256*38fd1498Szrj   end_any_block (outfile, curr_bb);
257*38fd1498Szrj   fprintf (outfile, "  ) ;; insn-chain\n");
258*38fd1498Szrj 
259*38fd1498Szrj   /* Additional RTL state.  */
260*38fd1498Szrj   fprintf (outfile, "  (crtl\n");
261*38fd1498Szrj   fprintf (outfile, "    (return_rtx \n");
262*38fd1498Szrj   w.print_rtl_single_with_indent (crtl->return_rtx, 6);
263*38fd1498Szrj   fprintf (outfile, "    ) ;; return_rtx\n");
264*38fd1498Szrj   fprintf (outfile, "  ) ;; crtl\n");
265*38fd1498Szrj 
266*38fd1498Szrj   fprintf (outfile, ") ;; function \"%s\"\n", dname);
267*38fd1498Szrj }
268