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