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	}
609260918Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
610260918Spfg      if (LABEL_ALIGN_LOG (in_rtx) > 0)
611260918Spfg	fprintf (outfile, " [log_align %u skip %u]", LABEL_ALIGN_LOG (in_rtx),
612260918Spfg		 LABEL_MAX_SKIP (in_rtx));
613260918Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \
61490075Sobrien      break;
61590075Sobrien
61690075Sobrien    default:
61790075Sobrien      break;
61890075Sobrien    }
61990075Sobrien
62052284Sobrien  if (dump_for_graph
621169689Skan      && (is_insn || NOTE_P (in_rtx)
622169689Skan	  || LABEL_P (in_rtx) || BARRIER_P (in_rtx)))
62352284Sobrien    sawclose = 0;
62452284Sobrien  else
62552284Sobrien    {
62652284Sobrien      fputc (')', outfile);
62752284Sobrien      sawclose = 1;
62852284Sobrien    }
62918334Speter}
63018334Speter
63150397Sobrien/* Print an rtx on the current line of FILE.  Initially indent IND
63250397Sobrien   characters.  */
63350397Sobrien
63450397Sobrienvoid
635132718Skanprint_inline_rtx (FILE *outf, rtx x, int ind)
63650397Sobrien{
63750397Sobrien  int oldsaw = sawclose;
63850397Sobrien  int oldindent = indent;
63950397Sobrien
64050397Sobrien  sawclose = 0;
64150397Sobrien  indent = ind;
64250397Sobrien  outfile = outf;
64350397Sobrien  print_rtx (x);
64450397Sobrien  sawclose = oldsaw;
64550397Sobrien  indent = oldindent;
64650397Sobrien}
64750397Sobrien
64818334Speter/* Call this function from the debugger to see what X looks like.  */
64918334Speter
65018334Spetervoid
651132718Skandebug_rtx (rtx x)
65218334Speter{
65318334Speter  outfile = stderr;
654117395Skan  sawclose = 0;
65518334Speter  print_rtx (x);
65618334Speter  fprintf (stderr, "\n");
65718334Speter}
65818334Speter
65918334Speter/* Count of rtx's to print with debug_rtx_list.
66018334Speter   This global exists because gdb user defined commands have no arguments.  */
66118334Speter
66218334Speterint debug_rtx_count = 0;	/* 0 is treated as equivalent to 1 */
66318334Speter
66418334Speter/* Call this function to print list from X on.
66518334Speter
66618334Speter   N is a count of the rtx's to print. Positive values print from the specified
66718334Speter   rtx on.  Negative values print a window around the rtx.
66818334Speter   EG: -5 prints 2 rtx's on either side (in addition to the specified rtx).  */
66918334Speter
67018334Spetervoid
671132718Skandebug_rtx_list (rtx x, int n)
67218334Speter{
67318334Speter  int i,count;
67418334Speter  rtx insn;
67518334Speter
67618334Speter  count = n == 0 ? 1 : n < 0 ? -n : n;
67718334Speter
67818334Speter  /* If we are printing a window, back up to the start.  */
67918334Speter
68018334Speter  if (n < 0)
68118334Speter    for (i = count / 2; i > 0; i--)
68218334Speter      {
68318334Speter	if (PREV_INSN (x) == 0)
68418334Speter	  break;
68518334Speter	x = PREV_INSN (x);
68618334Speter      }
68718334Speter
68818334Speter  for (i = count, insn = x; i > 0 && insn != 0; i--, insn = NEXT_INSN (insn))
689117395Skan    {
690117395Skan      debug_rtx (insn);
691117395Skan      fprintf (stderr, "\n");
692117395Skan    }
69318334Speter}
69418334Speter
69590075Sobrien/* Call this function to print an rtx list from START to END inclusive.  */
69690075Sobrien
69790075Sobrienvoid
698132718Skandebug_rtx_range (rtx start, rtx end)
69990075Sobrien{
70090075Sobrien  while (1)
70190075Sobrien    {
70290075Sobrien      debug_rtx (start);
703117395Skan      fprintf (stderr, "\n");
70490075Sobrien      if (!start || start == end)
70590075Sobrien	break;
70690075Sobrien      start = NEXT_INSN (start);
70790075Sobrien    }
70890075Sobrien}
70990075Sobrien
71018334Speter/* Call this function to search an rtx list to find one with insn uid UID,
71118334Speter   and then call debug_rtx_list to print it, using DEBUG_RTX_COUNT.
71218334Speter   The found insn is returned to enable further debugging analysis.  */
71318334Speter
71418334Speterrtx
715132718Skandebug_rtx_find (rtx x, int uid)
71618334Speter{
71718334Speter  while (x != 0 && INSN_UID (x) != uid)
71818334Speter    x = NEXT_INSN (x);
71918334Speter  if (x != 0)
72018334Speter    {
72118334Speter      debug_rtx_list (x, debug_rtx_count);
72218334Speter      return x;
72318334Speter    }
72418334Speter  else
72518334Speter    {
72618334Speter      fprintf (stderr, "insn uid %d not found\n", uid);
72718334Speter      return 0;
72818334Speter    }
72918334Speter}
73018334Speter
73118334Speter/* External entry point for printing a chain of insns
73218334Speter   starting with RTX_FIRST onto file OUTF.
73318334Speter   A blank line separates insns.
73418334Speter
73518334Speter   If RTX_FIRST is not an insn, then it alone is printed, with no newline.  */
73618334Speter
73718334Spetervoid
738132718Skanprint_rtl (FILE *outf, rtx rtx_first)
73918334Speter{
74090075Sobrien  rtx tmp_rtx;
74118334Speter
74218334Speter  outfile = outf;
74318334Speter  sawclose = 0;
74418334Speter
74518334Speter  if (rtx_first == 0)
74690075Sobrien    {
74790075Sobrien      fputs (print_rtx_head, outf);
74890075Sobrien      fputs ("(nil)\n", outf);
74990075Sobrien    }
75018334Speter  else
75118334Speter    switch (GET_CODE (rtx_first))
75218334Speter      {
75318334Speter      case INSN:
75418334Speter      case JUMP_INSN:
75518334Speter      case CALL_INSN:
75618334Speter      case NOTE:
75718334Speter      case CODE_LABEL:
75818334Speter      case BARRIER:
75990075Sobrien	for (tmp_rtx = rtx_first; tmp_rtx != 0; tmp_rtx = NEXT_INSN (tmp_rtx))
76090075Sobrien	  if (! flag_dump_unnumbered
761169689Skan	      || !NOTE_P (tmp_rtx) || NOTE_LINE_NUMBER (tmp_rtx) < 0)
76290075Sobrien	    {
763117395Skan	      fputs (print_rtx_head, outfile);
76490075Sobrien	      print_rtx (tmp_rtx);
76590075Sobrien	      fprintf (outfile, "\n");
76690075Sobrien	    }
76718334Speter	break;
76818334Speter
76918334Speter      default:
770117395Skan	fputs (print_rtx_head, outfile);
77118334Speter	print_rtx (rtx_first);
77218334Speter      }
77318334Speter}
77450397Sobrien
77550397Sobrien/* Like print_rtx, except specify a file.  */
77652284Sobrien/* Return nonzero if we actually printed anything.  */
77750397Sobrien
77852284Sobrienint
779132718Skanprint_rtl_single (FILE *outf, rtx x)
78050397Sobrien{
78150397Sobrien  outfile = outf;
78250397Sobrien  sawclose = 0;
78350397Sobrien  if (! flag_dump_unnumbered
784169689Skan      || !NOTE_P (x) || NOTE_LINE_NUMBER (x) < 0)
78550397Sobrien    {
78690075Sobrien      fputs (print_rtx_head, outfile);
78750397Sobrien      print_rtx (x);
78850397Sobrien      putc ('\n', outf);
78952284Sobrien      return 1;
79050397Sobrien    }
79152284Sobrien  return 0;
79250397Sobrien}
79390075Sobrien
79490075Sobrien
79590075Sobrien/* Like print_rtl except without all the detail; for example,
79690075Sobrien   if RTX is a CONST_INT then print in decimal format.  */
79790075Sobrien
79890075Sobrienvoid
799132718Skanprint_simple_rtl (FILE *outf, rtx x)
80090075Sobrien{
80190075Sobrien  flag_simple = 1;
80290075Sobrien  print_rtl (outf, x);
80390075Sobrien  flag_simple = 0;
80490075Sobrien}
805