1132718Skan/* Print RTL for GCC.
2169689Skan   Copyright (C) 1987, 1988, 1992, 1997, 1998, 1999, 2000, 2002, 2003,
3169689Skan   2004, 2005
490075Sobrien   Free Software Foundation, Inc.
518334Speter
690075SobrienThis file is part of GCC.
718334Speter
890075SobrienGCC is free software; you can redistribute it and/or modify it under
990075Sobrienthe terms of the GNU General Public License as published by the Free
1090075SobrienSoftware Foundation; either version 2, or (at your option) any later
1190075Sobrienversion.
1218334Speter
1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1590075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1690075Sobrienfor more details.
1718334Speter
1818334SpeterYou should have received a copy of the GNU General Public License
1990075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21169689Skan02110-1301, USA.  */
2218334Speter
23169689Skan/* This file is compiled twice: once for the generator programs,
24169689Skan   once for the compiler.  */
25169689Skan#ifdef GENERATOR_FILE
26169689Skan#include "bconfig.h"
27169689Skan#else
28169689Skan#include "config.h"
29169689Skan#endif
3018334Speter
3150397Sobrien#include "system.h"
32132718Skan#include "coretypes.h"
33132718Skan#include "tm.h"
3418334Speter#include "rtl.h"
3590075Sobrien
36169689Skan/* These headers all define things which are not available in
37169689Skan   generator programs.  */
38169689Skan#ifndef GENERATOR_FILE
3990075Sobrien#include "tree.h"
4050397Sobrien#include "real.h"
4152284Sobrien#include "flags.h"
4290075Sobrien#include "hard-reg-set.h"
4352284Sobrien#include "basic-block.h"
44169689Skan#endif
4518334Speter
4618334Speterstatic FILE *outfile;
4718334Speter
4818334Speterstatic int sawclose = 0;
4918334Speter
5050397Sobrienstatic int indent;
5150397Sobrien
52132718Skanstatic void print_rtx (rtx);
5318334Speter
5490075Sobrien/* String printed at beginning of each RTL when it is dumped.
5590075Sobrien   This string is set to ASM_COMMENT_START when the RTL is dumped in
5690075Sobrien   the assembly output file.  */
5790075Sobrienconst char *print_rtx_head = "";
5818334Speter
5952284Sobrien/* Nonzero means suppress output of instruction numbers and line number
6052284Sobrien   notes in debugging dumps.
6152284Sobrien   This must be defined here so that programs like gencodes can be linked.  */
6250397Sobrienint flag_dump_unnumbered = 0;
6352284Sobrien
6490075Sobrien/* Nonzero means use simplified format without flags, modes, etc.  */
6590075Sobrienint flag_simple = 0;
6690075Sobrien
6752284Sobrien/* Nonzero if we are dumping graphical description.  */
6852284Sobrienint dump_for_graph;
6952284Sobrien
70169689Skan#ifndef GENERATOR_FILE
71169689Skanstatic void
72169689Skanprint_decl_name (FILE *outfile, tree node)
73169689Skan{
74169689Skan  if (DECL_NAME (node))
75169689Skan    fputs (IDENTIFIER_POINTER (DECL_NAME (node)), outfile);
76169689Skan  else
77169689Skan    {
78169689Skan      if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1)
79169689Skan	fprintf (outfile, "L." HOST_WIDE_INT_PRINT_DEC, LABEL_DECL_UID (node));
80169689Skan      else
81169689Skan        {
82169689Skan          char c = TREE_CODE (node) == CONST_DECL ? 'C' : 'D';
83169689Skan	  fprintf (outfile, "%c.%u", c, DECL_UID (node));
84169689Skan        }
85169689Skan    }
86169689Skan}
8790075Sobrien
8890075Sobrienvoid
89132718Skanprint_mem_expr (FILE *outfile, tree expr)
9090075Sobrien{
9190075Sobrien  if (TREE_CODE (expr) == COMPONENT_REF)
9290075Sobrien    {
9390075Sobrien      if (TREE_OPERAND (expr, 0))
94117395Skan	print_mem_expr (outfile, TREE_OPERAND (expr, 0));
9590075Sobrien      else
9690075Sobrien	fputs (" <variable>", outfile);
97169689Skan      fputc ('.', outfile);
98169689Skan      print_decl_name (outfile, TREE_OPERAND (expr, 1));
9990075Sobrien    }
100110611Skan  else if (TREE_CODE (expr) == INDIRECT_REF)
101110611Skan    {
102110611Skan      fputs (" (*", outfile);
103110611Skan      print_mem_expr (outfile, TREE_OPERAND (expr, 0));
104110611Skan      fputs (")", outfile);
105110611Skan    }
106169689Skan  else if (TREE_CODE (expr) == ALIGN_INDIRECT_REF)
107169689Skan    {
108169689Skan      fputs (" (A*", outfile);
109169689Skan      print_mem_expr (outfile, TREE_OPERAND (expr, 0));
110169689Skan      fputs (")", outfile);
111169689Skan    }
112169689Skan  else if (TREE_CODE (expr) == MISALIGNED_INDIRECT_REF)
113169689Skan    {
114169689Skan      fputs (" (M*", outfile);
115169689Skan      print_mem_expr (outfile, TREE_OPERAND (expr, 0));
116169689Skan      fputs (")", outfile);
117169689Skan    }
11890075Sobrien  else if (TREE_CODE (expr) == RESULT_DECL)
11990075Sobrien    fputs (" <result>", outfile);
12090075Sobrien  else
121169689Skan    {
122169689Skan      fputc (' ', outfile);
123169689Skan      print_decl_name (outfile, expr);
124169689Skan    }
12590075Sobrien}
126169689Skan#endif
12790075Sobrien
12818334Speter/* Print IN_RTX onto OUTFILE.  This is the recursive part of printing.  */
12918334Speter
13018334Speterstatic void
131132718Skanprint_rtx (rtx in_rtx)
13218334Speter{
13390075Sobrien  int i = 0;
13490075Sobrien  int j;
13590075Sobrien  const char *format_ptr;
13690075Sobrien  int is_insn;
13718334Speter
13818334Speter  if (sawclose)
13918334Speter    {
14090075Sobrien      if (flag_simple)
14190075Sobrien	fputc (' ', outfile);
14290075Sobrien      else
14390075Sobrien	fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, "");
14418334Speter      sawclose = 0;
14518334Speter    }
14618334Speter
14718334Speter  if (in_rtx == 0)
14818334Speter    {
14952284Sobrien      fputs ("(nil)", outfile);
15018334Speter      sawclose = 1;
15118334Speter      return;
15218334Speter    }
15390075Sobrien  else if (GET_CODE (in_rtx) > NUM_RTX_CODE)
15490075Sobrien    {
15590075Sobrien       fprintf (outfile, "(??? bad code %d\n)", GET_CODE (in_rtx));
15690075Sobrien       sawclose = 1;
15790075Sobrien       return;
15890075Sobrien    }
15918334Speter
16090075Sobrien  is_insn = INSN_P (in_rtx);
16118334Speter
16252284Sobrien  /* When printing in VCG format we write INSNs, NOTE, LABEL, and BARRIER
16352284Sobrien     in separate nodes and therefore have to handle them special here.  */
16490075Sobrien  if (dump_for_graph
165169689Skan      && (is_insn || NOTE_P (in_rtx)
166169689Skan	  || LABEL_P (in_rtx) || BARRIER_P (in_rtx)))
16752284Sobrien    {
16852284Sobrien      i = 3;
16952284Sobrien      indent = 0;
17052284Sobrien    }
17152284Sobrien  else
17252284Sobrien    {
17390075Sobrien      /* Print name of expression code.  */
17490075Sobrien      if (flag_simple && GET_CODE (in_rtx) == CONST_INT)
17590075Sobrien	fputc ('(', outfile);
17690075Sobrien      else
17790075Sobrien	fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));
178117395Skan
17990075Sobrien      if (! flag_simple)
18090075Sobrien	{
181117395Skan	  if (RTX_FLAG (in_rtx, in_struct))
18290075Sobrien	    fputs ("/s", outfile);
18318334Speter
184117395Skan	  if (RTX_FLAG (in_rtx, volatil))
18590075Sobrien	    fputs ("/v", outfile);
186117395Skan
187117395Skan	  if (RTX_FLAG (in_rtx, unchanging))
18890075Sobrien	    fputs ("/u", outfile);
189117395Skan
190117395Skan	  if (RTX_FLAG (in_rtx, frame_related))
19190075Sobrien	    fputs ("/f", outfile);
192117395Skan
193117395Skan	  if (RTX_FLAG (in_rtx, jump))
19490075Sobrien	    fputs ("/j", outfile);
195117395Skan
196117395Skan	  if (RTX_FLAG (in_rtx, call))
19790075Sobrien	    fputs ("/c", outfile);
19818334Speter
199169689Skan	  if (RTX_FLAG (in_rtx, return_val))
200169689Skan	    fputs ("/i", outfile);
201169689Skan
202169689Skan	  /* Print REG_NOTE names for EXPR_LIST and INSN_LIST.  */
203169689Skan	  if (GET_CODE (in_rtx) == EXPR_LIST
204169689Skan	      || GET_CODE (in_rtx) == INSN_LIST)
205169689Skan	    fprintf (outfile, ":%s",
206169689Skan		     GET_REG_NOTE_NAME (GET_MODE (in_rtx)));
207169689Skan
208169689Skan	  /* For other rtl, print the mode if it's not VOID.  */
209169689Skan	  else if (GET_MODE (in_rtx) != VOIDmode)
210169689Skan	    fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));
21152284Sobrien	}
21218334Speter    }
21318334Speter
214117395Skan#ifndef GENERATOR_FILE
215117395Skan  if (GET_CODE (in_rtx) == CONST_DOUBLE && FLOAT_MODE_P (GET_MODE (in_rtx)))
216117395Skan    i = 5;
217117395Skan#endif
218117395Skan
21952284Sobrien  /* Get the format string and skip the first elements if we have handled
22052284Sobrien     them already.  */
22152284Sobrien  format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)) + i;
22252284Sobrien  for (; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)
22318334Speter    switch (*format_ptr++)
22418334Speter      {
22590075Sobrien	const char *str;
22690075Sobrien
22790075Sobrien      case 'T':
22890075Sobrien	str = XTMPL (in_rtx, i);
22990075Sobrien	goto string;
23090075Sobrien
23118334Speter      case 'S':
23218334Speter      case 's':
23390075Sobrien	str = XSTR (in_rtx, i);
23490075Sobrien      string:
23590075Sobrien
23690075Sobrien	if (str == 0)
23790075Sobrien	  fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile);
23890075Sobrien	else
23950397Sobrien	  {
24090075Sobrien	    if (dump_for_graph)
24190075Sobrien	      fprintf (outfile, " (\\\"%s\\\")", str);
24290075Sobrien	    else
24390075Sobrien	      fprintf (outfile, " (\"%s\")", str);
24450397Sobrien	  }
24590075Sobrien	sawclose = 1;
24690075Sobrien	break;
24750397Sobrien
24890075Sobrien	/* 0 indicates a field for internal use that should not be printed.
24990075Sobrien	   An exception is the third field of a NOTE, where it indicates
25090075Sobrien	   that the field has several different valid contents.  */
25190075Sobrien      case '0':
252169689Skan	if (i == 1 && REG_P (in_rtx))
25350397Sobrien	  {
25490075Sobrien	    if (REGNO (in_rtx) != ORIGINAL_REGNO (in_rtx))
25590075Sobrien	      fprintf (outfile, " [%d]", ORIGINAL_REGNO (in_rtx));
25650397Sobrien	  }
257132718Skan#ifndef GENERATOR_FILE
258132718Skan	else if (i == 1 && GET_CODE (in_rtx) == SYMBOL_REF)
25950397Sobrien	  {
260132718Skan	    int flags = SYMBOL_REF_FLAGS (in_rtx);
261132718Skan	    if (flags)
262132718Skan	      fprintf (outfile, " [flags 0x%x]", flags);
263132718Skan	  }
264132718Skan	else if (i == 2 && GET_CODE (in_rtx) == SYMBOL_REF)
265132718Skan	  {
266132718Skan	    tree decl = SYMBOL_REF_DECL (in_rtx);
267132718Skan	    if (decl)
268132718Skan	      print_node_brief (outfile, "", decl, 0);
269132718Skan	  }
270132718Skan#endif
271169689Skan	else if (i == 4 && NOTE_P (in_rtx))
272132718Skan	  {
27390075Sobrien	    switch (NOTE_LINE_NUMBER (in_rtx))
27490075Sobrien	      {
27590075Sobrien	      case NOTE_INSN_EH_REGION_BEG:
27690075Sobrien	      case NOTE_INSN_EH_REGION_END:
27790075Sobrien		if (flag_dump_unnumbered)
27890075Sobrien		  fprintf (outfile, " #");
27990075Sobrien		else
28090075Sobrien		  fprintf (outfile, " %d", NOTE_EH_HANDLER (in_rtx));
28190075Sobrien		sawclose = 1;
28290075Sobrien		break;
28350397Sobrien
28490075Sobrien	      case NOTE_INSN_BLOCK_BEG:
28590075Sobrien	      case NOTE_INSN_BLOCK_END:
286169689Skan#ifndef GENERATOR_FILE
287169689Skan		dump_addr (outfile, " ", NOTE_BLOCK (in_rtx));
288169689Skan#endif
28990075Sobrien		sawclose = 1;
29090075Sobrien		break;
29118334Speter
29290075Sobrien	      case NOTE_INSN_BASIC_BLOCK:
29390075Sobrien		{
294169689Skan#ifndef GENERATOR_FILE
29590075Sobrien		  basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
29690075Sobrien		  if (bb != 0)
29790075Sobrien		    fprintf (outfile, " [bb %d]", bb->index);
298169689Skan#endif
29990075Sobrien		  break;
30090075Sobrien	        }
30190075Sobrien
30290075Sobrien	      case NOTE_INSN_EXPECTED_VALUE:
30390075Sobrien		indent += 2;
30490075Sobrien		if (!sawclose)
30590075Sobrien		  fprintf (outfile, " ");
30690075Sobrien		print_rtx (NOTE_EXPECTED_VALUE (in_rtx));
30790075Sobrien		indent -= 2;
30890075Sobrien		break;
30990075Sobrien
31090075Sobrien	      case NOTE_INSN_DELETED_LABEL:
311169689Skan		{
312169689Skan		  const char *label = NOTE_DELETED_LABEL_NAME (in_rtx);
313169689Skan		  if (label)
314169689Skan		    fprintf (outfile, " (\"%s\")", label);
315169689Skan		  else
316169689Skan		    fprintf (outfile, " \"\"");
317169689Skan		}
31890075Sobrien		break;
31990075Sobrien
320169689Skan	      case NOTE_INSN_SWITCH_TEXT_SECTIONS:
321169689Skan		{
322169689Skan#ifndef GENERATOR_FILE
323169689Skan		  basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
324169689Skan		  if (bb != 0)
325169689Skan		    fprintf (outfile, " [bb %d]", bb->index);
326169689Skan#endif
327169689Skan		  break;
328169689Skan		}
329169689Skan
330169689Skan	      case NOTE_INSN_VAR_LOCATION:
331169689Skan#ifndef GENERATOR_FILE
332169689Skan		fprintf (outfile, " (");
333169689Skan		print_mem_expr (outfile, NOTE_VAR_LOCATION_DECL (in_rtx));
334169689Skan		fprintf (outfile, " ");
335169689Skan		print_rtx (NOTE_VAR_LOCATION_LOC (in_rtx));
336169689Skan		fprintf (outfile, ")");
337169689Skan#endif
338117395Skan		break;
339117395Skan
34090075Sobrien	      default:
34190075Sobrien		{
34290075Sobrien		  const char * const str = X0STR (in_rtx, i);
34390075Sobrien
34490075Sobrien		  if (NOTE_LINE_NUMBER (in_rtx) < 0)
34590075Sobrien		    ;
34690075Sobrien		  else if (str == 0)
34790075Sobrien		    fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile);
34890075Sobrien		  else
34990075Sobrien		    {
35090075Sobrien		      if (dump_for_graph)
35190075Sobrien		        fprintf (outfile, " (\\\"%s\\\")", str);
35290075Sobrien		      else
35390075Sobrien		        fprintf (outfile, " (\"%s\")", str);
35490075Sobrien		    }
35590075Sobrien		  break;
35690075Sobrien		}
35790075Sobrien	      }
35890075Sobrien	  }
35918334Speter	break;
36018334Speter
36118334Speter      case 'e':
36290075Sobrien      do_e:
36318334Speter	indent += 2;
36418334Speter	if (!sawclose)
36518334Speter	  fprintf (outfile, " ");
36618334Speter	print_rtx (XEXP (in_rtx, i));
36718334Speter	indent -= 2;
36818334Speter	break;
36918334Speter
37018334Speter      case 'E':
37118334Speter      case 'V':
37218334Speter	indent += 2;
37318334Speter	if (sawclose)
37418334Speter	  {
37590075Sobrien	    fprintf (outfile, "\n%s%*s",
376117395Skan		     print_rtx_head, indent * 2, "");
37718334Speter	    sawclose = 0;
37818334Speter	  }
379117395Skan	fputs (" [", outfile);
38018334Speter	if (NULL != XVEC (in_rtx, i))
38118334Speter	  {
38218334Speter	    indent += 2;
38318334Speter	    if (XVECLEN (in_rtx, i))
38418334Speter	      sawclose = 1;
38518334Speter
38618334Speter	    for (j = 0; j < XVECLEN (in_rtx, i); j++)
38718334Speter	      print_rtx (XVECEXP (in_rtx, i, j));
38818334Speter
38918334Speter	    indent -= 2;
39018334Speter	  }
39118334Speter	if (sawclose)
39290075Sobrien	  fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, "");
39318334Speter
394117395Skan	fputs ("]", outfile);
39518334Speter	sawclose = 1;
39618334Speter	indent -= 2;
39718334Speter	break;
39818334Speter
39918334Speter      case 'w':
40090075Sobrien	if (! flag_simple)
40190075Sobrien	  fprintf (outfile, " ");
40250397Sobrien	fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, XWINT (in_rtx, i));
40390075Sobrien	if (! flag_simple)
404132718Skan	  fprintf (outfile, " [" HOST_WIDE_INT_PRINT_HEX "]",
405132718Skan		   XWINT (in_rtx, i));
40618334Speter	break;
40718334Speter
40818334Speter      case 'i':
409132718Skan	if (i == 4 && INSN_P (in_rtx))
41090075Sobrien	  {
411132718Skan#ifndef GENERATOR_FILE
412132718Skan	    /*  Pretty-print insn locators.  Ignore scoping as it is mostly
413132718Skan		redundant with line number information and do not print anything
414132718Skan		when there is no location information available.  */
415132718Skan	    if (INSN_LOCATOR (in_rtx) && insn_file (in_rtx))
416132718Skan	      fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx));
417132718Skan#endif
418132718Skan	  }
419169689Skan	else if (i == 6 && NOTE_P (in_rtx))
420132718Skan	  {
42190075Sobrien	    /* This field is only used for NOTE_INSN_DELETED_LABEL, and
42290075Sobrien	       other times often contains garbage from INSN->NOTE death.  */
42390075Sobrien	    if (NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_DELETED_LABEL)
42490075Sobrien	      fprintf (outfile, " %d",  XINT (in_rtx, i));
42590075Sobrien	  }
42690075Sobrien	else
42790075Sobrien	  {
42890075Sobrien	    int value = XINT (in_rtx, i);
42990075Sobrien	    const char *name;
43018334Speter
431132718Skan#ifndef GENERATOR_FILE
432169689Skan	    if (REG_P (in_rtx) && value < FIRST_PSEUDO_REGISTER)
433132718Skan	      fprintf (outfile, " %d %s", REGNO (in_rtx),
434132718Skan		       reg_names[REGNO (in_rtx)]);
435169689Skan	    else if (REG_P (in_rtx)
43690075Sobrien		     && value <= LAST_VIRTUAL_REGISTER)
43790075Sobrien	      {
43890075Sobrien		if (value == VIRTUAL_INCOMING_ARGS_REGNUM)
43990075Sobrien		  fprintf (outfile, " %d virtual-incoming-args", value);
44090075Sobrien		else if (value == VIRTUAL_STACK_VARS_REGNUM)
44190075Sobrien		  fprintf (outfile, " %d virtual-stack-vars", value);
44290075Sobrien		else if (value == VIRTUAL_STACK_DYNAMIC_REGNUM)
44390075Sobrien		  fprintf (outfile, " %d virtual-stack-dynamic", value);
44490075Sobrien		else if (value == VIRTUAL_OUTGOING_ARGS_REGNUM)
44590075Sobrien		  fprintf (outfile, " %d virtual-outgoing-args", value);
44690075Sobrien		else if (value == VIRTUAL_CFA_REGNUM)
44790075Sobrien		  fprintf (outfile, " %d virtual-cfa", value);
44890075Sobrien		else
44990075Sobrien		  fprintf (outfile, " %d virtual-reg-%d", value,
45090075Sobrien			   value-FIRST_VIRTUAL_REGISTER);
45190075Sobrien	      }
452132718Skan	    else
453132718Skan#endif
454132718Skan	      if (flag_dump_unnumbered
455169689Skan		     && (is_insn || NOTE_P (in_rtx)))
45690075Sobrien	      fputc ('#', outfile);
45790075Sobrien	    else
45890075Sobrien	      fprintf (outfile, " %d", value);
45990075Sobrien
460169689Skan#ifndef GENERATOR_FILE
461169689Skan	    if (REG_P (in_rtx) && REG_ATTRS (in_rtx))
462132718Skan	      {
463132718Skan		fputs (" [", outfile);
464132718Skan		if (ORIGINAL_REGNO (in_rtx) != REGNO (in_rtx))
465132718Skan		  fprintf (outfile, "orig:%i", ORIGINAL_REGNO (in_rtx));
466132718Skan		if (REG_EXPR (in_rtx))
467132718Skan		  print_mem_expr (outfile, REG_EXPR (in_rtx));
468132718Skan
469132718Skan		if (REG_OFFSET (in_rtx))
470132718Skan		  fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC,
471132718Skan			   REG_OFFSET (in_rtx));
472132718Skan		fputs (" ]", outfile);
473132718Skan	      }
474169689Skan#endif
475132718Skan
47690075Sobrien	    if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, i)
47790075Sobrien		&& XINT (in_rtx, i) >= 0
47890075Sobrien		&& (name = get_insn_name (XINT (in_rtx, i))) != NULL)
47990075Sobrien	      fprintf (outfile, " {%s}", name);
48090075Sobrien	    sawclose = 0;
48190075Sobrien	  }
48218334Speter	break;
48318334Speter
48418334Speter      /* Print NOTE_INSN names rather than integer codes.  */
48518334Speter
48618334Speter      case 'n':
48790075Sobrien	if (XINT (in_rtx, i) >= (int) NOTE_INSN_BIAS
48890075Sobrien	    && XINT (in_rtx, i) < (int) NOTE_INSN_MAX)
48918334Speter	  fprintf (outfile, " %s", GET_NOTE_INSN_NAME (XINT (in_rtx, i)));
49018334Speter	else
49118334Speter	  fprintf (outfile, " %d", XINT (in_rtx, i));
49218334Speter	sawclose = 0;
49318334Speter	break;
49418334Speter
49518334Speter      case 'u':
49618334Speter	if (XEXP (in_rtx, i) != NULL)
49750397Sobrien	  {
49890075Sobrien	    rtx sub = XEXP (in_rtx, i);
49990075Sobrien	    enum rtx_code subc = GET_CODE (sub);
50090075Sobrien
50190075Sobrien	    if (GET_CODE (in_rtx) == LABEL_REF)
50290075Sobrien	      {
50390075Sobrien		if (subc == NOTE
50490075Sobrien		    && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
50590075Sobrien		  {
50690075Sobrien		    if (flag_dump_unnumbered)
50790075Sobrien		      fprintf (outfile, " [# deleted]");
50890075Sobrien		    else
50990075Sobrien		      fprintf (outfile, " [%d deleted]", INSN_UID (sub));
51090075Sobrien		    sawclose = 0;
51190075Sobrien		    break;
51290075Sobrien		  }
51390075Sobrien
51490075Sobrien		if (subc != CODE_LABEL)
51590075Sobrien		  goto do_e;
51690075Sobrien	      }
51790075Sobrien
51850397Sobrien	    if (flag_dump_unnumbered)
51990075Sobrien	      fputs (" #", outfile);
52050397Sobrien	    else
52190075Sobrien	      fprintf (outfile, " %d", INSN_UID (sub));
52250397Sobrien	  }
52318334Speter	else
52452284Sobrien	  fputs (" 0", outfile);
52518334Speter	sawclose = 0;
52618334Speter	break;
52718334Speter
52850397Sobrien      case 'b':
529169689Skan#ifndef GENERATOR_FILE
53050397Sobrien	if (XBITMAP (in_rtx, i) == NULL)
53152284Sobrien	  fputs (" {null}", outfile);
53250397Sobrien	else
53350397Sobrien	  bitmap_print (outfile, XBITMAP (in_rtx, i), " {", "}");
534169689Skan#endif
53550397Sobrien	sawclose = 0;
53650397Sobrien	break;
53750397Sobrien
53850397Sobrien      case 't':
539169689Skan#ifndef GENERATOR_FILE
540169689Skan	dump_addr (outfile, " ", XTREE (in_rtx, i));
541169689Skan#endif
54250397Sobrien	break;
54350397Sobrien
54418334Speter      case '*':
54552284Sobrien	fputs (" Unknown", outfile);
54618334Speter	sawclose = 0;
54718334Speter	break;
54818334Speter
549117395Skan      case 'B':
550169689Skan#ifndef GENERATOR_FILE
551117395Skan	if (XBBDEF (in_rtx, i))
552117395Skan	  fprintf (outfile, " %i", XBBDEF (in_rtx, i)->index);
553169689Skan#endif
554117395Skan	break;
555117395Skan
55618334Speter      default:
557169689Skan	gcc_unreachable ();
55818334Speter      }
55918334Speter
56090075Sobrien  switch (GET_CODE (in_rtx))
56190075Sobrien    {
562117395Skan#ifndef GENERATOR_FILE
56390075Sobrien    case MEM:
564132718Skan      fprintf (outfile, " [" HOST_WIDE_INT_PRINT_DEC, MEM_ALIAS_SET (in_rtx));
56552284Sobrien
56690075Sobrien      if (MEM_EXPR (in_rtx))
56790075Sobrien	print_mem_expr (outfile, MEM_EXPR (in_rtx));
56890075Sobrien
56990075Sobrien      if (MEM_OFFSET (in_rtx))
570132718Skan	fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC,
571132718Skan		 INTVAL (MEM_OFFSET (in_rtx)));
57290075Sobrien
57390075Sobrien      if (MEM_SIZE (in_rtx))
574132718Skan	fprintf (outfile, " S" HOST_WIDE_INT_PRINT_DEC,
575132718Skan		 INTVAL (MEM_SIZE (in_rtx)));
57690075Sobrien
57790075Sobrien      if (MEM_ALIGN (in_rtx) != 1)
57890075Sobrien	fprintf (outfile, " A%u", MEM_ALIGN (in_rtx));
57990075Sobrien
58090075Sobrien      fputc (']', outfile);
58190075Sobrien      break;
58290075Sobrien
58390075Sobrien    case CONST_DOUBLE:
58490075Sobrien      if (FLOAT_MODE_P (GET_MODE (in_rtx)))
58590075Sobrien	{
586117395Skan	  char s[60];
587117395Skan
588117395Skan	  real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
589117395Skan			   sizeof (s), 0, 1);
590117395Skan	  fprintf (outfile, " %s", s);
591117395Skan
592117395Skan	  real_to_hexadecimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
593117395Skan			       sizeof (s), 0, 1);
594117395Skan	  fprintf (outfile, " [%s]", s);
59590075Sobrien	}
59690075Sobrien      break;
59750397Sobrien#endif
59850397Sobrien
59990075Sobrien    case CODE_LABEL:
60090075Sobrien      fprintf (outfile, " [%d uses]", LABEL_NUSES (in_rtx));
601117395Skan      switch (LABEL_KIND (in_rtx))
602117395Skan	{
603117395Skan	  case LABEL_NORMAL: break;
604117395Skan	  case LABEL_STATIC_ENTRY: fputs (" [entry]", outfile); break;
605117395Skan	  case LABEL_GLOBAL_ENTRY: fputs (" [global entry]", outfile); break;
606117395Skan	  case LABEL_WEAK_ENTRY: fputs (" [weak entry]", outfile); break;
607169689Skan	  default: gcc_unreachable ();
608117395Skan	}
60990075Sobrien      break;
61090075Sobrien
61190075Sobrien    default:
61290075Sobrien      break;
61390075Sobrien    }
61490075Sobrien
61552284Sobrien  if (dump_for_graph
616169689Skan      && (is_insn || NOTE_P (in_rtx)
617169689Skan	  || LABEL_P (in_rtx) || BARRIER_P (in_rtx)))
61852284Sobrien    sawclose = 0;
61952284Sobrien  else
62052284Sobrien    {
62152284Sobrien      fputc (')', outfile);
62252284Sobrien      sawclose = 1;
62352284Sobrien    }
62418334Speter}
62518334Speter
62650397Sobrien/* Print an rtx on the current line of FILE.  Initially indent IND
62750397Sobrien   characters.  */
62850397Sobrien
62950397Sobrienvoid
630132718Skanprint_inline_rtx (FILE *outf, rtx x, int ind)
63150397Sobrien{
63250397Sobrien  int oldsaw = sawclose;
63350397Sobrien  int oldindent = indent;
63450397Sobrien
63550397Sobrien  sawclose = 0;
63650397Sobrien  indent = ind;
63750397Sobrien  outfile = outf;
63850397Sobrien  print_rtx (x);
63950397Sobrien  sawclose = oldsaw;
64050397Sobrien  indent = oldindent;
64150397Sobrien}
64250397Sobrien
64318334Speter/* Call this function from the debugger to see what X looks like.  */
64418334Speter
64518334Spetervoid
646132718Skandebug_rtx (rtx x)
64718334Speter{
64818334Speter  outfile = stderr;
649117395Skan  sawclose = 0;
65018334Speter  print_rtx (x);
65118334Speter  fprintf (stderr, "\n");
65218334Speter}
65318334Speter
65418334Speter/* Count of rtx's to print with debug_rtx_list.
65518334Speter   This global exists because gdb user defined commands have no arguments.  */
65618334Speter
65718334Speterint debug_rtx_count = 0;	/* 0 is treated as equivalent to 1 */
65818334Speter
65918334Speter/* Call this function to print list from X on.
66018334Speter
66118334Speter   N is a count of the rtx's to print. Positive values print from the specified
66218334Speter   rtx on.  Negative values print a window around the rtx.
66318334Speter   EG: -5 prints 2 rtx's on either side (in addition to the specified rtx).  */
66418334Speter
66518334Spetervoid
666132718Skandebug_rtx_list (rtx x, int n)
66718334Speter{
66818334Speter  int i,count;
66918334Speter  rtx insn;
67018334Speter
67118334Speter  count = n == 0 ? 1 : n < 0 ? -n : n;
67218334Speter
67318334Speter  /* If we are printing a window, back up to the start.  */
67418334Speter
67518334Speter  if (n < 0)
67618334Speter    for (i = count / 2; i > 0; i--)
67718334Speter      {
67818334Speter	if (PREV_INSN (x) == 0)
67918334Speter	  break;
68018334Speter	x = PREV_INSN (x);
68118334Speter      }
68218334Speter
68318334Speter  for (i = count, insn = x; i > 0 && insn != 0; i--, insn = NEXT_INSN (insn))
684117395Skan    {
685117395Skan      debug_rtx (insn);
686117395Skan      fprintf (stderr, "\n");
687117395Skan    }
68818334Speter}
68918334Speter
69090075Sobrien/* Call this function to print an rtx list from START to END inclusive.  */
69190075Sobrien
69290075Sobrienvoid
693132718Skandebug_rtx_range (rtx start, rtx end)
69490075Sobrien{
69590075Sobrien  while (1)
69690075Sobrien    {
69790075Sobrien      debug_rtx (start);
698117395Skan      fprintf (stderr, "\n");
69990075Sobrien      if (!start || start == end)
70090075Sobrien	break;
70190075Sobrien      start = NEXT_INSN (start);
70290075Sobrien    }
70390075Sobrien}
70490075Sobrien
70518334Speter/* Call this function to search an rtx list to find one with insn uid UID,
70618334Speter   and then call debug_rtx_list to print it, using DEBUG_RTX_COUNT.
70718334Speter   The found insn is returned to enable further debugging analysis.  */
70818334Speter
70918334Speterrtx
710132718Skandebug_rtx_find (rtx x, int uid)
71118334Speter{
71218334Speter  while (x != 0 && INSN_UID (x) != uid)
71318334Speter    x = NEXT_INSN (x);
71418334Speter  if (x != 0)
71518334Speter    {
71618334Speter      debug_rtx_list (x, debug_rtx_count);
71718334Speter      return x;
71818334Speter    }
71918334Speter  else
72018334Speter    {
72118334Speter      fprintf (stderr, "insn uid %d not found\n", uid);
72218334Speter      return 0;
72318334Speter    }
72418334Speter}
72518334Speter
72618334Speter/* External entry point for printing a chain of insns
72718334Speter   starting with RTX_FIRST onto file OUTF.
72818334Speter   A blank line separates insns.
72918334Speter
73018334Speter   If RTX_FIRST is not an insn, then it alone is printed, with no newline.  */
73118334Speter
73218334Spetervoid
733132718Skanprint_rtl (FILE *outf, rtx rtx_first)
73418334Speter{
73590075Sobrien  rtx tmp_rtx;
73618334Speter
73718334Speter  outfile = outf;
73818334Speter  sawclose = 0;
73918334Speter
74018334Speter  if (rtx_first == 0)
74190075Sobrien    {
74290075Sobrien      fputs (print_rtx_head, outf);
74390075Sobrien      fputs ("(nil)\n", outf);
74490075Sobrien    }
74518334Speter  else
74618334Speter    switch (GET_CODE (rtx_first))
74718334Speter      {
74818334Speter      case INSN:
74918334Speter      case JUMP_INSN:
75018334Speter      case CALL_INSN:
75118334Speter      case NOTE:
75218334Speter      case CODE_LABEL:
75318334Speter      case BARRIER:
75490075Sobrien	for (tmp_rtx = rtx_first; tmp_rtx != 0; tmp_rtx = NEXT_INSN (tmp_rtx))
75590075Sobrien	  if (! flag_dump_unnumbered
756169689Skan	      || !NOTE_P (tmp_rtx) || NOTE_LINE_NUMBER (tmp_rtx) < 0)
75790075Sobrien	    {
758117395Skan	      fputs (print_rtx_head, outfile);
75990075Sobrien	      print_rtx (tmp_rtx);
76090075Sobrien	      fprintf (outfile, "\n");
76190075Sobrien	    }
76218334Speter	break;
76318334Speter
76418334Speter      default:
765117395Skan	fputs (print_rtx_head, outfile);
76618334Speter	print_rtx (rtx_first);
76718334Speter      }
76818334Speter}
76950397Sobrien
77050397Sobrien/* Like print_rtx, except specify a file.  */
77152284Sobrien/* Return nonzero if we actually printed anything.  */
77250397Sobrien
77352284Sobrienint
774132718Skanprint_rtl_single (FILE *outf, rtx x)
77550397Sobrien{
77650397Sobrien  outfile = outf;
77750397Sobrien  sawclose = 0;
77850397Sobrien  if (! flag_dump_unnumbered
779169689Skan      || !NOTE_P (x) || NOTE_LINE_NUMBER (x) < 0)
78050397Sobrien    {
78190075Sobrien      fputs (print_rtx_head, outfile);
78250397Sobrien      print_rtx (x);
78350397Sobrien      putc ('\n', outf);
78452284Sobrien      return 1;
78550397Sobrien    }
78652284Sobrien  return 0;
78750397Sobrien}
78890075Sobrien
78990075Sobrien
79090075Sobrien/* Like print_rtl except without all the detail; for example,
79190075Sobrien   if RTX is a CONST_INT then print in decimal format.  */
79290075Sobrien
79390075Sobrienvoid
794132718Skanprint_simple_rtl (FILE *outf, rtx x)
79590075Sobrien{
79690075Sobrien  flag_simple = 1;
79790075Sobrien  print_rtl (outf, x);
79890075Sobrien  flag_simple = 0;
79990075Sobrien}
800