OSDN Git Service

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