1/* Pretty formatting of GENERIC trees in C syntax.
2   Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3   Adapted from c-pretty-print.c by Diego Novillo <dnovillo@redhat.com>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING.  If not, write to the Free
19Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2002110-1301, USA.  */
21
22#include "config.h"
23#include "system.h"
24#include "coretypes.h"
25#include "tm.h"
26#include "tree.h"
27#include "diagnostic.h"
28#include "real.h"
29#include "hashtab.h"
30#include "tree-flow.h"
31#include "langhooks.h"
32#include "tree-iterator.h"
33#include "tree-chrec.h"
34#include "tree-pass.h"
35
36/* Local functions, macros and variables.  */
37static int op_prio (tree);
38static const char *op_symbol (tree);
39static void pretty_print_string (pretty_printer *, const char*);
40static void print_call_name (pretty_printer *, tree);
41static void newline_and_indent (pretty_printer *, int);
42static void maybe_init_pretty_print (FILE *);
43static void print_declaration (pretty_printer *, tree, int, int);
44static void print_struct_decl (pretty_printer *, tree, int, int);
45static void do_niy (pretty_printer *, tree);
46static void dump_vops (pretty_printer *, tree, int, int);
47static void dump_generic_bb_buff (pretty_printer *, basic_block, int, int);
48
49#define INDENT(SPACE) do { \
50  int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
51
52#define NIY do_niy(buffer,node)
53
54#define PRINT_FUNCTION_NAME(NODE)  pp_printf             \
55  (buffer, "%s", TREE_CODE (NODE) == NOP_EXPR ?              \
56   lang_hooks.decl_printable_name (TREE_OPERAND (NODE, 0), 1) : \
57   lang_hooks.decl_printable_name (NODE, 1))
58
59static pretty_printer buffer;
60static int initialized = 0;
61static bool dumping_stmts;
62
63/* Try to print something for an unknown tree code.  */
64
65static void
66do_niy (pretty_printer *buffer, tree node)
67{
68  int i, len;
69
70  pp_string (buffer, "<<< Unknown tree: ");
71  pp_string (buffer, tree_code_name[(int) TREE_CODE (node)]);
72
73  if (EXPR_P (node))
74    {
75      len = TREE_CODE_LENGTH (TREE_CODE (node));
76      for (i = 0; i < len; ++i)
77	{
78	  newline_and_indent (buffer, 2);
79	  dump_generic_node (buffer, TREE_OPERAND (node, i), 2, 0, false);
80	}
81    }
82
83  pp_string (buffer, " >>>\n");
84}
85
86void
87debug_generic_expr (tree t)
88{
89  print_generic_expr (stderr, t, TDF_VOPS|TDF_UID);
90  fprintf (stderr, "\n");
91}
92
93void
94debug_generic_stmt (tree t)
95{
96  print_generic_stmt (stderr, t, TDF_VOPS|TDF_UID);
97  fprintf (stderr, "\n");
98}
99
100/* Prints declaration DECL to the FILE with details specified by FLAGS.  */
101void
102print_generic_decl (FILE *file, tree decl, int flags)
103{
104  maybe_init_pretty_print (file);
105  dumping_stmts = true;
106  print_declaration (&buffer, decl, 2, flags);
107  pp_write_text_to_stream (&buffer);
108}
109
110/* Print tree T, and its successors, on file FILE.  FLAGS specifies details
111   to show in the dump.  See TDF_* in tree.h.  */
112
113void
114print_generic_stmt (FILE *file, tree t, int flags)
115{
116  maybe_init_pretty_print (file);
117  dumping_stmts = true;
118  dump_generic_node (&buffer, t, 0, flags, true);
119  pp_flush (&buffer);
120}
121
122/* Print tree T, and its successors, on file FILE.  FLAGS specifies details
123   to show in the dump.  See TDF_* in tree.h.  The output is indented by
124   INDENT spaces.  */
125
126void
127print_generic_stmt_indented (FILE *file, tree t, int flags, int indent)
128{
129  int i;
130
131  maybe_init_pretty_print (file);
132  dumping_stmts = true;
133
134  for (i = 0; i < indent; i++)
135    pp_space (&buffer);
136  dump_generic_node (&buffer, t, indent, flags, true);
137  pp_flush (&buffer);
138}
139
140/* Print a single expression T on file FILE.  FLAGS specifies details to show
141   in the dump.  See TDF_* in tree.h.  */
142
143void
144print_generic_expr (FILE *file, tree t, int flags)
145{
146  maybe_init_pretty_print (file);
147  dumping_stmts = false;
148  dump_generic_node (&buffer, t, 0, flags, false);
149}
150
151/* Dump the name of a _DECL node and its DECL_UID if TDF_UID is set
152   in FLAGS.  */
153
154static void
155dump_decl_name (pretty_printer *buffer, tree node, int flags)
156{
157  if (DECL_NAME (node))
158    pp_tree_identifier (buffer, DECL_NAME (node));
159
160  if ((flags & TDF_UID)
161      || DECL_NAME (node) == NULL_TREE)
162    {
163      if (TREE_CODE (node) == LABEL_DECL
164	  && LABEL_DECL_UID (node) != -1)
165	pp_printf (buffer, "L." HOST_WIDE_INT_PRINT_DEC,
166		   LABEL_DECL_UID (node));
167      else
168	{
169	  char c = TREE_CODE (node) == CONST_DECL ? 'C' : 'D';
170	  pp_printf (buffer, "%c.%u", c, DECL_UID (node));
171	}
172    }
173}
174
175/* Like the above, but used for pretty printing function calls.  */
176
177static void
178dump_function_name (pretty_printer *buffer, tree node)
179{
180  if (DECL_NAME (node))
181    PRINT_FUNCTION_NAME (node);
182  else
183    dump_decl_name (buffer, node, 0);
184}
185
186/* Dump a function declaration.  NODE is the FUNCTION_TYPE.  BUFFER, SPC and
187   FLAGS are as in dump_generic_node.  */
188
189static void
190dump_function_declaration (pretty_printer *buffer, tree node,
191			   int spc, int flags)
192{
193  bool wrote_arg = false;
194  tree arg;
195
196  pp_space (buffer);
197  pp_character (buffer, '(');
198
199  /* Print the argument types.  The last element in the list is a VOID_TYPE.
200     The following avoids printing the last element.  */
201  arg = TYPE_ARG_TYPES (node);
202  while (arg && TREE_CHAIN (arg) && arg != error_mark_node)
203    {
204      wrote_arg = true;
205      dump_generic_node (buffer, TREE_VALUE (arg), spc, flags, false);
206      arg = TREE_CHAIN (arg);
207      if (TREE_CHAIN (arg) && TREE_CODE (TREE_CHAIN (arg)) == TREE_LIST)
208	{
209	  pp_character (buffer, ',');
210	  pp_space (buffer);
211	}
212    }
213
214  if (!wrote_arg)
215    pp_string (buffer, "void");
216
217  pp_character (buffer, ')');
218}
219
220/* Dump the domain associated with an array.  */
221
222static void
223dump_array_domain (pretty_printer *buffer, tree domain, int spc, int flags)
224{
225  pp_character (buffer, '[');
226  if (domain)
227    {
228      tree min = TYPE_MIN_VALUE (domain);
229      tree max = TYPE_MAX_VALUE (domain);
230
231      if (min && max
232	  && integer_zerop (min)
233	  && host_integerp (max, 0))
234	pp_wide_integer (buffer, TREE_INT_CST_LOW (max) + 1);
235      else
236	{
237	  if (min)
238	    dump_generic_node (buffer, min, spc, flags, false);
239	  pp_character (buffer, ':');
240	  if (max)
241	    dump_generic_node (buffer, max, spc, flags, false);
242	}
243    }
244  else
245    pp_string (buffer, "<unknown>");
246  pp_character (buffer, ']');
247}
248
249/* Dump the node NODE on the pretty_printer BUFFER, SPC spaces of indent.
250   FLAGS specifies details to show in the dump (see TDF_* in tree.h).  If
251   IS_STMT is true, the object printed is considered to be a statement
252   and it is terminated by ';' if appropriate.  */
253
254int
255dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
256		   bool is_stmt)
257{
258  tree type;
259  tree op0, op1;
260  const char *str;
261  bool is_expr;
262
263  if (node == NULL_TREE)
264    return spc;
265
266  is_expr = EXPR_P (node);
267
268  if (TREE_CODE (node) != ERROR_MARK
269      && is_gimple_stmt (node)
270      && (flags & TDF_VOPS)
271      && stmt_ann (node)
272      && TREE_CODE (node) != PHI_NODE)
273    dump_vops (buffer, node, spc, flags);
274
275  if (is_stmt && (flags & TDF_STMTADDR))
276    pp_printf (buffer, "<&%p> ", (void *)node);
277
278  if (dumping_stmts
279      && (flags & TDF_LINENO)
280      && EXPR_HAS_LOCATION (node))
281    {
282      expanded_location xloc = expand_location (EXPR_LOCATION (node));
283      pp_character (buffer, '[');
284      if (xloc.file)
285	{
286	  pp_string (buffer, xloc.file);
287	  pp_string (buffer, " : ");
288	}
289      pp_decimal_int (buffer, xloc.line);
290      pp_string (buffer, "] ");
291    }
292
293  switch (TREE_CODE (node))
294    {
295    case ERROR_MARK:
296      pp_string (buffer, "<<< error >>>");
297      break;
298
299    case IDENTIFIER_NODE:
300      pp_tree_identifier (buffer, node);
301      break;
302
303    case TREE_LIST:
304      while (node && node != error_mark_node)
305	{
306	  if (TREE_PURPOSE (node))
307	    {
308	      dump_generic_node (buffer, TREE_PURPOSE (node), spc, flags, false);
309	      pp_space (buffer);
310	    }
311	  dump_generic_node (buffer, TREE_VALUE (node), spc, flags, false);
312	  node = TREE_CHAIN (node);
313	  if (node && TREE_CODE (node) == TREE_LIST)
314	    {
315	      pp_character (buffer, ',');
316	      pp_space (buffer);
317	    }
318	}
319      break;
320
321    case TREE_BINFO:
322      dump_generic_node (buffer, BINFO_TYPE (node), spc, flags, false);
323
324    case TREE_VEC:
325      {
326	size_t i;
327	if (TREE_VEC_LENGTH (node) > 0)
328	  {
329	    size_t len = TREE_VEC_LENGTH (node);
330	    for (i = 0; i < len - 1; i++)
331	      {
332		dump_generic_node (buffer, TREE_VEC_ELT (node, i), spc, flags,
333				   false);
334		pp_character (buffer, ',');
335		pp_space (buffer);
336	      }
337	    dump_generic_node (buffer, TREE_VEC_ELT (node, len - 1), spc,
338			       flags, false);
339	  }
340      }
341      break;
342
343    case BLOCK:
344      NIY;
345      break;
346
347    case VOID_TYPE:
348    case INTEGER_TYPE:
349    case REAL_TYPE:
350    case COMPLEX_TYPE:
351    case VECTOR_TYPE:
352    case ENUMERAL_TYPE:
353    case BOOLEAN_TYPE:
354    case CHAR_TYPE:
355      {
356	unsigned int quals = TYPE_QUALS (node);
357	enum tree_code_class class;
358
359	if (quals & TYPE_QUAL_CONST)
360	  pp_string (buffer, "const ");
361	else if (quals & TYPE_QUAL_VOLATILE)
362	  pp_string (buffer, "volatile ");
363	else if (quals & TYPE_QUAL_RESTRICT)
364	  pp_string (buffer, "restrict ");
365
366	class = TREE_CODE_CLASS (TREE_CODE (node));
367
368	if (class == tcc_declaration)
369	  {
370	    if (DECL_NAME (node))
371	      dump_decl_name (buffer, node, flags);
372	    else
373              pp_string (buffer, "<unnamed type decl>");
374	  }
375	else if (class == tcc_type)
376	  {
377	    if (TYPE_NAME (node))
378	      {
379		if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
380		  pp_tree_identifier (buffer, TYPE_NAME (node));
381		else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
382			 && DECL_NAME (TYPE_NAME (node)))
383		  dump_decl_name (buffer, TYPE_NAME (node), flags);
384		else
385		  pp_string (buffer, "<unnamed type>");
386	      }
387	    else if (TREE_CODE (node) == VECTOR_TYPE)
388	      {
389		pp_string (buffer, "vector ");
390		dump_generic_node (buffer, TREE_TYPE (node),
391				   spc, flags, false);
392	      }
393	    else
394              pp_string (buffer, "<unnamed type>");
395	  }
396	break;
397      }
398
399    case POINTER_TYPE:
400    case REFERENCE_TYPE:
401      str = (TREE_CODE (node) == POINTER_TYPE ? "*" : "&");
402
403      if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
404        {
405	  tree fnode = TREE_TYPE (node);
406
407	  dump_generic_node (buffer, TREE_TYPE (fnode), spc, flags, false);
408	  pp_space (buffer);
409	  pp_character (buffer, '(');
410	  pp_string (buffer, str);
411	  if (TYPE_NAME (node) && DECL_NAME (TYPE_NAME (node)))
412	    dump_decl_name (buffer, TYPE_NAME (node), flags);
413	  else
414	    pp_printf (buffer, "<T%x>", TYPE_UID (node));
415
416	  pp_character (buffer, ')');
417	  dump_function_declaration (buffer, fnode, spc, flags);
418	}
419      else
420        {
421	  unsigned int quals = TYPE_QUALS (node);
422
423          dump_generic_node (buffer, TREE_TYPE (node), spc, flags, false);
424	  pp_space (buffer);
425	  pp_string (buffer, str);
426
427	  if (quals & TYPE_QUAL_CONST)
428	    pp_string (buffer, " const");
429	  else if (quals & TYPE_QUAL_VOLATILE)
430	    pp_string (buffer,  "volatile");
431	  else if (quals & TYPE_QUAL_RESTRICT)
432	    pp_string (buffer, " restrict");
433
434	  if (TYPE_REF_CAN_ALIAS_ALL (node))
435	    pp_string (buffer, " {ref-all}");
436	}
437      break;
438
439    case OFFSET_TYPE:
440      NIY;
441      break;
442
443    case METHOD_TYPE:
444      dump_decl_name (buffer, TYPE_NAME (TYPE_METHOD_BASETYPE (node)), flags);
445      pp_string (buffer, "::");
446      break;
447
448    case TARGET_MEM_REF:
449      {
450	const char *sep = "";
451	tree tmp;
452
453	pp_string (buffer, "MEM[");
454
455	tmp = TMR_SYMBOL (node);
456	if (tmp)
457	  {
458	    pp_string (buffer, sep);
459	    sep = ", ";
460	    pp_string (buffer, "symbol: ");
461	    dump_generic_node (buffer, tmp, spc, flags, false);
462	  }
463	tmp = TMR_BASE (node);
464	if (tmp)
465	  {
466	    pp_string (buffer, sep);
467	    sep = ", ";
468	    pp_string (buffer, "base: ");
469	    dump_generic_node (buffer, tmp, spc, flags, false);
470	  }
471	tmp = TMR_INDEX (node);
472	if (tmp)
473	  {
474	    pp_string (buffer, sep);
475	    sep = ", ";
476	    pp_string (buffer, "index: ");
477	    dump_generic_node (buffer, tmp, spc, flags, false);
478	  }
479	tmp = TMR_STEP (node);
480	if (tmp)
481	  {
482	    pp_string (buffer, sep);
483	    sep = ", ";
484	    pp_string (buffer, "step: ");
485	    dump_generic_node (buffer, tmp, spc, flags, false);
486	  }
487	tmp = TMR_OFFSET (node);
488	if (tmp)
489	  {
490	    pp_string (buffer, sep);
491	    sep = ", ";
492	    pp_string (buffer, "offset: ");
493	    dump_generic_node (buffer, tmp, spc, flags, false);
494	  }
495	pp_string (buffer, "]");
496	if (flags & TDF_DETAILS)
497	  {
498	    pp_string (buffer, "{");
499	    dump_generic_node (buffer, TMR_ORIGINAL (node), spc, flags,
500			       false);
501	    pp_string (buffer, "}");
502	  }
503      }
504      break;
505
506    case ARRAY_TYPE:
507      {
508	tree tmp;
509
510	/* Print the innermost component type.  */
511	for (tmp = TREE_TYPE (node); TREE_CODE (tmp) == ARRAY_TYPE;
512	     tmp = TREE_TYPE (tmp))
513	  ;
514	dump_generic_node (buffer, tmp, spc, flags, false);
515
516	/* Print the dimensions.  */
517	for (tmp = node; TREE_CODE (tmp) == ARRAY_TYPE; tmp = TREE_TYPE (tmp))
518	  dump_array_domain (buffer, TYPE_DOMAIN (tmp), spc, flags);
519	break;
520      }
521
522    case RECORD_TYPE:
523    case UNION_TYPE:
524    case QUAL_UNION_TYPE:
525      /* Print the name of the structure.  */
526      if (TREE_CODE (node) == RECORD_TYPE)
527	pp_string (buffer, "struct ");
528      else if (TREE_CODE (node) == UNION_TYPE)
529	pp_string (buffer, "union ");
530
531      if (TYPE_NAME (node))
532	dump_generic_node (buffer, TYPE_NAME (node), spc, flags, false);
533      else
534	print_struct_decl (buffer, node, spc, flags);
535      break;
536
537    case LANG_TYPE:
538      NIY;
539      break;
540
541    case INTEGER_CST:
542      if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE)
543	{
544	  /* In the case of a pointer, one may want to divide by the
545	     size of the pointed-to type.  Unfortunately, this not
546	     straightforward.  The C front-end maps expressions
547
548	     (int *) 5
549	     int *p; (p + 5)
550
551	     in such a way that the two INTEGER_CST nodes for "5" have
552	     different values but identical types.  In the latter
553	     case, the 5 is multiplied by sizeof (int) in c-common.c
554	     (pointer_int_sum) to convert it to a byte address, and
555	     yet the type of the node is left unchanged.  Argh.  What
556	     is consistent though is that the number value corresponds
557	     to bytes (UNITS) offset.
558
559             NB: Neither of the following divisors can be trivially
560             used to recover the original literal:
561
562             TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (node)))
563	     TYPE_PRECISION (TREE_TYPE (TREE_TYPE (node)))  */
564	  pp_wide_integer (buffer, TREE_INT_CST_LOW (node));
565	  pp_string (buffer, "B"); /* pseudo-unit */
566	}
567      else if (! host_integerp (node, 0))
568	{
569	  tree val = node;
570
571	  if (tree_int_cst_sgn (val) < 0)
572	    {
573	      pp_character (buffer, '-');
574	      val = build_int_cst_wide (NULL_TREE,
575					-TREE_INT_CST_LOW (val),
576					~TREE_INT_CST_HIGH (val)
577					+ !TREE_INT_CST_LOW (val));
578	    }
579	  /* Would "%x%0*x" or "%x%*0x" get zero-padding on all
580	     systems?  */
581	  {
582	    static char format[10]; /* "%x%09999x\0" */
583	    if (!format[0])
584	      sprintf (format, "%%x%%0%dx", HOST_BITS_PER_INT / 4);
585	    sprintf (pp_buffer (buffer)->digit_buffer, format,
586		     TREE_INT_CST_HIGH (val),
587		     TREE_INT_CST_LOW (val));
588	    pp_string (buffer, pp_buffer (buffer)->digit_buffer);
589	  }
590	}
591      else
592	pp_wide_integer (buffer, TREE_INT_CST_LOW (node));
593      break;
594
595    case REAL_CST:
596      /* Code copied from print_node.  */
597      {
598	REAL_VALUE_TYPE d;
599	if (TREE_OVERFLOW (node))
600	  pp_string (buffer, " overflow");
601
602#if !defined(REAL_IS_NOT_DOUBLE) || defined(REAL_ARITHMETIC)
603	d = TREE_REAL_CST (node);
604	if (REAL_VALUE_ISINF (d))
605	  pp_string (buffer, " Inf");
606	else if (REAL_VALUE_ISNAN (d))
607	  pp_string (buffer, " Nan");
608	else
609	  {
610	    char string[100];
611	    real_to_decimal (string, &d, sizeof (string), 0, 1);
612	    pp_string (buffer, string);
613	  }
614#else
615	{
616	  HOST_WIDE_INT i;
617	  unsigned char *p = (unsigned char *) &TREE_REAL_CST (node);
618	  pp_string (buffer, "0x");
619	  for (i = 0; i < sizeof TREE_REAL_CST (node); i++)
620	    output_formatted_integer (buffer, "%02x", *p++);
621	}
622#endif
623	break;
624      }
625
626    case COMPLEX_CST:
627      pp_string (buffer, "__complex__ (");
628      dump_generic_node (buffer, TREE_REALPART (node), spc, flags, false);
629      pp_string (buffer, ", ");
630      dump_generic_node (buffer, TREE_IMAGPART (node), spc, flags, false);
631      pp_string (buffer, ")");
632      break;
633
634    case STRING_CST:
635      pp_string (buffer, "\"");
636      pretty_print_string (buffer, TREE_STRING_POINTER (node));
637      pp_string (buffer, "\"");
638      break;
639
640    case VECTOR_CST:
641      {
642	tree elt;
643	pp_string (buffer, "{ ");
644	for (elt = TREE_VECTOR_CST_ELTS (node); elt; elt = TREE_CHAIN (elt))
645	  {
646	    dump_generic_node (buffer, TREE_VALUE (elt), spc, flags, false);
647	    if (TREE_CHAIN (elt))
648	      pp_string (buffer, ", ");
649	  }
650	pp_string (buffer, " }");
651      }
652      break;
653
654    case FUNCTION_TYPE:
655      break;
656
657    case FUNCTION_DECL:
658    case CONST_DECL:
659      dump_decl_name (buffer, node, flags);
660      break;
661
662    case LABEL_DECL:
663      if (DECL_NAME (node))
664	dump_decl_name (buffer, node, flags);
665      else if (LABEL_DECL_UID (node) != -1)
666        pp_printf (buffer, "<L" HOST_WIDE_INT_PRINT_DEC ">",
667		   LABEL_DECL_UID (node));
668      else
669        pp_printf (buffer, "<D%u>", DECL_UID (node));
670      break;
671
672    case TYPE_DECL:
673      if (DECL_IS_BUILTIN (node))
674	{
675	  /* Don't print the declaration of built-in types.  */
676	  break;
677	}
678      if (DECL_NAME (node))
679	dump_decl_name (buffer, node, flags);
680      else
681	{
682	  if ((TREE_CODE (TREE_TYPE (node)) == RECORD_TYPE
683	       || TREE_CODE (TREE_TYPE (node)) == UNION_TYPE)
684	      && TYPE_METHODS (TREE_TYPE (node)))
685	    {
686	      /* The type is a c++ class: all structures have at least
687		 4 methods.  */
688	      pp_string (buffer, "class ");
689	      dump_generic_node (buffer, TREE_TYPE (node), spc, flags, false);
690	    }
691	  else
692	    {
693	      pp_string (buffer,
694			 (TREE_CODE (TREE_TYPE (node)) == UNION_TYPE
695			  ? "union" : "struct "));
696	      dump_generic_node (buffer, TREE_TYPE (node), spc, flags, false);
697	    }
698	}
699      break;
700
701    case VAR_DECL:
702    case PARM_DECL:
703    case FIELD_DECL:
704    case NAMESPACE_DECL:
705      dump_decl_name (buffer, node, flags);
706      break;
707
708    case RESULT_DECL:
709      pp_string (buffer, "<retval>");
710      break;
711
712    case COMPONENT_REF:
713      op0 = TREE_OPERAND (node, 0);
714      str = ".";
715      if (TREE_CODE (op0) == INDIRECT_REF)
716	{
717	  op0 = TREE_OPERAND (op0, 0);
718	  str = "->";
719	}
720      if (op_prio (op0) < op_prio (node))
721	pp_character (buffer, '(');
722      dump_generic_node (buffer, op0, spc, flags, false);
723      if (op_prio (op0) < op_prio (node))
724	pp_character (buffer, ')');
725      pp_string (buffer, str);
726      dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
727
728      if (TREE_CODE (op0) != VALUE_HANDLE)
729	{
730	  op0 = component_ref_field_offset (node);
731	  if (op0 && TREE_CODE (op0) != INTEGER_CST)
732	    {
733	      pp_string (buffer, "{off: ");
734	      dump_generic_node (buffer, op0, spc, flags, false);
735	      pp_character (buffer, '}');
736	    }
737	}
738      break;
739
740    case BIT_FIELD_REF:
741      pp_string (buffer, "BIT_FIELD_REF <");
742      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
743      pp_string (buffer, ", ");
744      dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
745      pp_string (buffer, ", ");
746      dump_generic_node (buffer, TREE_OPERAND (node, 2), spc, flags, false);
747      pp_string (buffer, ">");
748      break;
749
750    case ARRAY_REF:
751    case ARRAY_RANGE_REF:
752      op0 = TREE_OPERAND (node, 0);
753      if (op_prio (op0) < op_prio (node))
754	pp_character (buffer, '(');
755      dump_generic_node (buffer, op0, spc, flags, false);
756      if (op_prio (op0) < op_prio (node))
757	pp_character (buffer, ')');
758      pp_character (buffer, '[');
759      dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
760      if (TREE_CODE (node) == ARRAY_RANGE_REF)
761	pp_string (buffer, " ...");
762      pp_character (buffer, ']');
763
764      op0 = array_ref_low_bound (node);
765      op1 = array_ref_element_size (node);
766
767      if (!integer_zerop (op0)
768	  || (TYPE_SIZE_UNIT (TREE_TYPE (node))
769	      && !operand_equal_p (op1, TYPE_SIZE_UNIT (TREE_TYPE (node)), 0)))
770	{
771	  pp_string (buffer, "{lb: ");
772	  dump_generic_node (buffer, op0, spc, flags, false);
773	  pp_string (buffer, " sz: ");
774	  dump_generic_node (buffer, op1, spc, flags, false);
775	  pp_character (buffer, '}');
776	}
777      break;
778
779    case CONSTRUCTOR:
780      {
781	unsigned HOST_WIDE_INT ix;
782	tree field, val;
783	bool is_struct_init = FALSE;
784	pp_character (buffer, '{');
785	if (TREE_CODE (TREE_TYPE (node)) == RECORD_TYPE
786	    || TREE_CODE (TREE_TYPE (node)) == UNION_TYPE)
787	  is_struct_init = TRUE;
788	FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (node), ix, field, val)
789	  {
790	    if (field && is_struct_init)
791	      {
792		pp_character (buffer, '.');
793		dump_generic_node (buffer, field, spc, flags, false);
794		pp_string (buffer, "=");
795	      }
796	    if (val && TREE_CODE (val) == ADDR_EXPR)
797	      if (TREE_CODE (TREE_OPERAND (val, 0)) == FUNCTION_DECL)
798		val = TREE_OPERAND (val, 0);
799	    if (val && TREE_CODE (val) == FUNCTION_DECL)
800		dump_decl_name (buffer, val, flags);
801	    else
802		dump_generic_node (buffer, val, spc, flags, false);
803	    if (ix != VEC_length (constructor_elt, CONSTRUCTOR_ELTS (node)) - 1)
804	      {
805		pp_character (buffer, ',');
806		pp_space (buffer);
807	      }
808	  }
809	pp_character (buffer, '}');
810      }
811      break;
812
813    case COMPOUND_EXPR:
814      {
815	tree *tp;
816	if (flags & TDF_SLIM)
817	  {
818	    pp_string (buffer, "<COMPOUND_EXPR>");
819	    break;
820	  }
821
822	dump_generic_node (buffer, TREE_OPERAND (node, 0),
823			   spc, flags, dumping_stmts);
824	if (dumping_stmts)
825	  newline_and_indent (buffer, spc);
826	else
827	  {
828	    pp_character (buffer, ',');
829	    pp_space (buffer);
830	  }
831
832	for (tp = &TREE_OPERAND (node, 1);
833	     TREE_CODE (*tp) == COMPOUND_EXPR;
834	     tp = &TREE_OPERAND (*tp, 1))
835	  {
836	    dump_generic_node (buffer, TREE_OPERAND (*tp, 0),
837			       spc, flags, dumping_stmts);
838	    if (dumping_stmts)
839	      newline_and_indent (buffer, spc);
840	    else
841	      {
842	        pp_character (buffer, ',');
843	        pp_space (buffer);
844	      }
845	  }
846
847	dump_generic_node (buffer, *tp, spc, flags, dumping_stmts);
848      }
849      break;
850
851    case STATEMENT_LIST:
852      {
853	tree_stmt_iterator si;
854	bool first = true;
855
856	if ((flags & TDF_SLIM) || !dumping_stmts)
857	  {
858	    pp_string (buffer, "<STATEMENT_LIST>");
859	    break;
860	  }
861
862	for (si = tsi_start (node); !tsi_end_p (si); tsi_next (&si))
863	  {
864	    if (!first)
865	      newline_and_indent (buffer, spc);
866	    else
867	      first = false;
868	    dump_generic_node (buffer, tsi_stmt (si), spc, flags, true);
869	  }
870      }
871      break;
872
873    case MODIFY_EXPR:
874    case INIT_EXPR:
875      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
876      pp_space (buffer);
877      pp_character (buffer, '=');
878      pp_space (buffer);
879      dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
880      break;
881
882    case TARGET_EXPR:
883      pp_string (buffer, "TARGET_EXPR <");
884      dump_generic_node (buffer, TARGET_EXPR_SLOT (node), spc, flags, false);
885      pp_character (buffer, ',');
886      pp_space (buffer);
887      dump_generic_node (buffer, TARGET_EXPR_INITIAL (node), spc, flags, false);
888      pp_character (buffer, '>');
889      break;
890
891    case DECL_EXPR:
892      print_declaration (buffer, DECL_EXPR_DECL (node), spc, flags);
893      is_stmt = false;
894      break;
895
896    case COND_EXPR:
897      if (TREE_TYPE (node) == NULL || TREE_TYPE (node) == void_type_node)
898	{
899	  pp_string (buffer, "if (");
900	  dump_generic_node (buffer, COND_EXPR_COND (node), spc, flags, false);
901	  pp_character (buffer, ')');
902	  /* The lowered cond_exprs should always be printed in full.  */
903	  if (COND_EXPR_THEN (node)
904	      && (IS_EMPTY_STMT (COND_EXPR_THEN (node))
905		  || TREE_CODE (COND_EXPR_THEN (node)) == GOTO_EXPR)
906	      && COND_EXPR_ELSE (node)
907	      && (IS_EMPTY_STMT (COND_EXPR_ELSE (node))
908		  || TREE_CODE (COND_EXPR_ELSE (node)) == GOTO_EXPR))
909	    {
910	      pp_space (buffer);
911	      dump_generic_node (buffer, COND_EXPR_THEN (node), 0, flags, true);
912	      pp_string (buffer, " else ");
913	      dump_generic_node (buffer, COND_EXPR_ELSE (node), 0, flags, true);
914	    }
915	  else if (!(flags & TDF_SLIM))
916	    {
917	      /* Output COND_EXPR_THEN.  */
918	      if (COND_EXPR_THEN (node))
919		{
920		  newline_and_indent (buffer, spc+2);
921		  pp_character (buffer, '{');
922		  newline_and_indent (buffer, spc+4);
923		  dump_generic_node (buffer, COND_EXPR_THEN (node), spc+4,
924				     flags, true);
925		  newline_and_indent (buffer, spc+2);
926		  pp_character (buffer, '}');
927		}
928
929	      /* Output COND_EXPR_ELSE.  */
930	      if (COND_EXPR_ELSE (node))
931		{
932		  newline_and_indent (buffer, spc);
933		  pp_string (buffer, "else");
934		  newline_and_indent (buffer, spc+2);
935		  pp_character (buffer, '{');
936		  newline_and_indent (buffer, spc+4);
937		  dump_generic_node (buffer, COND_EXPR_ELSE (node), spc+4,
938			             flags, true);
939		  newline_and_indent (buffer, spc+2);
940		  pp_character (buffer, '}');
941		}
942	    }
943	  is_expr = false;
944	}
945      else
946	{
947	  dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
948	  pp_space (buffer);
949	  pp_character (buffer, '?');
950	  pp_space (buffer);
951	  dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
952	  pp_space (buffer);
953	  pp_character (buffer, ':');
954	  pp_space (buffer);
955	  dump_generic_node (buffer, TREE_OPERAND (node, 2), spc, flags, false);
956	}
957      break;
958
959    case BIND_EXPR:
960      pp_character (buffer, '{');
961      if (!(flags & TDF_SLIM))
962	{
963	  if (BIND_EXPR_VARS (node))
964	    {
965	      pp_newline (buffer);
966
967	      for (op0 = BIND_EXPR_VARS (node); op0; op0 = TREE_CHAIN (op0))
968		{
969		  print_declaration (buffer, op0, spc+2, flags);
970		  pp_newline (buffer);
971		}
972	    }
973
974	  newline_and_indent (buffer, spc+2);
975	  dump_generic_node (buffer, BIND_EXPR_BODY (node), spc+2, flags, true);
976	  newline_and_indent (buffer, spc);
977	  pp_character (buffer, '}');
978	}
979      is_expr = false;
980      break;
981
982    case CALL_EXPR:
983      print_call_name (buffer, node);
984
985      /* Print parameters.  */
986      pp_space (buffer);
987      pp_character (buffer, '(');
988      op1 = TREE_OPERAND (node, 1);
989      if (op1)
990	dump_generic_node (buffer, op1, spc, flags, false);
991      pp_character (buffer, ')');
992
993      op1 = TREE_OPERAND (node, 2);
994      if (op1)
995	{
996	  pp_string (buffer, " [static-chain: ");
997	  dump_generic_node (buffer, op1, spc, flags, false);
998	  pp_character (buffer, ']');
999	}
1000
1001      if (CALL_EXPR_RETURN_SLOT_OPT (node))
1002	pp_string (buffer, " [return slot optimization]");
1003      if (CALL_EXPR_TAILCALL (node))
1004	pp_string (buffer, " [tail call]");
1005      break;
1006
1007    case WITH_CLEANUP_EXPR:
1008      NIY;
1009      break;
1010
1011    case CLEANUP_POINT_EXPR:
1012      pp_string (buffer, "<<cleanup_point ");
1013      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1014      pp_string (buffer, ">>");
1015      break;
1016
1017    case PLACEHOLDER_EXPR:
1018      pp_string (buffer, "<PLACEHOLDER_EXPR ");
1019      dump_generic_node (buffer, TREE_TYPE (node), spc, flags, false);
1020      pp_character (buffer, '>');
1021      break;
1022
1023      /* Binary arithmetic and logic expressions.  */
1024    case MULT_EXPR:
1025    case PLUS_EXPR:
1026    case MINUS_EXPR:
1027    case TRUNC_DIV_EXPR:
1028    case CEIL_DIV_EXPR:
1029    case FLOOR_DIV_EXPR:
1030    case ROUND_DIV_EXPR:
1031    case TRUNC_MOD_EXPR:
1032    case CEIL_MOD_EXPR:
1033    case FLOOR_MOD_EXPR:
1034    case ROUND_MOD_EXPR:
1035    case RDIV_EXPR:
1036    case EXACT_DIV_EXPR:
1037    case LSHIFT_EXPR:
1038    case RSHIFT_EXPR:
1039    case LROTATE_EXPR:
1040    case RROTATE_EXPR:
1041    case VEC_LSHIFT_EXPR:
1042    case VEC_RSHIFT_EXPR:
1043    case BIT_IOR_EXPR:
1044    case BIT_XOR_EXPR:
1045    case BIT_AND_EXPR:
1046    case TRUTH_ANDIF_EXPR:
1047    case TRUTH_ORIF_EXPR:
1048    case TRUTH_AND_EXPR:
1049    case TRUTH_OR_EXPR:
1050    case TRUTH_XOR_EXPR:
1051    case LT_EXPR:
1052    case LE_EXPR:
1053    case GT_EXPR:
1054    case GE_EXPR:
1055    case EQ_EXPR:
1056    case NE_EXPR:
1057    case UNLT_EXPR:
1058    case UNLE_EXPR:
1059    case UNGT_EXPR:
1060    case UNGE_EXPR:
1061    case UNEQ_EXPR:
1062    case LTGT_EXPR:
1063    case ORDERED_EXPR:
1064    case UNORDERED_EXPR:
1065      {
1066	const char *op = op_symbol (node);
1067	op0 = TREE_OPERAND (node, 0);
1068	op1 = TREE_OPERAND (node, 1);
1069
1070	/* When the operands are expressions with less priority,
1071	   keep semantics of the tree representation.  */
1072	if (op_prio (op0) < op_prio (node))
1073	  {
1074	    pp_character (buffer, '(');
1075	    dump_generic_node (buffer, op0, spc, flags, false);
1076	    pp_character (buffer, ')');
1077	  }
1078	else
1079	  dump_generic_node (buffer, op0, spc, flags, false);
1080
1081	pp_space (buffer);
1082	pp_string (buffer, op);
1083	pp_space (buffer);
1084
1085	/* When the operands are expressions with less priority,
1086	   keep semantics of the tree representation.  */
1087	if (op_prio (op1) < op_prio (node))
1088	  {
1089	    pp_character (buffer, '(');
1090	    dump_generic_node (buffer, op1, spc, flags, false);
1091	    pp_character (buffer, ')');
1092	  }
1093	else
1094	  dump_generic_node (buffer, op1, spc, flags, false);
1095      }
1096      break;
1097
1098      /* Unary arithmetic and logic expressions.  */
1099    case NEGATE_EXPR:
1100    case BIT_NOT_EXPR:
1101    case TRUTH_NOT_EXPR:
1102    case ADDR_EXPR:
1103    case PREDECREMENT_EXPR:
1104    case PREINCREMENT_EXPR:
1105    case ALIGN_INDIRECT_REF:
1106    case MISALIGNED_INDIRECT_REF:
1107    case INDIRECT_REF:
1108      if (TREE_CODE (node) == ADDR_EXPR
1109	  && (TREE_CODE (TREE_OPERAND (node, 0)) == STRING_CST
1110	      || TREE_CODE (TREE_OPERAND (node, 0)) == FUNCTION_DECL))
1111	;	/* Do not output '&' for strings and function pointers.  */
1112      else
1113	pp_string (buffer, op_symbol (node));
1114
1115      if (op_prio (TREE_OPERAND (node, 0)) < op_prio (node))
1116	{
1117	  pp_character (buffer, '(');
1118	  dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1119	  pp_character (buffer, ')');
1120	}
1121      else
1122	dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1123
1124      if (TREE_CODE (node) == MISALIGNED_INDIRECT_REF)
1125        {
1126          pp_string (buffer, "{misalignment: ");
1127          dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
1128          pp_character (buffer, '}');
1129        }
1130      break;
1131
1132    case POSTDECREMENT_EXPR:
1133    case POSTINCREMENT_EXPR:
1134      if (op_prio (TREE_OPERAND (node, 0)) < op_prio (node))
1135	{
1136	  pp_character (buffer, '(');
1137	  dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1138	  pp_character (buffer, ')');
1139	}
1140      else
1141	dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1142      pp_string (buffer, op_symbol (node));
1143      break;
1144
1145    case MIN_EXPR:
1146      pp_string (buffer, "MIN_EXPR <");
1147      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1148      pp_string (buffer, ", ");
1149      dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
1150      pp_character (buffer, '>');
1151      break;
1152
1153    case MAX_EXPR:
1154      pp_string (buffer, "MAX_EXPR <");
1155      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1156      pp_string (buffer, ", ");
1157      dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
1158      pp_character (buffer, '>');
1159      break;
1160
1161    case ABS_EXPR:
1162      pp_string (buffer, "ABS_EXPR <");
1163      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1164      pp_character (buffer, '>');
1165      break;
1166
1167    case RANGE_EXPR:
1168      NIY;
1169      break;
1170
1171    case FIX_TRUNC_EXPR:
1172    case FIX_CEIL_EXPR:
1173    case FIX_FLOOR_EXPR:
1174    case FIX_ROUND_EXPR:
1175    case FLOAT_EXPR:
1176    case CONVERT_EXPR:
1177    case NOP_EXPR:
1178      type = TREE_TYPE (node);
1179      op0 = TREE_OPERAND (node, 0);
1180      if (type != TREE_TYPE (op0))
1181	{
1182	  pp_character (buffer, '(');
1183	  dump_generic_node (buffer, type, spc, flags, false);
1184	  pp_string (buffer, ") ");
1185	}
1186      if (op_prio (op0) < op_prio (node))
1187	pp_character (buffer, '(');
1188      dump_generic_node (buffer, op0, spc, flags, false);
1189      if (op_prio (op0) < op_prio (node))
1190	pp_character (buffer, ')');
1191      break;
1192
1193    case VIEW_CONVERT_EXPR:
1194      pp_string (buffer, "VIEW_CONVERT_EXPR<");
1195      dump_generic_node (buffer, TREE_TYPE (node), spc, flags, false);
1196      pp_string (buffer, ">(");
1197      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1198      pp_character (buffer, ')');
1199      break;
1200
1201    case NON_LVALUE_EXPR:
1202      pp_string (buffer, "NON_LVALUE_EXPR <");
1203      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1204      pp_character (buffer, '>');
1205      break;
1206
1207    case SAVE_EXPR:
1208      pp_string (buffer, "SAVE_EXPR <");
1209      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1210      pp_character (buffer, '>');
1211      break;
1212
1213    case COMPLEX_EXPR:
1214      pp_string (buffer, "COMPLEX_EXPR <");
1215      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1216      pp_string (buffer, ", ");
1217      dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
1218      pp_string (buffer, ">");
1219      break;
1220
1221    case CONJ_EXPR:
1222      pp_string (buffer, "CONJ_EXPR <");
1223      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1224      pp_string (buffer, ">");
1225      break;
1226
1227    case REALPART_EXPR:
1228      pp_string (buffer, "REALPART_EXPR <");
1229      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1230      pp_string (buffer, ">");
1231      break;
1232
1233    case IMAGPART_EXPR:
1234      pp_string (buffer, "IMAGPART_EXPR <");
1235      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1236      pp_string (buffer, ">");
1237      break;
1238
1239    case VA_ARG_EXPR:
1240      pp_string (buffer, "VA_ARG_EXPR <");
1241      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1242      pp_string (buffer, ">");
1243      break;
1244
1245    case TRY_FINALLY_EXPR:
1246    case TRY_CATCH_EXPR:
1247      pp_string (buffer, "try");
1248      newline_and_indent (buffer, spc+2);
1249      pp_string (buffer, "{");
1250      newline_and_indent (buffer, spc+4);
1251      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc+4, flags, true);
1252      newline_and_indent (buffer, spc+2);
1253      pp_string (buffer, "}");
1254      newline_and_indent (buffer, spc);
1255      pp_string (buffer,
1256			 (TREE_CODE (node) == TRY_CATCH_EXPR) ? "catch" : "finally");
1257      newline_and_indent (buffer, spc+2);
1258      pp_string (buffer, "{");
1259      newline_and_indent (buffer, spc+4);
1260      dump_generic_node (buffer, TREE_OPERAND (node, 1), spc+4, flags, true);
1261      newline_and_indent (buffer, spc+2);
1262      pp_string (buffer, "}");
1263      is_expr = false;
1264      break;
1265
1266    case CATCH_EXPR:
1267      pp_string (buffer, "catch (");
1268      dump_generic_node (buffer, CATCH_TYPES (node), spc+2, flags, false);
1269      pp_string (buffer, ")");
1270      newline_and_indent (buffer, spc+2);
1271      pp_string (buffer, "{");
1272      newline_and_indent (buffer, spc+4);
1273      dump_generic_node (buffer, CATCH_BODY (node), spc+4, flags, true);
1274      newline_and_indent (buffer, spc+2);
1275      pp_string (buffer, "}");
1276      is_expr = false;
1277      break;
1278
1279    case EH_FILTER_EXPR:
1280      pp_string (buffer, "<<<eh_filter (");
1281      dump_generic_node (buffer, EH_FILTER_TYPES (node), spc+2, flags, false);
1282      pp_string (buffer, ")>>>");
1283      newline_and_indent (buffer, spc+2);
1284      pp_string (buffer, "{");
1285      newline_and_indent (buffer, spc+4);
1286      dump_generic_node (buffer, EH_FILTER_FAILURE (node), spc+4, flags, true);
1287      newline_and_indent (buffer, spc+2);
1288      pp_string (buffer, "}");
1289      is_expr = false;
1290      break;
1291
1292    case LABEL_EXPR:
1293      op0 = TREE_OPERAND (node, 0);
1294      /* If this is for break or continue, don't bother printing it.  */
1295      if (DECL_NAME (op0))
1296	{
1297	  const char *name = IDENTIFIER_POINTER (DECL_NAME (op0));
1298	  if (strcmp (name, "break") == 0
1299	      || strcmp (name, "continue") == 0)
1300	    break;
1301	}
1302      dump_generic_node (buffer, op0, spc, flags, false);
1303      pp_character (buffer, ':');
1304      if (DECL_NONLOCAL (op0))
1305	pp_string (buffer, " [non-local]");
1306      break;
1307
1308    case EXC_PTR_EXPR:
1309      pp_string (buffer, "<<<exception object>>>");
1310      break;
1311
1312    case FILTER_EXPR:
1313      pp_string (buffer, "<<<filter object>>>");
1314      break;
1315
1316    case LOOP_EXPR:
1317      pp_string (buffer, "while (1)");
1318      if (!(flags & TDF_SLIM))
1319	{
1320	  newline_and_indent (buffer, spc+2);
1321	  pp_character (buffer, '{');
1322	  newline_and_indent (buffer, spc+4);
1323	  dump_generic_node (buffer, LOOP_EXPR_BODY (node), spc+4, flags, true);
1324	  newline_and_indent (buffer, spc+2);
1325	  pp_character (buffer, '}');
1326	}
1327      is_expr = false;
1328      break;
1329
1330    case RETURN_EXPR:
1331      pp_string (buffer, "return");
1332      op0 = TREE_OPERAND (node, 0);
1333      if (op0)
1334	{
1335	  pp_space (buffer);
1336	  if (TREE_CODE (op0) == MODIFY_EXPR)
1337	    dump_generic_node (buffer, TREE_OPERAND (op0, 1), spc, flags, false);
1338	  else
1339	    dump_generic_node (buffer, op0, spc, flags, false);
1340	}
1341      break;
1342
1343    case EXIT_EXPR:
1344      pp_string (buffer, "if (");
1345      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1346      pp_string (buffer, ") break");
1347      break;
1348
1349    case SWITCH_EXPR:
1350      pp_string (buffer, "switch (");
1351      dump_generic_node (buffer, SWITCH_COND (node), spc, flags, false);
1352      pp_character (buffer, ')');
1353      if (!(flags & TDF_SLIM))
1354	{
1355	  newline_and_indent (buffer, spc+2);
1356	  pp_character (buffer, '{');
1357	  if (SWITCH_BODY (node))
1358	    {
1359	      newline_and_indent (buffer, spc+4);
1360	      dump_generic_node (buffer, SWITCH_BODY (node), spc+4, flags, true);
1361	    }
1362	  else
1363	    {
1364	      tree vec = SWITCH_LABELS (node);
1365	      size_t i, n = TREE_VEC_LENGTH (vec);
1366	      for (i = 0; i < n; ++i)
1367		{
1368		  tree elt = TREE_VEC_ELT (vec, i);
1369		  newline_and_indent (buffer, spc+4);
1370		  dump_generic_node (buffer, elt, spc+4, flags, false);
1371		  pp_string (buffer, " goto ");
1372		  dump_generic_node (buffer, CASE_LABEL (elt), spc+4, flags, true);
1373		  pp_semicolon (buffer);
1374		}
1375	    }
1376	  newline_and_indent (buffer, spc+2);
1377	  pp_character (buffer, '}');
1378	}
1379      is_expr = false;
1380      break;
1381
1382    case GOTO_EXPR:
1383      op0 = GOTO_DESTINATION (node);
1384      if (TREE_CODE (op0) != SSA_NAME && DECL_P (op0) && DECL_NAME (op0))
1385	{
1386	  const char *name = IDENTIFIER_POINTER (DECL_NAME (op0));
1387	  if (strcmp (name, "break") == 0
1388	      || strcmp (name, "continue") == 0)
1389	    {
1390	      pp_string (buffer, name);
1391	      break;
1392	    }
1393	}
1394      pp_string (buffer, "goto ");
1395      dump_generic_node (buffer, op0, spc, flags, false);
1396      break;
1397
1398    case RESX_EXPR:
1399      pp_string (buffer, "resx");
1400      /* ??? Any sensible way to present the eh region?  */
1401      break;
1402
1403    case ASM_EXPR:
1404      pp_string (buffer, "__asm__");
1405      if (ASM_VOLATILE_P (node))
1406	pp_string (buffer, " __volatile__");
1407      pp_character (buffer, '(');
1408      dump_generic_node (buffer, ASM_STRING (node), spc, flags, false);
1409      pp_character (buffer, ':');
1410      dump_generic_node (buffer, ASM_OUTPUTS (node), spc, flags, false);
1411      pp_character (buffer, ':');
1412      dump_generic_node (buffer, ASM_INPUTS (node), spc, flags, false);
1413      if (ASM_CLOBBERS (node))
1414	{
1415	  pp_character (buffer, ':');
1416	  dump_generic_node (buffer, ASM_CLOBBERS (node), spc, flags, false);
1417	}
1418      pp_string (buffer, ")");
1419      break;
1420
1421    case CASE_LABEL_EXPR:
1422      if (CASE_LOW (node) && CASE_HIGH (node))
1423	{
1424	  pp_string (buffer, "case ");
1425	  dump_generic_node (buffer, CASE_LOW (node), spc, flags, false);
1426	  pp_string (buffer, " ... ");
1427	  dump_generic_node (buffer, CASE_HIGH (node), spc, flags, false);
1428	}
1429      else if (CASE_LOW (node))
1430	{
1431	  pp_string (buffer, "case ");
1432	  dump_generic_node (buffer, CASE_LOW (node), spc, flags, false);
1433	}
1434      else
1435	pp_string (buffer, "default ");
1436      pp_character (buffer, ':');
1437      break;
1438
1439    case OBJ_TYPE_REF:
1440      pp_string (buffer, "OBJ_TYPE_REF(");
1441      dump_generic_node (buffer, OBJ_TYPE_REF_EXPR (node), spc, flags, false);
1442      pp_character (buffer, ';');
1443      dump_generic_node (buffer, OBJ_TYPE_REF_OBJECT (node), spc, flags, false);
1444      pp_character (buffer, '-');
1445      pp_character (buffer, '>');
1446      dump_generic_node (buffer, OBJ_TYPE_REF_TOKEN (node), spc, flags, false);
1447      pp_character (buffer, ')');
1448      break;
1449
1450    case PHI_NODE:
1451      {
1452	int i;
1453
1454	dump_generic_node (buffer, PHI_RESULT (node), spc, flags, false);
1455	pp_string (buffer, " = PHI <");
1456	for (i = 0; i < PHI_NUM_ARGS (node); i++)
1457	  {
1458	    dump_generic_node (buffer, PHI_ARG_DEF (node, i), spc, flags, false);
1459	    pp_string (buffer, "(");
1460	    pp_decimal_int (buffer, PHI_ARG_EDGE (node, i)->src->index);
1461	    pp_string (buffer, ")");
1462	    if (i < PHI_NUM_ARGS (node) - 1)
1463	      pp_string (buffer, ", ");
1464	  }
1465	pp_string (buffer, ">;");
1466      }
1467      break;
1468
1469    case SSA_NAME:
1470      dump_generic_node (buffer, SSA_NAME_VAR (node), spc, flags, false);
1471      pp_string (buffer, "_");
1472      pp_decimal_int (buffer, SSA_NAME_VERSION (node));
1473      if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (node))
1474	pp_string (buffer, "(ab)");
1475      break;
1476
1477    case WITH_SIZE_EXPR:
1478      pp_string (buffer, "WITH_SIZE_EXPR <");
1479      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1480      pp_string (buffer, ", ");
1481      dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
1482      pp_string (buffer, ">");
1483      break;
1484
1485    case VALUE_HANDLE:
1486      pp_printf (buffer, "VH.%d", VALUE_HANDLE_ID (node));
1487      break;
1488
1489    case ASSERT_EXPR:
1490      pp_string (buffer, "ASSERT_EXPR <");
1491      dump_generic_node (buffer, ASSERT_EXPR_VAR (node), spc, flags, false);
1492      pp_string (buffer, ", ");
1493      dump_generic_node (buffer, ASSERT_EXPR_COND (node), spc, flags, false);
1494      pp_string (buffer, ">");
1495      break;
1496
1497    case SCEV_KNOWN:
1498      pp_string (buffer, "scev_known");
1499      break;
1500
1501    case SCEV_NOT_KNOWN:
1502      pp_string (buffer, "scev_not_known");
1503      break;
1504
1505    case POLYNOMIAL_CHREC:
1506      pp_string (buffer, "{");
1507      dump_generic_node (buffer, CHREC_LEFT (node), spc, flags, false);
1508      pp_string (buffer, ", +, ");
1509      dump_generic_node (buffer, CHREC_RIGHT (node), spc, flags, false);
1510      pp_string (buffer, "}_");
1511      dump_generic_node (buffer, CHREC_VAR (node), spc, flags, false);
1512      is_stmt = false;
1513      break;
1514
1515    case REALIGN_LOAD_EXPR:
1516      pp_string (buffer, "REALIGN_LOAD <");
1517      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1518      pp_string (buffer, ", ");
1519      dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
1520      pp_string (buffer, ", ");
1521      dump_generic_node (buffer, TREE_OPERAND (node, 2), spc, flags, false);
1522      pp_string (buffer, ">");
1523      break;
1524
1525    case VEC_COND_EXPR:
1526      pp_string (buffer, " VEC_COND_EXPR < ");
1527      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1528      pp_string (buffer, " , ");
1529      dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
1530      pp_string (buffer, " , ");
1531      dump_generic_node (buffer, TREE_OPERAND (node, 2), spc, flags, false);
1532      pp_string (buffer, " > ");
1533      break;
1534
1535    case REDUC_MAX_EXPR:
1536      pp_string (buffer, " REDUC_MAX_EXPR < ");
1537      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1538      pp_string (buffer, " > ");
1539      break;
1540
1541    case REDUC_MIN_EXPR:
1542      pp_string (buffer, " REDUC_MIN_EXPR < ");
1543      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1544      pp_string (buffer, " > ");
1545      break;
1546
1547    case REDUC_PLUS_EXPR:
1548      pp_string (buffer, " REDUC_PLUS_EXPR < ");
1549      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1550      pp_string (buffer, " > ");
1551      break;
1552
1553    default:
1554      NIY;
1555    }
1556
1557  if (is_stmt && is_expr)
1558    pp_semicolon (buffer);
1559  pp_write_text_to_stream (buffer);
1560
1561  return spc;
1562}
1563
1564/* Print the declaration of a variable.  */
1565
1566static void
1567print_declaration (pretty_printer *buffer, tree t, int spc, int flags)
1568{
1569  INDENT (spc);
1570
1571  if (TREE_CODE (t) == TYPE_DECL)
1572    pp_string (buffer, "typedef ");
1573
1574  if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_WRTL) && DECL_REGISTER (t))
1575    pp_string (buffer, "register ");
1576
1577  if (TREE_PUBLIC (t) && DECL_EXTERNAL (t))
1578    pp_string (buffer, "extern ");
1579  else if (TREE_STATIC (t))
1580    pp_string (buffer, "static ");
1581
1582  /* Print the type and name.  */
1583  if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
1584    {
1585      tree tmp;
1586
1587      /* Print array's type.  */
1588      tmp = TREE_TYPE (t);
1589      while (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
1590	tmp = TREE_TYPE (tmp);
1591      dump_generic_node (buffer, TREE_TYPE (tmp), spc, flags, false);
1592
1593      /* Print variable's name.  */
1594      pp_space (buffer);
1595      dump_generic_node (buffer, t, spc, flags, false);
1596
1597      /* Print the dimensions.  */
1598      tmp = TREE_TYPE (t);
1599      while (TREE_CODE (tmp) == ARRAY_TYPE)
1600	{
1601	  dump_array_domain (buffer, TYPE_DOMAIN (tmp), spc, flags);
1602	  tmp = TREE_TYPE (tmp);
1603	}
1604    }
1605  else if (TREE_CODE (t) == FUNCTION_DECL)
1606    {
1607      dump_generic_node (buffer, TREE_TYPE (TREE_TYPE (t)), spc, flags, false);
1608      pp_space (buffer);
1609      dump_decl_name (buffer, t, flags);
1610      dump_function_declaration (buffer, TREE_TYPE (t), spc, flags);
1611    }
1612  else
1613    {
1614      /* Print type declaration.  */
1615      dump_generic_node (buffer, TREE_TYPE (t), spc, flags, false);
1616
1617      /* Print variable's name.  */
1618      pp_space (buffer);
1619      dump_generic_node (buffer, t, spc, flags, false);
1620    }
1621
1622  if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
1623    {
1624      pp_string (buffer, " __asm__ ");
1625      pp_character (buffer, '(');
1626      dump_generic_node (buffer, DECL_ASSEMBLER_NAME (t), spc, flags, false);
1627      pp_character (buffer, ')');
1628    }
1629
1630  /* The initial value of a function serves to determine wether the function
1631     is declared or defined.  So the following does not apply to function
1632     nodes.  */
1633  if (TREE_CODE (t) != FUNCTION_DECL)
1634    {
1635      /* Print the initial value.  */
1636      if (DECL_INITIAL (t))
1637	{
1638	  pp_space (buffer);
1639	  pp_character (buffer, '=');
1640	  pp_space (buffer);
1641	  dump_generic_node (buffer, DECL_INITIAL (t), spc, flags, false);
1642	}
1643    }
1644
1645  pp_character (buffer, ';');
1646}
1647
1648
1649/* Prints a structure: name, fields, and methods.
1650   FIXME: Still incomplete.  */
1651
1652static void
1653print_struct_decl (pretty_printer *buffer, tree node, int spc, int flags)
1654{
1655  /* Print the name of the structure.  */
1656  if (TYPE_NAME (node))
1657    {
1658      INDENT (spc);
1659      if (TREE_CODE (node) == RECORD_TYPE)
1660	pp_string (buffer, "struct ");
1661      else if ((TREE_CODE (node) == UNION_TYPE
1662		|| TREE_CODE (node) == QUAL_UNION_TYPE))
1663	pp_string (buffer, "union ");
1664
1665      dump_generic_node (buffer, TYPE_NAME (node), spc, 0, false);
1666    }
1667
1668  /* Print the contents of the structure.  */
1669  pp_newline (buffer);
1670  INDENT (spc);
1671  pp_character (buffer, '{');
1672  pp_newline (buffer);
1673
1674  /* Print the fields of the structure.  */
1675  {
1676    tree tmp;
1677    tmp = TYPE_FIELDS (node);
1678    while (tmp)
1679      {
1680	/* Avoid to print recursively the structure.  */
1681	/* FIXME : Not implemented correctly...,
1682	   what about the case when we have a cycle in the contain graph? ...
1683	   Maybe this could be solved by looking at the scope in which the
1684	   structure was declared.  */
1685	if (TREE_TYPE (tmp) != node
1686	    || (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE
1687		&& TREE_TYPE (TREE_TYPE (tmp)) != node))
1688	  {
1689	    print_declaration (buffer, tmp, spc+2, flags);
1690	    pp_newline (buffer);
1691	  }
1692	tmp = TREE_CHAIN (tmp);
1693      }
1694  }
1695  INDENT (spc);
1696  pp_character (buffer, '}');
1697}
1698
1699/* Return the priority of the operator OP.
1700
1701   From lowest to highest precedence with either left-to-right (L-R)
1702   or right-to-left (R-L) associativity]:
1703
1704     1	[L-R] ,
1705     2	[R-L] = += -= *= /= %= &= ^= |= <<= >>=
1706     3	[R-L] ?:
1707     4	[L-R] ||
1708     5	[L-R] &&
1709     6	[L-R] |
1710     7	[L-R] ^
1711     8	[L-R] &
1712     9	[L-R] == !=
1713    10	[L-R] < <= > >=
1714    11	[L-R] << >>
1715    12	[L-R] + -
1716    13	[L-R] * / %
1717    14	[R-L] ! ~ ++ -- + - * & (type) sizeof
1718    15	[L-R] fn() [] -> .
1719
1720   unary +, - and * have higher precedence than the corresponding binary
1721   operators.  */
1722
1723static int
1724op_prio (tree op)
1725{
1726  if (op == NULL)
1727    return 9999;
1728
1729  switch (TREE_CODE (op))
1730    {
1731    case TREE_LIST:
1732    case COMPOUND_EXPR:
1733    case BIND_EXPR:
1734      return 1;
1735
1736    case MODIFY_EXPR:
1737    case INIT_EXPR:
1738      return 2;
1739
1740    case COND_EXPR:
1741      return 3;
1742
1743    case TRUTH_OR_EXPR:
1744    case TRUTH_ORIF_EXPR:
1745      return 4;
1746
1747    case TRUTH_AND_EXPR:
1748    case TRUTH_ANDIF_EXPR:
1749      return 5;
1750
1751    case BIT_IOR_EXPR:
1752      return 6;
1753
1754    case BIT_XOR_EXPR:
1755    case TRUTH_XOR_EXPR:
1756      return 7;
1757
1758    case BIT_AND_EXPR:
1759      return 8;
1760
1761    case EQ_EXPR:
1762    case NE_EXPR:
1763      return 9;
1764
1765    case UNLT_EXPR:
1766    case UNLE_EXPR:
1767    case UNGT_EXPR:
1768    case UNGE_EXPR:
1769    case UNEQ_EXPR:
1770    case LTGT_EXPR:
1771    case ORDERED_EXPR:
1772    case UNORDERED_EXPR:
1773    case LT_EXPR:
1774    case LE_EXPR:
1775    case GT_EXPR:
1776    case GE_EXPR:
1777      return 10;
1778
1779    case LSHIFT_EXPR:
1780    case RSHIFT_EXPR:
1781    case LROTATE_EXPR:
1782    case RROTATE_EXPR:
1783      return 11;
1784
1785    case PLUS_EXPR:
1786    case MINUS_EXPR:
1787      return 12;
1788
1789    case MULT_EXPR:
1790    case TRUNC_DIV_EXPR:
1791    case CEIL_DIV_EXPR:
1792    case FLOOR_DIV_EXPR:
1793    case ROUND_DIV_EXPR:
1794    case RDIV_EXPR:
1795    case EXACT_DIV_EXPR:
1796    case TRUNC_MOD_EXPR:
1797    case CEIL_MOD_EXPR:
1798    case FLOOR_MOD_EXPR:
1799    case ROUND_MOD_EXPR:
1800      return 13;
1801
1802    case TRUTH_NOT_EXPR:
1803    case BIT_NOT_EXPR:
1804    case POSTINCREMENT_EXPR:
1805    case POSTDECREMENT_EXPR:
1806    case PREINCREMENT_EXPR:
1807    case PREDECREMENT_EXPR:
1808    case NEGATE_EXPR:
1809    case ALIGN_INDIRECT_REF:
1810    case MISALIGNED_INDIRECT_REF:
1811    case INDIRECT_REF:
1812    case ADDR_EXPR:
1813    case FLOAT_EXPR:
1814    case NOP_EXPR:
1815    case CONVERT_EXPR:
1816    case FIX_TRUNC_EXPR:
1817    case FIX_CEIL_EXPR:
1818    case FIX_FLOOR_EXPR:
1819    case FIX_ROUND_EXPR:
1820    case TARGET_EXPR:
1821      return 14;
1822
1823    case CALL_EXPR:
1824    case ARRAY_REF:
1825    case ARRAY_RANGE_REF:
1826    case COMPONENT_REF:
1827      return 15;
1828
1829      /* Special expressions.  */
1830    case MIN_EXPR:
1831    case MAX_EXPR:
1832    case ABS_EXPR:
1833    case REALPART_EXPR:
1834    case IMAGPART_EXPR:
1835    case REDUC_MAX_EXPR:
1836    case REDUC_MIN_EXPR:
1837    case REDUC_PLUS_EXPR:
1838    case VEC_LSHIFT_EXPR:
1839    case VEC_RSHIFT_EXPR:
1840      return 16;
1841
1842    case SAVE_EXPR:
1843    case NON_LVALUE_EXPR:
1844      return op_prio (TREE_OPERAND (op, 0));
1845
1846    default:
1847      /* Return an arbitrarily high precedence to avoid surrounding single
1848	 VAR_DECLs in ()s.  */
1849      return 9999;
1850    }
1851}
1852
1853
1854/* Return the symbol associated with operator OP.  */
1855
1856static const char *
1857op_symbol (tree op)
1858{
1859  gcc_assert (op);
1860
1861  switch (TREE_CODE (op))
1862    {
1863    case MODIFY_EXPR:
1864      return "=";
1865
1866    case TRUTH_OR_EXPR:
1867    case TRUTH_ORIF_EXPR:
1868      return "||";
1869
1870    case TRUTH_AND_EXPR:
1871    case TRUTH_ANDIF_EXPR:
1872      return "&&";
1873
1874    case BIT_IOR_EXPR:
1875      return "|";
1876
1877    case TRUTH_XOR_EXPR:
1878    case BIT_XOR_EXPR:
1879      return "^";
1880
1881    case ADDR_EXPR:
1882    case BIT_AND_EXPR:
1883      return "&";
1884
1885    case ORDERED_EXPR:
1886      return "ord";
1887    case UNORDERED_EXPR:
1888      return "unord";
1889
1890    case EQ_EXPR:
1891      return "==";
1892    case UNEQ_EXPR:
1893      return "u==";
1894
1895    case NE_EXPR:
1896      return "!=";
1897
1898    case LT_EXPR:
1899      return "<";
1900    case UNLT_EXPR:
1901      return "u<";
1902
1903    case LE_EXPR:
1904      return "<=";
1905    case UNLE_EXPR:
1906      return "u<=";
1907
1908    case GT_EXPR:
1909      return ">";
1910    case UNGT_EXPR:
1911      return "u>";
1912
1913    case GE_EXPR:
1914      return ">=";
1915    case UNGE_EXPR:
1916      return "u>=";
1917
1918    case LTGT_EXPR:
1919      return "<>";
1920
1921    case LSHIFT_EXPR:
1922      return "<<";
1923
1924    case RSHIFT_EXPR:
1925      return ">>";
1926
1927    case VEC_LSHIFT_EXPR:
1928      return "v<<";
1929
1930    case VEC_RSHIFT_EXPR:
1931      return "v>>";
1932
1933    case PLUS_EXPR:
1934      return "+";
1935
1936    case REDUC_PLUS_EXPR:
1937      return "r+";
1938
1939    case NEGATE_EXPR:
1940    case MINUS_EXPR:
1941      return "-";
1942
1943    case BIT_NOT_EXPR:
1944      return "~";
1945
1946    case TRUTH_NOT_EXPR:
1947      return "!";
1948
1949    case MULT_EXPR:
1950    case INDIRECT_REF:
1951      return "*";
1952
1953    case ALIGN_INDIRECT_REF:
1954      return "A*";
1955
1956    case MISALIGNED_INDIRECT_REF:
1957      return "M*";
1958
1959    case TRUNC_DIV_EXPR:
1960    case RDIV_EXPR:
1961      return "/";
1962
1963    case CEIL_DIV_EXPR:
1964      return "/[cl]";
1965
1966    case FLOOR_DIV_EXPR:
1967      return "/[fl]";
1968
1969    case ROUND_DIV_EXPR:
1970      return "/[rd]";
1971
1972    case EXACT_DIV_EXPR:
1973      return "/[ex]";
1974
1975    case TRUNC_MOD_EXPR:
1976      return "%";
1977
1978    case CEIL_MOD_EXPR:
1979      return "%[cl]";
1980
1981    case FLOOR_MOD_EXPR:
1982      return "%[fl]";
1983
1984    case ROUND_MOD_EXPR:
1985      return "%[rd]";
1986
1987    case PREDECREMENT_EXPR:
1988      return " --";
1989
1990    case PREINCREMENT_EXPR:
1991      return " ++";
1992
1993    case POSTDECREMENT_EXPR:
1994      return "-- ";
1995
1996    case POSTINCREMENT_EXPR:
1997      return "++ ";
1998
1999    default:
2000      return "<<< ??? >>>";
2001    }
2002}
2003
2004/* Prints the name of a CALL_EXPR.  */
2005
2006static void
2007print_call_name (pretty_printer *buffer, tree node)
2008{
2009  tree op0;
2010
2011  gcc_assert (TREE_CODE (node) == CALL_EXPR);
2012
2013  op0 = TREE_OPERAND (node, 0);
2014
2015  if (TREE_CODE (op0) == NON_LVALUE_EXPR)
2016    op0 = TREE_OPERAND (op0, 0);
2017
2018  switch (TREE_CODE (op0))
2019    {
2020    case VAR_DECL:
2021    case PARM_DECL:
2022      dump_function_name (buffer, op0);
2023      break;
2024
2025    case ADDR_EXPR:
2026    case INDIRECT_REF:
2027    case NOP_EXPR:
2028      dump_generic_node (buffer, TREE_OPERAND (op0, 0), 0, 0, false);
2029      break;
2030
2031    case COND_EXPR:
2032      pp_string (buffer, "(");
2033      dump_generic_node (buffer, TREE_OPERAND (op0, 0), 0, 0, false);
2034      pp_string (buffer, ") ? ");
2035      dump_generic_node (buffer, TREE_OPERAND (op0, 1), 0, 0, false);
2036      pp_string (buffer, " : ");
2037      dump_generic_node (buffer, TREE_OPERAND (op0, 2), 0, 0, false);
2038      break;
2039
2040    case COMPONENT_REF:
2041      /* The function is a pointer contained in a structure.  */
2042      if (TREE_CODE (TREE_OPERAND (op0, 0)) == INDIRECT_REF ||
2043	  TREE_CODE (TREE_OPERAND (op0, 0)) == VAR_DECL)
2044	dump_function_name (buffer, TREE_OPERAND (op0, 1));
2045      else
2046	dump_generic_node (buffer, TREE_OPERAND (op0, 0), 0, 0, false);
2047      /* else
2048	 We can have several levels of structures and a function
2049	 pointer inside.  This is not implemented yet...  */
2050      /*		  NIY;*/
2051      break;
2052
2053    case ARRAY_REF:
2054      if (TREE_CODE (TREE_OPERAND (op0, 0)) == VAR_DECL)
2055	dump_function_name (buffer, TREE_OPERAND (op0, 0));
2056      else
2057	dump_generic_node (buffer, op0, 0, 0, false);
2058      break;
2059
2060    case SSA_NAME:
2061    case OBJ_TYPE_REF:
2062      dump_generic_node (buffer, op0, 0, 0, false);
2063      break;
2064
2065    default:
2066      NIY;
2067    }
2068}
2069
2070/* Parses the string STR and replaces new-lines by '\n', tabs by '\t', ...  */
2071
2072static void
2073pretty_print_string (pretty_printer *buffer, const char *str)
2074{
2075  if (str == NULL)
2076    return;
2077
2078  while (*str)
2079    {
2080      switch (str[0])
2081	{
2082	case '\b':
2083	  pp_string (buffer, "\\b");
2084	  break;
2085
2086	case '\f':
2087	  pp_string (buffer, "\\f");
2088	  break;
2089
2090	case '\n':
2091	  pp_string (buffer, "\\n");
2092	  break;
2093
2094	case '\r':
2095	  pp_string (buffer, "\\r");
2096	  break;
2097
2098	case '\t':
2099	  pp_string (buffer, "\\t");
2100	  break;
2101
2102	case '\v':
2103	  pp_string (buffer, "\\v");
2104	  break;
2105
2106	case '\\':
2107	  pp_string (buffer, "\\\\");
2108	  break;
2109
2110	case '\"':
2111	  pp_string (buffer, "\\\"");
2112	  break;
2113
2114	case '\'':
2115	  pp_string (buffer, "\\'");
2116	  break;
2117
2118	case '\0':
2119	  pp_string (buffer, "\\0");
2120	  break;
2121
2122	case '\1':
2123	  pp_string (buffer, "\\1");
2124	  break;
2125
2126	case '\2':
2127	  pp_string (buffer, "\\2");
2128	  break;
2129
2130	case '\3':
2131	  pp_string (buffer, "\\3");
2132	  break;
2133
2134	case '\4':
2135	  pp_string (buffer, "\\4");
2136	  break;
2137
2138	case '\5':
2139	  pp_string (buffer, "\\5");
2140	  break;
2141
2142	case '\6':
2143	  pp_string (buffer, "\\6");
2144	  break;
2145
2146	case '\7':
2147	  pp_string (buffer, "\\7");
2148	  break;
2149
2150	default:
2151	  pp_character (buffer, str[0]);
2152	  break;
2153	}
2154      str++;
2155    }
2156}
2157
2158static void
2159maybe_init_pretty_print (FILE *file)
2160{
2161  if (!initialized)
2162    {
2163      pp_construct (&buffer, /* prefix */NULL, /* line-width */0);
2164      pp_needs_newline (&buffer) = true;
2165      initialized = 1;
2166    }
2167
2168  buffer.buffer->stream = file;
2169}
2170
2171static void
2172newline_and_indent (pretty_printer *buffer, int spc)
2173{
2174  pp_newline (buffer);
2175  INDENT (spc);
2176}
2177
2178static void
2179dump_vops (pretty_printer *buffer, tree stmt, int spc, int flags)
2180{
2181  tree use;
2182  use_operand_p use_p;
2183  def_operand_p def_p;
2184  use_operand_p kill_p;
2185  ssa_op_iter iter;
2186
2187  if (!ssa_operands_active ())
2188    return;
2189
2190  FOR_EACH_SSA_MAYDEF_OPERAND (def_p, use_p, stmt, iter)
2191    {
2192      pp_string (buffer, "#   ");
2193      dump_generic_node (buffer, DEF_FROM_PTR (def_p),
2194                         spc + 2, flags, false);
2195      pp_string (buffer, " = V_MAY_DEF <");
2196      dump_generic_node (buffer, USE_FROM_PTR (use_p),
2197                         spc + 2, flags, false);
2198      pp_string (buffer, ">;");
2199      newline_and_indent (buffer, spc);
2200    }
2201
2202  FOR_EACH_SSA_MUSTDEF_OPERAND (def_p, kill_p, stmt, iter)
2203    {
2204      pp_string (buffer, "#   ");
2205      dump_generic_node (buffer, DEF_FROM_PTR (def_p),
2206                         spc + 2, flags, false);
2207      pp_string (buffer, " = V_MUST_DEF <");
2208      dump_generic_node (buffer, USE_FROM_PTR (kill_p),
2209                         spc + 2, flags, false);
2210      pp_string (buffer, ">;");
2211      newline_and_indent (buffer, spc);
2212    }
2213
2214  FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_VUSE)
2215    {
2216      pp_string (buffer, "#   VUSE <");
2217      dump_generic_node (buffer, use, spc + 2, flags, false);
2218      pp_string (buffer, ">;");
2219      newline_and_indent (buffer, spc);
2220    }
2221}
2222
2223/* Dumps basic block BB to FILE with details described by FLAGS and
2224   indented by INDENT spaces.  */
2225
2226void
2227dump_generic_bb (FILE *file, basic_block bb, int indent, int flags)
2228{
2229  maybe_init_pretty_print (file);
2230  dumping_stmts = true;
2231  dump_generic_bb_buff (&buffer, bb, indent, flags);
2232  pp_flush (&buffer);
2233}
2234
2235/* Dumps header of basic block BB to buffer BUFFER indented by INDENT
2236   spaces and details described by flags.  */
2237
2238static void
2239dump_bb_header (pretty_printer *buffer, basic_block bb, int indent, int flags)
2240{
2241  edge e;
2242  tree stmt;
2243  edge_iterator ei;
2244
2245  if (flags & TDF_BLOCKS)
2246    {
2247      INDENT (indent);
2248      pp_string (buffer, "# BLOCK ");
2249      pp_decimal_int (buffer, bb->index);
2250      if (bb->frequency)
2251	{
2252          pp_string (buffer, " freq:");
2253          pp_decimal_int (buffer, bb->frequency);
2254	}
2255      if (bb->count)
2256	{
2257          pp_string (buffer, " count:");
2258          pp_widest_integer (buffer, bb->count);
2259	}
2260
2261      if (flags & TDF_LINENO)
2262	{
2263	  block_stmt_iterator bsi;
2264
2265	  for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
2266	    if (get_lineno (bsi_stmt (bsi)) != -1)
2267	      {
2268		pp_string (buffer, ", starting at line ");
2269		pp_decimal_int (buffer, get_lineno (bsi_stmt (bsi)));
2270		break;
2271	      }
2272	}
2273      newline_and_indent (buffer, indent);
2274
2275      pp_string (buffer, "# PRED:");
2276      pp_write_text_to_stream (buffer);
2277      FOR_EACH_EDGE (e, ei, bb->preds)
2278	if (flags & TDF_SLIM)
2279	  {
2280	    pp_string (buffer, " ");
2281	    if (e->src == ENTRY_BLOCK_PTR)
2282	      pp_string (buffer, "ENTRY");
2283	    else
2284	      pp_decimal_int (buffer, e->src->index);
2285	  }
2286	else
2287	  dump_edge_info (buffer->buffer->stream, e, 0);
2288      pp_newline (buffer);
2289    }
2290  else
2291    {
2292      stmt = first_stmt (bb);
2293      if (!stmt || TREE_CODE (stmt) != LABEL_EXPR)
2294	{
2295	  INDENT (indent - 2);
2296	  pp_string (buffer, "<bb ");
2297	  pp_decimal_int (buffer, bb->index);
2298	  pp_string (buffer, ">:");
2299	  pp_newline (buffer);
2300	}
2301    }
2302  pp_write_text_to_stream (buffer);
2303  check_bb_profile (bb, buffer->buffer->stream);
2304}
2305
2306/* Dumps end of basic block BB to buffer BUFFER indented by INDENT
2307   spaces.  */
2308
2309static void
2310dump_bb_end (pretty_printer *buffer, basic_block bb, int indent, int flags)
2311{
2312  edge e;
2313  edge_iterator ei;
2314
2315  INDENT (indent);
2316  pp_string (buffer, "# SUCC:");
2317  pp_write_text_to_stream (buffer);
2318  FOR_EACH_EDGE (e, ei, bb->succs)
2319    if (flags & TDF_SLIM)
2320      {
2321	pp_string (buffer, " ");
2322	if (e->dest == EXIT_BLOCK_PTR)
2323	  pp_string (buffer, "EXIT");
2324	else
2325	  pp_decimal_int (buffer, e->dest->index);
2326      }
2327    else
2328      dump_edge_info (buffer->buffer->stream, e, 1);
2329  pp_newline (buffer);
2330}
2331
2332/* Dumps phi nodes of basic block BB to buffer BUFFER with details described by
2333   FLAGS indented by INDENT spaces.  */
2334
2335static void
2336dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags)
2337{
2338  tree phi = phi_nodes (bb);
2339  if (!phi)
2340    return;
2341
2342  for (; phi; phi = PHI_CHAIN (phi))
2343    {
2344      if (is_gimple_reg (PHI_RESULT (phi)) || (flags & TDF_VOPS))
2345        {
2346          INDENT (indent);
2347          pp_string (buffer, "# ");
2348          dump_generic_node (buffer, phi, indent, flags, false);
2349          pp_newline (buffer);
2350        }
2351    }
2352}
2353
2354/* Dump jump to basic block BB that is represented implicitly in the cfg
2355   to BUFFER.  */
2356
2357static void
2358pp_cfg_jump (pretty_printer *buffer, basic_block bb)
2359{
2360  tree stmt;
2361
2362  stmt = first_stmt (bb);
2363
2364  pp_string (buffer, "goto <bb ");
2365  pp_decimal_int (buffer, bb->index);
2366  pp_string (buffer, ">");
2367  if (stmt && TREE_CODE (stmt) == LABEL_EXPR)
2368    {
2369      pp_string (buffer, " (");
2370      dump_generic_node (buffer, LABEL_EXPR_LABEL (stmt), 0, 0, false);
2371      pp_string (buffer, ")");
2372    }
2373  pp_semicolon (buffer);
2374}
2375
2376/* Dump edges represented implicitly in basic block BB to BUFFER, indented
2377   by INDENT spaces, with details given by FLAGS.  */
2378
2379static void
2380dump_implicit_edges (pretty_printer *buffer, basic_block bb, int indent,
2381		     int flags)
2382{
2383  edge e;
2384  edge_iterator ei;
2385
2386  /* If there is a fallthru edge, we may need to add an artificial goto to the
2387     dump.  */
2388  FOR_EACH_EDGE (e, ei, bb->succs)
2389    if (e->flags & EDGE_FALLTHRU)
2390      break;
2391  if (e && e->dest != bb->next_bb)
2392    {
2393      INDENT (indent);
2394
2395      if ((flags & TDF_LINENO)
2396#ifdef USE_MAPPED_LOCATION
2397	  && e->goto_locus != UNKNOWN_LOCATION
2398#else
2399	  && e->goto_locus
2400#endif
2401	  )
2402	{
2403	  expanded_location goto_xloc;
2404#ifdef USE_MAPPED_LOCATION
2405	  goto_xloc = expand_location (e->goto_locus);
2406#else
2407	  goto_xloc = *e->goto_locus;
2408#endif
2409	  pp_character (buffer, '[');
2410	  if (goto_xloc.file)
2411	    {
2412	      pp_string (buffer, goto_xloc.file);
2413	      pp_string (buffer, " : ");
2414	    }
2415	  pp_decimal_int (buffer, goto_xloc.line);
2416	  pp_string (buffer, "] ");
2417	}
2418
2419      pp_cfg_jump (buffer, e->dest);
2420      pp_newline (buffer);
2421    }
2422}
2423
2424/* Dumps basic block BB to buffer BUFFER with details described by FLAGS and
2425   indented by INDENT spaces.  */
2426
2427static void
2428dump_generic_bb_buff (pretty_printer *buffer, basic_block bb,
2429		      int indent, int flags)
2430{
2431  block_stmt_iterator bsi;
2432  tree stmt;
2433  int label_indent = indent - 2;
2434
2435  if (label_indent < 0)
2436    label_indent = 0;
2437
2438  dump_bb_header (buffer, bb, indent, flags);
2439
2440  dump_phi_nodes (buffer, bb, indent, flags);
2441
2442  for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
2443    {
2444      int curr_indent;
2445
2446      stmt = bsi_stmt (bsi);
2447
2448      curr_indent = TREE_CODE (stmt) == LABEL_EXPR ? label_indent : indent;
2449
2450      INDENT (curr_indent);
2451      dump_generic_node (buffer, stmt, curr_indent, flags, true);
2452      pp_newline (buffer);
2453    }
2454
2455  dump_implicit_edges (buffer, bb, indent, flags);
2456
2457  if (flags & TDF_BLOCKS)
2458    dump_bb_end (buffer, bb, indent, flags);
2459}
2460