OSDN Git Service

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