OSDN Git Service

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