OSDN Git Service

* config/m68k/m68k.c (notice_update_cc): Use SET_DEST and
[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 #include "tree-pass.h"
35
36 /* Local functions, macros and variables.  */
37 static int op_prio (tree);
38 static const char *op_symbol (tree);
39 static void pretty_print_string (pretty_printer *, const char*);
40 static void print_call_name (pretty_printer *, tree);
41 static void newline_and_indent (pretty_printer *, int);
42 static void maybe_init_pretty_print (FILE *);
43 static void print_declaration (pretty_printer *, tree, int, int);
44 static void print_struct_decl (pretty_printer *, tree, int, int);
45 static void do_niy (pretty_printer *, tree);
46 static void dump_vops (pretty_printer *, tree, int, int);
47 static 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
59 static pretty_printer buffer;
60 static int initialized = 0;
61 static bool dumping_stmts;
62
63 /* Try to print something for an unknown tree code.  */
64
65 static void
66 do_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
86 void
87 debug_generic_expr (tree t)
88 {
89   print_generic_expr (stderr, t, TDF_VOPS|TDF_UID);
90   fprintf (stderr, "\n");
91 }
92
93 void
94 debug_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.  */
101 void
102 print_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
113 void
114 print_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
126 void
127 print_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
143 void
144 print_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
154 static void
155 dump_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
177 static void
178 dump_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
189 static void
190 dump_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
222 static void
223 dump_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
254 int
255 dump_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
1566 static void
1567 print_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
1652 static void
1653 print_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
1723 static int
1724 op_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
1856 static const char *
1857 op_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
2006 static void
2007 print_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
2072 static void
2073 pretty_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
2158 static void
2159 maybe_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
2171 static void
2172 newline_and_indent (pretty_printer *buffer, int spc)
2173 {
2174   pp_newline (buffer);
2175   INDENT (spc);
2176 }
2177
2178 static void
2179 dump_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
2226 void
2227 dump_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
2238 static void
2239 dump_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
2309 static void
2310 dump_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
2335 static void
2336 dump_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
2357 static void
2358 pp_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
2379 static void
2380 dump_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
2427 static void
2428 dump_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 }