OSDN Git Service

2004-09-24 Ben Elliston <bje@au.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     case VEC_COND_EXPR:
1474       pp_string (buffer, " VEC_COND_EXPR < ");
1475       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1476       pp_string (buffer, " , ");
1477       dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
1478       pp_string (buffer, " , ");
1479       dump_generic_node (buffer, TREE_OPERAND (node, 2), spc, flags, false);
1480       pp_string (buffer, " > ");
1481       break;
1482
1483     default:
1484       NIY;
1485     }
1486
1487   if (is_stmt && is_expr)
1488     pp_semicolon (buffer);
1489   pp_write_text_to_stream (buffer);
1490
1491   return spc;
1492 }
1493
1494 /* Print the declaration of a variable.  */
1495
1496 static void
1497 print_declaration (pretty_printer *buffer, tree t, int spc, int flags)
1498 {
1499   INDENT (spc);
1500
1501   if (TREE_CODE (t) == TYPE_DECL)
1502     pp_string (buffer, "typedef ");
1503
1504   if (DECL_REGISTER (t))
1505     pp_string (buffer, "register ");
1506
1507   if (TREE_PUBLIC (t) && DECL_EXTERNAL (t))
1508     pp_string (buffer, "extern ");
1509   else if (TREE_STATIC (t))
1510     pp_string (buffer, "static ");
1511
1512   /* Print the type and name.  */
1513   if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
1514     {
1515       tree tmp;
1516
1517       /* Print array's type.  */
1518       tmp = TREE_TYPE (t);
1519       while (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
1520         tmp = TREE_TYPE (tmp);
1521       dump_generic_node (buffer, TREE_TYPE (tmp), spc, flags, false);
1522
1523       /* Print variable's name.  */
1524       pp_space (buffer);
1525       dump_generic_node (buffer, t, spc, flags, false);
1526
1527       /* Print the dimensions.  */
1528       tmp = TREE_TYPE (t);
1529       while (TREE_CODE (tmp) == ARRAY_TYPE)
1530         {
1531           pp_character (buffer, '[');
1532           if (TYPE_DOMAIN (tmp))
1533             {
1534               if (TREE_CODE (TYPE_SIZE (tmp)) == INTEGER_CST)
1535                 pp_wide_integer (buffer,
1536                                 TREE_INT_CST_LOW (TYPE_SIZE (tmp)) /
1537                                 TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tmp))));
1538               else
1539                 dump_generic_node (buffer, TYPE_SIZE_UNIT (tmp), spc, flags,
1540                                    false);
1541             }
1542           pp_character (buffer, ']');
1543           tmp = TREE_TYPE (tmp);
1544         }
1545     }
1546   else if (TREE_CODE (t) == FUNCTION_DECL)
1547     {
1548       dump_generic_node (buffer, TREE_TYPE (TREE_TYPE (t)), spc, flags, false);
1549       pp_space (buffer);
1550       dump_decl_name (buffer, t, flags);
1551       dump_function_declaration (buffer, TREE_TYPE (t), spc, flags);
1552     }
1553   else
1554     {
1555       /* Print type declaration.  */
1556       dump_generic_node (buffer, TREE_TYPE (t), spc, flags, false);
1557
1558       /* Print variable's name.  */
1559       pp_space (buffer);
1560       dump_generic_node (buffer, t, spc, flags, false);
1561     }
1562
1563   /* The initial value of a function serves to determine wether the function
1564      is declared or defined.  So the following does not apply to function
1565      nodes.  */
1566   if (TREE_CODE (t) != FUNCTION_DECL)
1567     {
1568       /* Print the initial value.  */
1569       if (DECL_INITIAL (t))
1570         {
1571           pp_space (buffer);
1572           pp_character (buffer, '=');
1573           pp_space (buffer);
1574           dump_generic_node (buffer, DECL_INITIAL (t), spc, flags, false);
1575         }
1576     }
1577
1578   pp_character (buffer, ';');
1579 }
1580
1581
1582 /* Prints a structure: name, fields, and methods.
1583    FIXME: Still incomplete.  */
1584
1585 static void
1586 print_struct_decl (pretty_printer *buffer, tree node, int spc, int flags)
1587 {
1588   /* Print the name of the structure.  */
1589   if (TYPE_NAME (node))
1590     {
1591       INDENT (spc);
1592       if (TREE_CODE (node) == RECORD_TYPE)
1593         pp_string (buffer, "struct ");
1594       else if ((TREE_CODE (node) == UNION_TYPE
1595                 || TREE_CODE (node) == QUAL_UNION_TYPE))
1596         pp_string (buffer, "union ");
1597
1598       dump_generic_node (buffer, TYPE_NAME (node), spc, 0, false);
1599     }
1600
1601   /* Print the contents of the structure.  */
1602   pp_newline (buffer);
1603   INDENT (spc);
1604   pp_character (buffer, '{');
1605   pp_newline (buffer);
1606
1607   /* Print the fields of the structure.  */
1608   {
1609     tree tmp;
1610     tmp = TYPE_FIELDS (node);
1611     while (tmp)
1612       {
1613         /* Avoid to print recursively the structure.  */
1614         /* FIXME : Not implemented correctly...,
1615            what about the case when we have a cycle in the contain graph? ...
1616            Maybe this could be solved by looking at the scope in which the
1617            structure was declared.  */
1618         if (TREE_TYPE (tmp) != node
1619             || (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE
1620                 && TREE_TYPE (TREE_TYPE (tmp)) != node))
1621           {
1622             print_declaration (buffer, tmp, spc+2, flags);
1623             pp_newline (buffer);
1624           }
1625         tmp = TREE_CHAIN (tmp);
1626       }
1627   }
1628   INDENT (spc);
1629   pp_character (buffer, '}');
1630 }
1631
1632 /* Return the priority of the operator OP.
1633
1634    From lowest to highest precedence with either left-to-right (L-R)
1635    or right-to-left (R-L) associativity]:
1636
1637      1  [L-R] ,
1638      2  [R-L] = += -= *= /= %= &= ^= |= <<= >>=
1639      3  [R-L] ?:
1640      4  [L-R] ||
1641      5  [L-R] &&
1642      6  [L-R] |
1643      7  [L-R] ^
1644      8  [L-R] &
1645      9  [L-R] == !=
1646     10  [L-R] < <= > >=
1647     11  [L-R] << >>
1648     12  [L-R] + -
1649     13  [L-R] * / %
1650     14  [R-L] ! ~ ++ -- + - * & (type) sizeof
1651     15  [L-R] fn() [] -> .
1652
1653    unary +, - and * have higher precedence than the corresponding binary
1654    operators.  */
1655
1656 static int
1657 op_prio (tree op)
1658 {
1659   if (op == NULL)
1660     return 9999;
1661
1662   switch (TREE_CODE (op))
1663     {
1664     case TREE_LIST:
1665     case COMPOUND_EXPR:
1666     case BIND_EXPR:
1667       return 1;
1668
1669     case MODIFY_EXPR:
1670     case INIT_EXPR:
1671       return 2;
1672
1673     case COND_EXPR:
1674       return 3;
1675
1676     case TRUTH_OR_EXPR:
1677     case TRUTH_ORIF_EXPR:
1678       return 4;
1679
1680     case TRUTH_AND_EXPR:
1681     case TRUTH_ANDIF_EXPR:
1682       return 5;
1683
1684     case BIT_IOR_EXPR:
1685       return 6;
1686
1687     case BIT_XOR_EXPR:
1688     case TRUTH_XOR_EXPR:
1689       return 7;
1690
1691     case BIT_AND_EXPR:
1692       return 8;
1693
1694     case EQ_EXPR:
1695     case NE_EXPR:
1696       return 9;
1697
1698     case UNLT_EXPR:
1699     case UNLE_EXPR:
1700     case UNGT_EXPR:
1701     case UNGE_EXPR:
1702     case UNEQ_EXPR:
1703     case LTGT_EXPR:
1704     case ORDERED_EXPR:
1705     case UNORDERED_EXPR:
1706     case LT_EXPR:
1707     case LE_EXPR:
1708     case GT_EXPR:
1709     case GE_EXPR:
1710       return 10;
1711
1712     case LSHIFT_EXPR:
1713     case RSHIFT_EXPR:
1714     case LROTATE_EXPR:
1715     case RROTATE_EXPR:
1716       return 11;
1717
1718     case PLUS_EXPR:
1719     case MINUS_EXPR:
1720       return 12;
1721
1722     case MULT_EXPR:
1723     case TRUNC_DIV_EXPR:
1724     case CEIL_DIV_EXPR:
1725     case FLOOR_DIV_EXPR:
1726     case ROUND_DIV_EXPR:
1727     case RDIV_EXPR:
1728     case EXACT_DIV_EXPR:
1729     case TRUNC_MOD_EXPR:
1730     case CEIL_MOD_EXPR:
1731     case FLOOR_MOD_EXPR:
1732     case ROUND_MOD_EXPR:
1733       return 13;
1734
1735     case TRUTH_NOT_EXPR:
1736     case BIT_NOT_EXPR:
1737     case POSTINCREMENT_EXPR:
1738     case POSTDECREMENT_EXPR:
1739     case PREINCREMENT_EXPR:
1740     case PREDECREMENT_EXPR:
1741     case NEGATE_EXPR:
1742     case ALIGN_INDIRECT_REF:
1743     case MISALIGNED_INDIRECT_REF:
1744     case INDIRECT_REF:
1745     case ADDR_EXPR:
1746     case FLOAT_EXPR:
1747     case NOP_EXPR:
1748     case CONVERT_EXPR:
1749     case FIX_TRUNC_EXPR:
1750     case FIX_CEIL_EXPR:
1751     case FIX_FLOOR_EXPR:
1752     case FIX_ROUND_EXPR:
1753     case TARGET_EXPR:
1754       return 14;
1755
1756     case CALL_EXPR:
1757     case ARRAY_REF:
1758     case ARRAY_RANGE_REF:
1759     case COMPONENT_REF:
1760       return 15;
1761
1762       /* Special expressions.  */
1763     case MIN_EXPR:
1764     case MAX_EXPR:
1765     case ABS_EXPR:
1766     case REALPART_EXPR:
1767     case IMAGPART_EXPR:
1768       return 16;
1769
1770     case SAVE_EXPR:
1771     case NON_LVALUE_EXPR:
1772       return op_prio (TREE_OPERAND (op, 0));
1773
1774     default:
1775       /* Return an arbitrarily high precedence to avoid surrounding single
1776          VAR_DECLs in ()s.  */
1777       return 9999;
1778     }
1779 }
1780
1781
1782 /* Return the symbol associated with operator OP.  */
1783
1784 static const char *
1785 op_symbol (tree op)
1786 {
1787   gcc_assert (op);
1788
1789   switch (TREE_CODE (op))
1790     {
1791     case MODIFY_EXPR:
1792       return "=";
1793
1794     case TRUTH_OR_EXPR:
1795     case TRUTH_ORIF_EXPR:
1796       return "||";
1797
1798     case TRUTH_AND_EXPR:
1799     case TRUTH_ANDIF_EXPR:
1800       return "&&";
1801
1802     case BIT_IOR_EXPR:
1803       return "|";
1804
1805     case TRUTH_XOR_EXPR:
1806     case BIT_XOR_EXPR:
1807       return "^";
1808
1809     case ADDR_EXPR:
1810     case BIT_AND_EXPR:
1811       return "&";
1812
1813     case ORDERED_EXPR:
1814       return "ord";
1815     case UNORDERED_EXPR:
1816       return "unord";
1817
1818     case EQ_EXPR:
1819       return "==";
1820     case UNEQ_EXPR:
1821       return "u==";
1822
1823     case NE_EXPR:
1824       return "!=";
1825
1826     case LT_EXPR:
1827       return "<";
1828     case UNLT_EXPR:
1829       return "u<";
1830
1831     case LE_EXPR:
1832       return "<=";
1833     case UNLE_EXPR:
1834       return "u<=";
1835
1836     case GT_EXPR:
1837       return ">";
1838     case UNGT_EXPR:
1839       return "u>";
1840
1841     case GE_EXPR:
1842       return ">=";
1843     case UNGE_EXPR:
1844       return "u>=";
1845
1846     case LTGT_EXPR:
1847       return "<>";
1848
1849     case LSHIFT_EXPR:
1850       return "<<";
1851
1852     case RSHIFT_EXPR:
1853       return ">>";
1854
1855     case PLUS_EXPR:
1856       return "+";
1857
1858     case NEGATE_EXPR:
1859     case MINUS_EXPR:
1860       return "-";
1861
1862     case BIT_NOT_EXPR:
1863       return "~";
1864
1865     case TRUTH_NOT_EXPR:
1866       return "!";
1867
1868     case MULT_EXPR:
1869     case INDIRECT_REF:
1870       return "*";
1871
1872     case ALIGN_INDIRECT_REF:
1873       return "A*";
1874
1875     case MISALIGNED_INDIRECT_REF:
1876       return "M*";
1877
1878     case TRUNC_DIV_EXPR:
1879     case RDIV_EXPR:
1880       return "/";
1881
1882     case CEIL_DIV_EXPR:
1883       return "/[cl]";
1884
1885     case FLOOR_DIV_EXPR:
1886       return "/[fl]";
1887
1888     case ROUND_DIV_EXPR:
1889       return "/[rd]";
1890
1891     case EXACT_DIV_EXPR:
1892       return "/[ex]";
1893
1894     case TRUNC_MOD_EXPR:
1895       return "%";
1896
1897     case CEIL_MOD_EXPR:
1898       return "%[cl]";
1899
1900     case FLOOR_MOD_EXPR:
1901       return "%[fl]";
1902
1903     case ROUND_MOD_EXPR:
1904       return "%[rd]";
1905
1906     case PREDECREMENT_EXPR:
1907       return " --";
1908
1909     case PREINCREMENT_EXPR:
1910       return " ++";
1911
1912     case POSTDECREMENT_EXPR:
1913       return "-- ";
1914
1915     case POSTINCREMENT_EXPR:
1916       return "++ ";
1917
1918     default:
1919       return "<<< ??? >>>";
1920     }
1921 }
1922
1923 /* Prints the name of a CALL_EXPR.  */
1924
1925 static void
1926 print_call_name (pretty_printer *buffer, tree node)
1927 {
1928   tree op0;
1929
1930   gcc_assert (TREE_CODE (node) == CALL_EXPR);
1931
1932   op0 = TREE_OPERAND (node, 0);
1933
1934   if (TREE_CODE (op0) == NON_LVALUE_EXPR)
1935     op0 = TREE_OPERAND (op0, 0);
1936
1937   switch (TREE_CODE (op0))
1938     {
1939     case VAR_DECL:
1940     case PARM_DECL:
1941       dump_function_name (buffer, op0);
1942       break;
1943
1944     case ADDR_EXPR:
1945     case INDIRECT_REF:
1946     case NOP_EXPR:
1947       dump_generic_node (buffer, TREE_OPERAND (op0, 0), 0, 0, false);
1948       break;
1949
1950     case COND_EXPR:
1951       pp_string (buffer, "(");
1952       dump_generic_node (buffer, TREE_OPERAND (op0, 0), 0, 0, false);
1953       pp_string (buffer, ") ? ");
1954       dump_generic_node (buffer, TREE_OPERAND (op0, 1), 0, 0, false);
1955       pp_string (buffer, " : ");
1956       dump_generic_node (buffer, TREE_OPERAND (op0, 2), 0, 0, false);
1957       break;
1958
1959     case COMPONENT_REF:
1960       /* The function is a pointer contained in a structure.  */
1961       if (TREE_CODE (TREE_OPERAND (op0, 0)) == INDIRECT_REF ||
1962           TREE_CODE (TREE_OPERAND (op0, 0)) == VAR_DECL)
1963         dump_function_name (buffer, TREE_OPERAND (op0, 1));
1964       else
1965         dump_generic_node (buffer, TREE_OPERAND (op0, 0), 0, 0, false);
1966       /* else
1967          We can have several levels of structures and a function
1968          pointer inside.  This is not implemented yet...  */
1969       /*                  NIY;*/
1970       break;
1971
1972     case ARRAY_REF:
1973       if (TREE_CODE (TREE_OPERAND (op0, 0)) == VAR_DECL)
1974         dump_function_name (buffer, TREE_OPERAND (op0, 0));
1975       else
1976         dump_generic_node (buffer, op0, 0, 0, false);
1977       break;
1978
1979     case SSA_NAME:
1980     case OBJ_TYPE_REF:
1981       dump_generic_node (buffer, op0, 0, 0, false);
1982       break;
1983
1984     default:
1985       NIY;
1986     }
1987 }
1988
1989 /* Parses the string STR and replaces new-lines by '\n', tabs by '\t', ...  */
1990
1991 static void
1992 pretty_print_string (pretty_printer *buffer, const char *str)
1993 {
1994   if (str == NULL)
1995     return;
1996
1997   while (*str)
1998     {
1999       switch (str[0])
2000         {
2001         case '\b':
2002           pp_string (buffer, "\\b");
2003           break;
2004
2005         case '\f':
2006           pp_string (buffer, "\\f");
2007           break;
2008
2009         case '\n':
2010           pp_string (buffer, "\\n");
2011           break;
2012
2013         case '\r':
2014           pp_string (buffer, "\\r");
2015           break;
2016
2017         case '\t':
2018           pp_string (buffer, "\\t");
2019           break;
2020
2021         case '\v':
2022           pp_string (buffer, "\\v");
2023           break;
2024
2025         case '\\':
2026           pp_string (buffer, "\\\\");
2027           break;
2028
2029         case '\"':
2030           pp_string (buffer, "\\\"");
2031           break;
2032
2033         case '\'':
2034           pp_string (buffer, "\\'");
2035           break;
2036
2037         case '\0':
2038           pp_string (buffer, "\\0");
2039           break;
2040
2041         case '\1':
2042           pp_string (buffer, "\\1");
2043           break;
2044
2045         case '\2':
2046           pp_string (buffer, "\\2");
2047           break;
2048
2049         case '\3':
2050           pp_string (buffer, "\\3");
2051           break;
2052
2053         case '\4':
2054           pp_string (buffer, "\\4");
2055           break;
2056
2057         case '\5':
2058           pp_string (buffer, "\\5");
2059           break;
2060
2061         case '\6':
2062           pp_string (buffer, "\\6");
2063           break;
2064
2065         case '\7':
2066           pp_string (buffer, "\\7");
2067           break;
2068
2069         default:
2070           pp_character (buffer, str[0]);
2071           break;
2072         }
2073       str++;
2074     }
2075 }
2076
2077 static void
2078 maybe_init_pretty_print (FILE *file)
2079 {
2080   if (!initialized)
2081     {
2082       pp_construct (&buffer, /* prefix */NULL, /* line-width */0);
2083       pp_needs_newline (&buffer) = true;
2084       initialized = 1;
2085     }
2086
2087   buffer.buffer->stream = file;
2088 }
2089
2090 static void
2091 newline_and_indent (pretty_printer *buffer, int spc)
2092 {
2093   pp_newline (buffer);
2094   INDENT (spc);
2095 }
2096
2097 static void
2098 dump_vops (pretty_printer *buffer, tree stmt, int spc, int flags)
2099 {
2100   tree use, def;
2101   use_operand_p use_p;
2102   def_operand_p def_p;
2103   ssa_op_iter iter;
2104
2105   FOR_EACH_SSA_MAYDEF_OPERAND (def_p, use_p, stmt, iter)
2106     {
2107       pp_string (buffer, "#   ");
2108       dump_generic_node (buffer, DEF_FROM_PTR (def_p),
2109                          spc + 2, flags, false);
2110       pp_string (buffer, " = V_MAY_DEF <");
2111       dump_generic_node (buffer, USE_FROM_PTR (use_p),
2112                          spc + 2, flags, false);
2113       pp_string (buffer, ">;");
2114       newline_and_indent (buffer, spc);
2115     }
2116
2117   FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_VMUSTDEF)
2118     {
2119       pp_string (buffer, "#   V_MUST_DEF <");
2120       dump_generic_node (buffer, def, spc + 2, flags, false);
2121       pp_string (buffer, ">;");
2122       newline_and_indent (buffer, spc);
2123     }
2124
2125   FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_VUSE)
2126     {
2127       pp_string (buffer, "#   VUSE <");
2128       dump_generic_node (buffer, use, spc + 2, flags, false);
2129       pp_string (buffer, ">;");
2130       newline_and_indent (buffer, spc);
2131     }
2132 }
2133
2134 /* Dumps basic block BB to FILE with details described by FLAGS and
2135    indented by INDENT spaces.  */
2136
2137 void
2138 dump_generic_bb (FILE *file, basic_block bb, int indent, int flags)
2139 {
2140   maybe_init_pretty_print (file);
2141   dumping_stmts = true;
2142   dump_generic_bb_buff (&buffer, bb, indent, flags);
2143   pp_flush (&buffer);
2144 }
2145
2146 /* Dumps header of basic block BB to buffer BUFFER indented by INDENT
2147    spaces and details described by flags.  */
2148
2149 static void
2150 dump_bb_header (pretty_printer *buffer, basic_block bb, int indent, int flags)
2151 {
2152   edge e;
2153   tree stmt;
2154   edge_iterator ei;
2155
2156   if (flags & TDF_BLOCKS)
2157     {
2158       INDENT (indent);
2159       pp_string (buffer, "# BLOCK ");
2160       pp_decimal_int (buffer, bb->index);
2161
2162       if (flags & TDF_LINENO)
2163         {
2164           block_stmt_iterator bsi;
2165
2166           for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
2167             if (get_lineno (bsi_stmt (bsi)) != -1)
2168               {
2169                 pp_string (buffer, ", starting at line ");
2170                 pp_decimal_int (buffer, get_lineno (bsi_stmt (bsi)));
2171                 break;
2172               }
2173         }
2174       newline_and_indent (buffer, indent);
2175
2176       pp_string (buffer, "# PRED:");
2177       pp_write_text_to_stream (buffer);
2178       FOR_EACH_EDGE (e, ei, bb->preds)
2179         if (flags & TDF_SLIM)
2180           {
2181             pp_string (buffer, " ");
2182             if (e->src == ENTRY_BLOCK_PTR)
2183               pp_string (buffer, "ENTRY");
2184             else
2185               pp_decimal_int (buffer, e->src->index);
2186           }
2187         else
2188           dump_edge_info (buffer->buffer->stream, e, 0);
2189       pp_newline (buffer);
2190     }
2191   else
2192     {
2193       stmt = first_stmt (bb);
2194       if (!stmt || TREE_CODE (stmt) != LABEL_EXPR)
2195         {
2196           INDENT (indent - 2);
2197           pp_string (buffer, "<bb ");
2198           pp_decimal_int (buffer, bb->index);
2199           pp_string (buffer, ">:");
2200           pp_newline (buffer);
2201         }
2202     }
2203   pp_write_text_to_stream (buffer);
2204   check_bb_profile (bb, buffer->buffer->stream);
2205 }
2206
2207 /* Dumps end of basic block BB to buffer BUFFER indented by INDENT
2208    spaces.  */
2209
2210 static void
2211 dump_bb_end (pretty_printer *buffer, basic_block bb, int indent, int flags)
2212 {
2213   edge e;
2214   edge_iterator ei;
2215
2216   INDENT (indent);
2217   pp_string (buffer, "# SUCC:");
2218   pp_write_text_to_stream (buffer);
2219   FOR_EACH_EDGE (e, ei, bb->succs)
2220     if (flags & TDF_SLIM)
2221       {
2222         pp_string (buffer, " ");
2223         if (e->dest == EXIT_BLOCK_PTR)
2224           pp_string (buffer, "EXIT");
2225         else
2226           pp_decimal_int (buffer, e->dest->index);
2227       }
2228     else
2229       dump_edge_info (buffer->buffer->stream, e, 1);
2230   pp_newline (buffer);
2231 }
2232
2233 /* Dumps phi nodes of basic block BB to buffer BUFFER with details described by
2234    FLAGS indented by INDENT spaces.  */
2235
2236 static void
2237 dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags)
2238 {
2239   tree phi = phi_nodes (bb);
2240   if (!phi)
2241     return;
2242
2243   for (; phi; phi = PHI_CHAIN (phi))
2244     {
2245       if (is_gimple_reg (PHI_RESULT (phi)) || (flags & TDF_VOPS))
2246         {
2247           INDENT (indent);
2248           pp_string (buffer, "# ");
2249           dump_generic_node (buffer, phi, indent, flags, false);
2250           pp_newline (buffer);
2251         }
2252     }
2253 }
2254
2255 /* Dump jump to basic block BB that is represented implicitly in the cfg
2256    to BUFFER.  */
2257
2258 static void
2259 pp_cfg_jump (pretty_printer *buffer, basic_block bb)
2260 {
2261   tree stmt;
2262
2263   stmt = first_stmt (bb);
2264
2265   pp_string (buffer, "goto <bb ");
2266   pp_decimal_int (buffer, bb->index);
2267   pp_string (buffer, ">");
2268   if (stmt && TREE_CODE (stmt) == LABEL_EXPR)
2269     {
2270       pp_string (buffer, " (");
2271       dump_generic_node (buffer, LABEL_EXPR_LABEL (stmt), 0, 0, false);
2272       pp_string (buffer, ")");
2273     }
2274   pp_semicolon (buffer);
2275 }
2276
2277 /* Dump edges represented implicitly in basic block BB to BUFFER, indented
2278    by INDENT spaces, with details given by FLAGS.  */
2279
2280 static void
2281 dump_implicit_edges (pretty_printer *buffer, basic_block bb, int indent,
2282                      int flags)
2283 {
2284   edge e;
2285   edge_iterator ei;
2286
2287   /* If there is a fallthru edge, we may need to add an artificial goto to the
2288      dump.  */
2289   FOR_EACH_EDGE (e, ei, bb->succs)
2290     if (e->flags & EDGE_FALLTHRU)
2291       break;
2292   if (e && e->dest != bb->next_bb)
2293     {
2294       INDENT (indent);
2295
2296       if ((flags & TDF_LINENO)
2297 #ifdef USE_MAPPED_LOCATION
2298           && e->goto_locus != UNKNOWN_LOCATION
2299 #else
2300           && e->goto_locus
2301 #endif
2302           )
2303         {
2304           expanded_location goto_xloc;
2305 #ifdef USE_MAPPED_LOCATION
2306           goto_xloc = expand_location (e->goto_locus);
2307 #else
2308           goto_xloc = *e->goto_locus;
2309 #endif
2310           pp_character (buffer, '[');
2311           if (goto_xloc.file)
2312             {
2313               pp_string (buffer, goto_xloc.file);
2314               pp_string (buffer, " : ");
2315             }
2316           pp_decimal_int (buffer, goto_xloc.line);
2317           pp_string (buffer, "] ");
2318         }
2319
2320       pp_cfg_jump (buffer, e->dest);
2321       pp_newline (buffer);
2322     }
2323 }
2324
2325 /* Dumps basic block BB to buffer BUFFER with details described by FLAGS and
2326    indented by INDENT spaces.  */
2327
2328 static void
2329 dump_generic_bb_buff (pretty_printer *buffer, basic_block bb,
2330                       int indent, int flags)
2331 {
2332   block_stmt_iterator bsi;
2333   tree stmt;
2334   int label_indent = indent - 2;
2335
2336   if (label_indent < 0)
2337     label_indent = 0;
2338
2339   dump_bb_header (buffer, bb, indent, flags);
2340
2341   if (bb_ann (bb))
2342     dump_phi_nodes (buffer, bb, indent, flags);
2343
2344   for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
2345     {
2346       int curr_indent;
2347
2348       stmt = bsi_stmt (bsi);
2349
2350       curr_indent = TREE_CODE (stmt) == LABEL_EXPR ? label_indent : indent;
2351
2352       INDENT (curr_indent);
2353       dump_generic_node (buffer, stmt, curr_indent, flags, true);
2354       pp_newline (buffer);
2355     }
2356
2357   dump_implicit_edges (buffer, bb, indent, flags);
2358
2359   if (flags & TDF_BLOCKS)
2360     dump_bb_end (buffer, bb, indent, flags);
2361 }