OSDN Git Service

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