OSDN Git Service

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