OSDN Git Service

optimize
[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 BUFFER_REF:
645       NIY;
646       break;
647
648     case ARRAY_REF:
649     case ARRAY_RANGE_REF:
650       op0 = TREE_OPERAND (node, 0);
651       if (op_prio (op0) < op_prio (node))
652         pp_character (buffer, '(');
653       dump_generic_node (buffer, op0, spc, flags, false);
654       if (op_prio (op0) < op_prio (node))
655         pp_character (buffer, ')');
656       pp_character (buffer, '[');
657       dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
658       if (TREE_CODE (node) == ARRAY_RANGE_REF)
659         pp_string (buffer, " ...");
660       pp_character (buffer, ']');
661
662       op0 = array_ref_low_bound (node);
663       op1 = array_ref_element_size (node);
664
665       if (!integer_zerop (op0)
666           || (TYPE_SIZE_UNIT (TREE_TYPE (node))
667               && !operand_equal_p (op1, TYPE_SIZE_UNIT (TREE_TYPE (node)), 0)))
668         {
669           pp_string (buffer, "{lb: ");
670           dump_generic_node (buffer, op0, spc, flags, false);
671           pp_string (buffer, " sz: ");
672           dump_generic_node (buffer, op1, spc, flags, false);
673           pp_character (buffer, '}');
674         }
675       break;
676
677     case CONSTRUCTOR:
678       {
679         tree lnode;
680         bool is_struct_init = FALSE;
681         pp_character (buffer, '{');
682         lnode = CONSTRUCTOR_ELTS (node);
683         if (TREE_CODE (TREE_TYPE (node)) == RECORD_TYPE
684             || TREE_CODE (TREE_TYPE (node)) == UNION_TYPE)
685           is_struct_init = TRUE;
686         while (lnode && lnode != error_mark_node)
687           {
688             tree val;
689             if (TREE_PURPOSE (lnode) && is_struct_init)
690               {
691                 pp_character (buffer, '.');
692                 dump_generic_node (buffer, TREE_PURPOSE (lnode), spc, flags, false);
693                 pp_string (buffer, "=");
694               }
695             val = TREE_VALUE (lnode);
696             if (val && TREE_CODE (val) == ADDR_EXPR)
697               if (TREE_CODE (TREE_OPERAND (val, 0)) == FUNCTION_DECL)
698                 val = TREE_OPERAND (val, 0);
699             if (val && TREE_CODE (val) == FUNCTION_DECL)
700               {
701                 dump_decl_name (buffer, val, flags);
702               }
703             else
704               {
705                 dump_generic_node (buffer, TREE_VALUE (lnode), spc, flags, false);
706               }
707             lnode = TREE_CHAIN (lnode);
708             if (lnode && TREE_CODE (lnode) == TREE_LIST)
709               {
710                 pp_character (buffer, ',');
711                 pp_space (buffer);
712               }
713           }
714         pp_character (buffer, '}');
715       }
716       break;
717
718     case COMPOUND_EXPR:
719       {
720         tree *tp;
721         if (flags & TDF_SLIM)
722           {
723             pp_string (buffer, "<COMPOUND_EXPR>");
724             break;
725           }
726
727         dump_generic_node (buffer, TREE_OPERAND (node, 0),
728                            spc, flags, dumping_stmts);
729         if (dumping_stmts)
730           newline_and_indent (buffer, spc);
731         else
732           {
733             pp_character (buffer, ',');
734             pp_space (buffer);
735           }
736
737         for (tp = &TREE_OPERAND (node, 1);
738              TREE_CODE (*tp) == COMPOUND_EXPR;
739              tp = &TREE_OPERAND (*tp, 1))
740           {
741             dump_generic_node (buffer, TREE_OPERAND (*tp, 0),
742                                spc, flags, dumping_stmts);
743             if (dumping_stmts)
744               newline_and_indent (buffer, spc);
745             else
746               {
747                 pp_character (buffer, ',');
748                 pp_space (buffer);
749               }
750           }
751
752         dump_generic_node (buffer, *tp, spc, flags, dumping_stmts);
753       }
754       break;
755
756     case STATEMENT_LIST:
757       {
758         tree_stmt_iterator si;
759         bool first = true;
760   
761         if ((flags & TDF_SLIM) || !dumping_stmts)
762           {
763             pp_string (buffer, "<STATEMENT_LIST>");
764             break;
765           }
766
767         for (si = tsi_start (node); !tsi_end_p (si); tsi_next (&si))
768           {
769             if (!first)
770               newline_and_indent (buffer, spc);
771             else
772               first = false;
773             dump_generic_node (buffer, tsi_stmt (si), spc, flags, true);
774           }
775       }
776       break;
777
778     case MODIFY_EXPR:
779     case INIT_EXPR:
780       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
781       pp_space (buffer);
782       pp_character (buffer, '=');
783       pp_space (buffer);
784       dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
785       break;
786
787     case TARGET_EXPR:
788       pp_string (buffer, "TARGET_EXPR <");
789       dump_generic_node (buffer, TARGET_EXPR_SLOT (node), spc, flags, false);
790       pp_character (buffer, ',');
791       pp_space (buffer);
792       dump_generic_node (buffer, TARGET_EXPR_INITIAL (node), spc, flags, false);
793       pp_character (buffer, '>');
794       break;
795
796     case DECL_EXPR:
797       print_declaration (buffer, DECL_EXPR_DECL (node), spc, flags);
798       is_stmt = false;
799       break;
800
801     case COND_EXPR:
802       if (TREE_TYPE (node) == NULL || TREE_TYPE (node) == void_type_node)
803         {
804           pp_string (buffer, "if (");
805           dump_generic_node (buffer, COND_EXPR_COND (node), spc, flags, false);
806           pp_character (buffer, ')');
807           /* The lowered cond_exprs should always be printed in full.  */
808           if (COND_EXPR_THEN (node)
809               && TREE_CODE (COND_EXPR_THEN (node)) == GOTO_EXPR
810               && COND_EXPR_ELSE (node)
811               && TREE_CODE (COND_EXPR_ELSE (node)) == GOTO_EXPR)
812             {
813               pp_space (buffer);
814               dump_generic_node (buffer, COND_EXPR_THEN (node), 0, flags, true);
815               pp_string (buffer, " else ");
816               dump_generic_node (buffer, COND_EXPR_ELSE (node), 0, flags, true);
817             }
818           else if (!(flags & TDF_SLIM))
819             {
820               /* Output COND_EXPR_THEN.  */
821               if (COND_EXPR_THEN (node))
822                 {
823                   newline_and_indent (buffer, spc+2);
824                   pp_character (buffer, '{');
825                   newline_and_indent (buffer, spc+4);
826                   dump_generic_node (buffer, COND_EXPR_THEN (node), spc+4,
827                                      flags, true);
828                   newline_and_indent (buffer, spc+2);
829                   pp_character (buffer, '}');
830                 }
831
832               /* Output COND_EXPR_ELSE.  */
833               if (COND_EXPR_ELSE (node))
834                 {
835                   newline_and_indent (buffer, spc);
836                   pp_string (buffer, "else");
837                   newline_and_indent (buffer, spc+2);
838                   pp_character (buffer, '{');
839                   newline_and_indent (buffer, spc+4);
840                   dump_generic_node (buffer, COND_EXPR_ELSE (node), spc+4,
841                                      flags, true);
842                   newline_and_indent (buffer, spc+2);
843                   pp_character (buffer, '}');
844                 }
845             }
846           is_expr = false;
847         }
848       else
849         {
850           dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
851           pp_space (buffer);
852           pp_character (buffer, '?');
853           pp_space (buffer);
854           dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
855           pp_space (buffer);
856           pp_character (buffer, ':');
857           pp_space (buffer);
858           dump_generic_node (buffer, TREE_OPERAND (node, 2), spc, flags, false);
859         }
860       break;
861
862     case BIND_EXPR:
863       pp_character (buffer, '{');
864       if (!(flags & TDF_SLIM))
865         {
866           if (BIND_EXPR_VARS (node))
867             {
868               pp_newline (buffer);
869
870               for (op0 = BIND_EXPR_VARS (node); op0; op0 = TREE_CHAIN (op0))
871                 {
872                   print_declaration (buffer, op0, spc+2, flags);
873                   pp_newline (buffer);
874                 }
875             }
876
877           newline_and_indent (buffer, spc+2);
878           dump_generic_node (buffer, BIND_EXPR_BODY (node), spc+2, flags, true);
879           newline_and_indent (buffer, spc);
880           pp_character (buffer, '}');
881         }
882       is_expr = false;
883       break;
884
885     case CALL_EXPR:
886       print_call_name (buffer, node);
887
888       /* Print parameters.  */
889       pp_space (buffer);
890       pp_character (buffer, '(');
891       op1 = TREE_OPERAND (node, 1);
892       if (op1)
893         dump_generic_node (buffer, op1, spc, flags, false);
894       pp_character (buffer, ')');
895
896       op1 = TREE_OPERAND (node, 2);
897       if (op1)
898         {
899           pp_string (buffer, " [static-chain: ");
900           dump_generic_node (buffer, op1, spc, flags, false);
901           pp_character (buffer, ']');
902         }
903
904       if (CALL_EXPR_TAILCALL (node))
905         pp_string (buffer, " [tail call]");
906       break;
907
908     case WITH_CLEANUP_EXPR:
909       NIY;
910       break;
911
912     case CLEANUP_POINT_EXPR:
913       pp_string (buffer, "<<cleanup_point ");
914       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
915       pp_string (buffer, ">>");
916       break;
917
918     case PLACEHOLDER_EXPR:
919       pp_string (buffer, "<PLACEHOLDER_EXPR ");
920       dump_generic_node (buffer, TREE_TYPE (node), spc, flags, false);
921       pp_character (buffer, '>');
922       break;
923
924       /* Binary arithmetic and logic expressions.  */
925     case MULT_EXPR:
926     case PLUS_EXPR:
927     case MINUS_EXPR:
928     case TRUNC_DIV_EXPR:
929     case CEIL_DIV_EXPR:
930     case FLOOR_DIV_EXPR:
931     case ROUND_DIV_EXPR:
932     case TRUNC_MOD_EXPR:
933     case CEIL_MOD_EXPR:
934     case FLOOR_MOD_EXPR:
935     case ROUND_MOD_EXPR:
936     case RDIV_EXPR:
937     case EXACT_DIV_EXPR:
938     case LSHIFT_EXPR:
939     case RSHIFT_EXPR:
940     case LROTATE_EXPR:
941     case RROTATE_EXPR:
942     case BIT_IOR_EXPR:
943     case BIT_XOR_EXPR:
944     case BIT_AND_EXPR:
945     case TRUTH_ANDIF_EXPR:
946     case TRUTH_ORIF_EXPR:
947     case TRUTH_AND_EXPR:
948     case TRUTH_OR_EXPR:
949     case TRUTH_XOR_EXPR:
950     case LT_EXPR:
951     case LE_EXPR:
952     case GT_EXPR:
953     case GE_EXPR:
954     case EQ_EXPR:
955     case NE_EXPR:
956     case UNLT_EXPR:
957     case UNLE_EXPR:
958     case UNGT_EXPR:
959     case UNGE_EXPR:
960     case UNEQ_EXPR:
961     case LTGT_EXPR:
962     case ORDERED_EXPR:
963     case UNORDERED_EXPR:
964       {
965         const char *op = op_symbol (node);
966         op0 = TREE_OPERAND (node, 0);
967         op1 = TREE_OPERAND (node, 1);
968
969         /* When the operands are expressions with less priority,
970            keep semantics of the tree representation.  */
971         if (op_prio (op0) < op_prio (node))
972           {
973             pp_character (buffer, '(');
974             dump_generic_node (buffer, op0, spc, flags, false);
975             pp_character (buffer, ')');
976           }
977         else
978           dump_generic_node (buffer, op0, spc, flags, false);
979
980         pp_space (buffer);
981         pp_string (buffer, op);
982         pp_space (buffer);
983
984         /* When the operands are expressions with less priority,
985            keep semantics of the tree representation.  */
986         if (op_prio (op1) < op_prio (node))
987           {
988             pp_character (buffer, '(');
989             dump_generic_node (buffer, op1, spc, flags, false);
990             pp_character (buffer, ')');
991           }
992         else
993           dump_generic_node (buffer, op1, spc, flags, false);
994       }
995       break;
996
997       /* Unary arithmetic and logic expressions.  */
998     case NEGATE_EXPR:
999     case BIT_NOT_EXPR:
1000     case TRUTH_NOT_EXPR:
1001     case ADDR_EXPR:
1002     case PREDECREMENT_EXPR:
1003     case PREINCREMENT_EXPR:
1004     case INDIRECT_REF:
1005       if (TREE_CODE (node) == ADDR_EXPR
1006           && (TREE_CODE (TREE_OPERAND (node, 0)) == STRING_CST
1007               || TREE_CODE (TREE_OPERAND (node, 0)) == FUNCTION_DECL))
1008         ;       /* Do not output '&' for strings and function pointers.  */
1009       else
1010         pp_string (buffer, op_symbol (node));
1011
1012       if (op_prio (TREE_OPERAND (node, 0)) < op_prio (node))
1013         {
1014           pp_character (buffer, '(');
1015           dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1016           pp_character (buffer, ')');
1017         }
1018       else
1019         dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1020       break;
1021
1022     case POSTDECREMENT_EXPR:
1023     case POSTINCREMENT_EXPR:
1024       if (op_prio (TREE_OPERAND (node, 0)) < op_prio (node))
1025         {
1026           pp_character (buffer, '(');
1027           dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1028           pp_character (buffer, ')');
1029         }
1030       else
1031         dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1032       pp_string (buffer, op_symbol (node));
1033       break;
1034
1035     case MIN_EXPR:
1036       pp_string (buffer, "MIN_EXPR <");
1037       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1038       pp_string (buffer, ", ");
1039       dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
1040       pp_character (buffer, '>');
1041       break;
1042
1043     case MAX_EXPR:
1044       pp_string (buffer, "MAX_EXPR <");
1045       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1046       pp_string (buffer, ", ");
1047       dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
1048       pp_character (buffer, '>');
1049       break;
1050
1051     case ABS_EXPR:
1052       pp_string (buffer, "ABS_EXPR <");
1053       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1054       pp_character (buffer, '>');
1055       break;
1056
1057     case IN_EXPR:
1058       NIY;
1059       break;
1060
1061     case SET_LE_EXPR:
1062       NIY;
1063       break;
1064
1065     case CARD_EXPR:
1066       NIY;
1067       break;
1068
1069     case RANGE_EXPR:
1070       NIY;
1071       break;
1072
1073     case FIX_TRUNC_EXPR:
1074     case FIX_CEIL_EXPR:
1075     case FIX_FLOOR_EXPR:
1076     case FIX_ROUND_EXPR:
1077     case FLOAT_EXPR:
1078     case CONVERT_EXPR:
1079     case NOP_EXPR:
1080       type = TREE_TYPE (node);
1081       op0 = TREE_OPERAND (node, 0);
1082       if (type != TREE_TYPE (op0))
1083         {
1084           pp_character (buffer, '(');
1085           dump_generic_node (buffer, type, spc, flags, false);
1086           pp_string (buffer, ")");
1087         }
1088       if (op_prio (op0) < op_prio (node))
1089         pp_character (buffer, '(');
1090       dump_generic_node (buffer, op0, spc, flags, false);
1091       if (op_prio (op0) < op_prio (node))
1092         pp_character (buffer, ')');
1093       break;
1094
1095     case VIEW_CONVERT_EXPR:
1096       pp_string (buffer, "VIEW_CONVERT_EXPR<");
1097       dump_generic_node (buffer, TREE_TYPE (node), spc, flags, false);
1098       pp_string (buffer, ">(");
1099       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1100       pp_character (buffer, ')');
1101       break;
1102
1103     case NON_LVALUE_EXPR:
1104       pp_string (buffer, "NON_LVALUE_EXPR <");
1105       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1106       pp_character (buffer, '>');
1107       break;
1108
1109     case SAVE_EXPR:
1110       pp_string (buffer, "SAVE_EXPR <");
1111       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1112       pp_character (buffer, '>');
1113       break;
1114
1115     case UNSAVE_EXPR:
1116       pp_string (buffer, "UNSAVE_EXPR <");
1117       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1118       pp_character (buffer, '>');
1119       break;
1120
1121     case ENTRY_VALUE_EXPR:
1122       NIY;
1123       break;
1124
1125     case COMPLEX_EXPR:
1126       pp_string (buffer, "COMPLEX_EXPR <");
1127       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1128       pp_string (buffer, ", ");
1129       dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
1130       pp_string (buffer, ">");
1131       break;
1132
1133     case CONJ_EXPR:
1134       pp_string (buffer, "CONJ_EXPR <");
1135       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1136       pp_string (buffer, ">");
1137       break;
1138
1139     case REALPART_EXPR:
1140       pp_string (buffer, "REALPART_EXPR <");
1141       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1142       pp_string (buffer, ">");
1143       break;
1144
1145     case IMAGPART_EXPR:
1146       pp_string (buffer, "IMAGPART_EXPR <");
1147       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1148       pp_string (buffer, ">");
1149       break;
1150
1151     case VA_ARG_EXPR:
1152       pp_string (buffer, "VA_ARG_EXPR <");
1153       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1154       pp_string (buffer, ">");
1155       break;
1156
1157     case TRY_FINALLY_EXPR:
1158     case TRY_CATCH_EXPR:
1159       pp_string (buffer, "try");
1160       newline_and_indent (buffer, spc+2);
1161       pp_string (buffer, "{");
1162       newline_and_indent (buffer, spc+4);
1163       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc+4, flags, true);
1164       newline_and_indent (buffer, spc+2);
1165       pp_string (buffer, "}");
1166       newline_and_indent (buffer, spc);
1167       pp_string (buffer,
1168                          (TREE_CODE (node) == TRY_CATCH_EXPR) ? "catch" : "finally");
1169       newline_and_indent (buffer, spc+2);
1170       pp_string (buffer, "{");
1171       newline_and_indent (buffer, spc+4);
1172       dump_generic_node (buffer, TREE_OPERAND (node, 1), spc+4, flags, true);
1173       newline_and_indent (buffer, spc+2);
1174       pp_string (buffer, "}");
1175       is_expr = false;
1176       break;
1177
1178     case CATCH_EXPR:
1179       pp_string (buffer, "catch (");
1180       dump_generic_node (buffer, CATCH_TYPES (node), spc+2, flags, false);
1181       pp_string (buffer, ")");
1182       newline_and_indent (buffer, spc+2);
1183       pp_string (buffer, "{");
1184       newline_and_indent (buffer, spc+4);
1185       dump_generic_node (buffer, CATCH_BODY (node), spc+4, flags, true);
1186       newline_and_indent (buffer, spc+2);
1187       pp_string (buffer, "}");
1188       is_expr = false;
1189       break;
1190
1191     case EH_FILTER_EXPR:
1192       pp_string (buffer, "<<<eh_filter (");
1193       dump_generic_node (buffer, EH_FILTER_TYPES (node), spc+2, flags, false);
1194       pp_string (buffer, ")>>>");
1195       newline_and_indent (buffer, spc+2);
1196       pp_string (buffer, "{");
1197       newline_and_indent (buffer, spc+4);
1198       dump_generic_node (buffer, EH_FILTER_FAILURE (node), spc+4, flags, true);
1199       newline_and_indent (buffer, spc+2);
1200       pp_string (buffer, "}");
1201       is_expr = false;
1202       break;
1203
1204     case GOTO_SUBROUTINE_EXPR:
1205       NIY;
1206       break;
1207
1208     case LABEL_EXPR:
1209       op0 = TREE_OPERAND (node, 0);
1210       /* If this is for break or continue, don't bother printing it.  */
1211       if (DECL_NAME (op0))
1212         {
1213           const char *name = IDENTIFIER_POINTER (DECL_NAME (op0));
1214           if (strcmp (name, "break") == 0
1215               || strcmp (name, "continue") == 0)
1216             break;
1217         }
1218       dump_generic_node (buffer, op0, spc, flags, false);
1219       pp_character (buffer, ':');
1220       if (DECL_NONLOCAL (op0))
1221         pp_string (buffer, " [non-local]");
1222       break;
1223
1224     case LABELED_BLOCK_EXPR:
1225       op0 = LABELED_BLOCK_LABEL (node);
1226       /* If this is for break or continue, don't bother printing it.  */
1227       if (DECL_NAME (op0))
1228         {
1229           const char *name = IDENTIFIER_POINTER (DECL_NAME (op0));
1230           if (strcmp (name, "break") == 0
1231               || strcmp (name, "continue") == 0)
1232             {
1233               dump_generic_node (buffer, LABELED_BLOCK_BODY (node), spc, flags, false);
1234               break;
1235             }
1236         }
1237       dump_generic_node (buffer, LABELED_BLOCK_LABEL (node), spc, flags, false);
1238       pp_string (buffer, ": {");
1239       if (!(flags & TDF_SLIM))
1240         newline_and_indent (buffer, spc+2);
1241       dump_generic_node (buffer, LABELED_BLOCK_BODY (node), spc+2, flags, true);
1242       if (!flags)
1243         newline_and_indent (buffer, spc);
1244       pp_character (buffer, '}');
1245       is_expr = false;
1246       break;
1247
1248     case EXIT_BLOCK_EXPR:
1249       op0 = LABELED_BLOCK_LABEL (EXIT_BLOCK_LABELED_BLOCK (node));
1250       /* If this is for a break or continue, print it accordingly.  */
1251       if (DECL_NAME (op0))
1252         {
1253           const char *name = IDENTIFIER_POINTER (DECL_NAME (op0));
1254           if (strcmp (name, "break") == 0
1255               || strcmp (name, "continue") == 0)
1256             {
1257               pp_string (buffer, name);
1258               break;
1259             }
1260         }
1261       pp_string (buffer, "<<<exit block ");
1262       dump_generic_node (buffer, op0, spc, flags, false);
1263       pp_string (buffer, ">>>");
1264       break;
1265
1266     case EXC_PTR_EXPR:
1267       pp_string (buffer, "<<<exception object>>>");
1268       break;
1269
1270     case FILTER_EXPR:
1271       pp_string (buffer, "<<<filter object>>>");
1272       break;
1273
1274     case LOOP_EXPR:
1275       pp_string (buffer, "while (1)");
1276       if (!(flags & TDF_SLIM))
1277         {
1278           newline_and_indent (buffer, spc+2);
1279           pp_character (buffer, '{');
1280           newline_and_indent (buffer, spc+4);
1281           dump_generic_node (buffer, LOOP_EXPR_BODY (node), spc+4, flags, true);
1282           newline_and_indent (buffer, spc+2);
1283           pp_character (buffer, '}');
1284         }
1285       is_expr = false;
1286       break;
1287
1288     case RETURN_EXPR:
1289       pp_string (buffer, "return");
1290       op0 = TREE_OPERAND (node, 0);
1291       if (op0)
1292         {
1293           pp_space (buffer);
1294           if (TREE_CODE (op0) == MODIFY_EXPR)
1295             dump_generic_node (buffer, TREE_OPERAND (op0, 1), spc, flags, false);
1296           else
1297             dump_generic_node (buffer, op0, spc, flags, false);
1298         }
1299       break;
1300
1301     case EXIT_EXPR:
1302       pp_string (buffer, "if (");
1303       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
1304       pp_string (buffer, ") break");
1305       break;
1306
1307     case SWITCH_EXPR:
1308       pp_string (buffer, "switch (");
1309       dump_generic_node (buffer, SWITCH_COND (node), spc, flags, false);
1310       pp_character (buffer, ')');
1311       if (!(flags & TDF_SLIM))
1312         {
1313           newline_and_indent (buffer, spc+2);
1314           pp_character (buffer, '{');
1315           if (SWITCH_BODY (node))
1316             {
1317               newline_and_indent (buffer, spc+4);
1318               dump_generic_node (buffer, SWITCH_BODY (node), spc+4, flags, true);
1319             }
1320           else
1321             {
1322               tree vec = SWITCH_LABELS (node);
1323               size_t i, n = TREE_VEC_LENGTH (vec);
1324               for (i = 0; i < n; ++i)
1325                 {
1326                   tree elt = TREE_VEC_ELT (vec, i);
1327                   newline_and_indent (buffer, spc+4);
1328                   dump_generic_node (buffer, elt, spc+4, flags, false);
1329                   pp_string (buffer, " goto ");
1330                   dump_generic_node (buffer, CASE_LABEL (elt), spc+4, flags, true);
1331                   pp_semicolon (buffer);
1332                 }
1333             }
1334           newline_and_indent (buffer, spc+2);
1335           pp_character (buffer, '}');
1336         }
1337       is_expr = false;
1338       break;
1339
1340     case GOTO_EXPR:
1341       op0 = GOTO_DESTINATION (node);
1342       if (TREE_CODE (op0) != SSA_NAME
1343           && DECL_P (op0)
1344           && DECL_NAME (op0))
1345         {
1346           const char *name = IDENTIFIER_POINTER (DECL_NAME (op0));
1347           if (strcmp (name, "break") == 0
1348               || strcmp (name, "continue") == 0)
1349             {
1350               pp_string (buffer, name);
1351               break;
1352             }
1353         }
1354       pp_string (buffer, "goto ");
1355       dump_generic_node (buffer, op0, spc, flags, false);
1356       break;
1357
1358     case RESX_EXPR:
1359       pp_string (buffer, "resx");
1360       /* ??? Any sensible way to present the eh region?  */
1361       break;
1362
1363     case ASM_EXPR:
1364       pp_string (buffer, "__asm__");
1365       if (ASM_VOLATILE_P (node))
1366         pp_string (buffer, " __volatile__");
1367       pp_character (buffer, '(');
1368       dump_generic_node (buffer, ASM_STRING (node), spc, flags, false);
1369       pp_character (buffer, ':');
1370       dump_generic_node (buffer, ASM_OUTPUTS (node), spc, flags, false);
1371       pp_character (buffer, ':');
1372       dump_generic_node (buffer, ASM_INPUTS (node), spc, flags, false);
1373       if (ASM_CLOBBERS (node))
1374         {
1375           pp_character (buffer, ':');
1376           dump_generic_node (buffer, ASM_CLOBBERS (node), spc, flags, false);
1377         }
1378       pp_string (buffer, ")");
1379       break;
1380
1381     case CASE_LABEL_EXPR:
1382       if (CASE_LOW (node) && CASE_HIGH (node))
1383         {
1384           pp_string (buffer, "case ");
1385           dump_generic_node (buffer, CASE_LOW (node), spc, flags, false);
1386           pp_string (buffer, " ... ");
1387           dump_generic_node (buffer, CASE_HIGH (node), spc, flags, false);
1388         }
1389       else if (CASE_LOW (node))
1390         {
1391           pp_string (buffer, "case ");
1392           dump_generic_node (buffer, CASE_LOW (node), spc, flags, false);
1393         }
1394       else
1395         pp_string (buffer, "default ");
1396       pp_character (buffer, ':');
1397       break;
1398
1399     case OBJ_TYPE_REF:
1400       pp_string (buffer, "OBJ_TYPE_REF(");
1401       dump_generic_node (buffer, OBJ_TYPE_REF_EXPR (node), spc, flags, false);
1402       pp_character (buffer, ';');
1403       dump_generic_node (buffer, OBJ_TYPE_REF_OBJECT (node), spc, flags, false);
1404       pp_character (buffer, '-');
1405       pp_character (buffer, '>');
1406       dump_generic_node (buffer, OBJ_TYPE_REF_TOKEN (node), spc, flags, false);
1407       pp_character (buffer, ')');
1408       break;
1409
1410     case PHI_NODE:
1411       {
1412         int i;
1413
1414         dump_generic_node (buffer, PHI_RESULT (node), spc, flags, false);
1415         pp_string (buffer, " = PHI <");
1416         for (i = 0; i < PHI_NUM_ARGS (node); i++)
1417           {
1418             dump_generic_node (buffer, PHI_ARG_DEF (node, i), spc, flags, false);
1419             pp_string (buffer, "(");
1420             pp_decimal_int (buffer, PHI_ARG_EDGE (node, i)->src->index);
1421             pp_string (buffer, ")");
1422             if (i < PHI_NUM_ARGS (node) - 1)
1423               pp_string (buffer, ", ");
1424           }
1425         pp_string (buffer, ">;");
1426       }
1427       break;
1428
1429     case SSA_NAME:
1430       dump_generic_node (buffer, SSA_NAME_VAR (node), spc, flags, false);
1431       pp_string (buffer, "_");
1432       pp_decimal_int (buffer, SSA_NAME_VERSION (node));
1433       break;
1434
1435     case VALUE_HANDLE:
1436       pp_printf (buffer, "VH.%d", VALUE_HANDLE_ID (node));
1437       break;
1438
1439     default:
1440       NIY;
1441     }
1442
1443   if (is_stmt && is_expr)
1444     pp_semicolon (buffer);
1445   pp_write_text_to_stream (buffer);
1446
1447   return spc;
1448 }
1449
1450 /* Print the declaration of a variable.  */
1451
1452 static void
1453 print_declaration (pretty_printer *buffer, tree t, int spc, int flags)
1454 {
1455   INDENT (spc);
1456
1457   if (TREE_CODE (t) == TYPE_DECL)
1458     pp_string (buffer, "typedef ");
1459
1460   if (DECL_REGISTER (t))
1461     pp_string (buffer, "register ");
1462
1463   if (TREE_PUBLIC (t) && DECL_EXTERNAL (t))
1464     pp_string (buffer, "extern ");
1465   else if (TREE_STATIC (t))
1466     pp_string (buffer, "static ");
1467
1468   /* Print the type and name.  */
1469   if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
1470     {
1471       tree tmp;
1472
1473       /* Print array's type.  */
1474       tmp = TREE_TYPE (t);
1475       while (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
1476         tmp = TREE_TYPE (tmp);
1477       dump_generic_node (buffer, TREE_TYPE (tmp), spc, flags, false);
1478
1479       /* Print variable's name.  */
1480       pp_space (buffer);
1481       dump_generic_node (buffer, t, spc, flags, false);
1482
1483       /* Print the dimensions.  */
1484       tmp = TREE_TYPE (t);
1485       while (TREE_CODE (tmp) == ARRAY_TYPE)
1486         {
1487           pp_character (buffer, '[');
1488           if (TYPE_DOMAIN (tmp))
1489             {
1490               if (TREE_CODE (TYPE_SIZE (tmp)) == INTEGER_CST)
1491                 pp_wide_integer (buffer,
1492                                 TREE_INT_CST_LOW (TYPE_SIZE (tmp)) /
1493                                 TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tmp))));
1494               else
1495                 dump_generic_node (buffer, TYPE_SIZE_UNIT (tmp), spc, flags,
1496                                    false);
1497             }
1498           pp_character (buffer, ']');
1499           tmp = TREE_TYPE (tmp);
1500         }
1501     }
1502   else if (TREE_CODE (t) == FUNCTION_DECL)
1503     {
1504       dump_generic_node (buffer, TREE_TYPE (TREE_TYPE (t)), spc, flags, false);
1505       pp_space (buffer);
1506       dump_decl_name (buffer, t, flags);
1507       dump_function_declaration (buffer, TREE_TYPE (t), spc, flags);
1508     }
1509   else
1510     {
1511       /* Print type declaration.  */
1512       dump_generic_node (buffer, TREE_TYPE (t), spc, flags, false);
1513
1514       /* Print variable's name.  */
1515       pp_space (buffer);
1516       dump_generic_node (buffer, t, spc, flags, false);
1517     }
1518
1519   /* The initial value of a function serves to determine wether the function
1520      is declared or defined.  So the following does not apply to function
1521      nodes.  */
1522   if (TREE_CODE (t) != FUNCTION_DECL)
1523     {
1524       /* Print the initial value.  */
1525       if (DECL_INITIAL (t))
1526         {
1527           pp_space (buffer);
1528           pp_character (buffer, '=');
1529           pp_space (buffer);
1530           dump_generic_node (buffer, DECL_INITIAL (t), spc, flags, false);
1531         }
1532     }
1533
1534   pp_character (buffer, ';');
1535 }
1536
1537
1538 /* Prints a structure: name, fields, and methods.
1539    FIXME: Still incomplete.  */
1540
1541 static void
1542 print_struct_decl (pretty_printer *buffer, tree node, int spc, int flags)
1543 {
1544   /* Print the name of the structure.  */
1545   if (TYPE_NAME (node))
1546     {
1547       INDENT (spc);
1548       if (TREE_CODE (node) == RECORD_TYPE)
1549         pp_string (buffer, "struct ");
1550       else if ((TREE_CODE (node) == UNION_TYPE
1551                 || TREE_CODE (node) == QUAL_UNION_TYPE))
1552         pp_string (buffer, "union ");
1553
1554       dump_generic_node (buffer, TYPE_NAME (node), spc, 0, false);
1555     }
1556
1557   /* Print the contents of the structure.  */
1558   pp_newline (buffer);
1559   INDENT (spc);
1560   pp_character (buffer, '{');
1561   pp_newline (buffer);
1562
1563   /* Print the fields of the structure.  */
1564   {
1565     tree tmp;
1566     tmp = TYPE_FIELDS (node);
1567     while (tmp)
1568       {
1569         /* Avoid to print recursively the structure.  */
1570         /* FIXME : Not implemented correctly...,
1571            what about the case when we have a cycle in the contain graph? ...
1572            Maybe this could be solved by looking at the scope in which the
1573            structure was declared.  */
1574         if (TREE_TYPE (tmp) != node
1575             || (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE
1576                 && TREE_TYPE (TREE_TYPE (tmp)) != node))
1577           {
1578             print_declaration (buffer, tmp, spc+2, flags);
1579             pp_newline (buffer);
1580           }
1581         tmp = TREE_CHAIN (tmp);
1582       }
1583   }
1584   INDENT (spc);
1585   pp_character (buffer, '}');
1586 }
1587
1588 /* Return the priority of the operator OP.
1589
1590    From lowest to highest precedence with either left-to-right (L-R)
1591    or right-to-left (R-L) associativity]:
1592
1593      1  [L-R] ,
1594      2  [R-L] = += -= *= /= %= &= ^= |= <<= >>=
1595      3  [R-L] ?:
1596      4  [L-R] ||
1597      5  [L-R] &&
1598      6  [L-R] |
1599      7  [L-R] ^
1600      8  [L-R] &
1601      9  [L-R] == !=
1602     10  [L-R] < <= > >=
1603     11  [L-R] << >>
1604     12  [L-R] + -
1605     13  [L-R] * / %
1606     14  [R-L] ! ~ ++ -- + - * & (type) sizeof
1607     15  [L-R] fn() [] -> .
1608
1609    unary +, - and * have higher precedence than the corresponding binary
1610    operators.  */
1611
1612 static int
1613 op_prio (tree op)
1614 {
1615   if (op == NULL)
1616     return 9999;
1617
1618   switch (TREE_CODE (op))
1619     {
1620     case TREE_LIST:
1621     case COMPOUND_EXPR:
1622     case BIND_EXPR:
1623       return 1;
1624
1625     case MODIFY_EXPR:
1626     case INIT_EXPR:
1627       return 2;
1628
1629     case COND_EXPR:
1630       return 3;
1631
1632     case TRUTH_OR_EXPR:
1633     case TRUTH_ORIF_EXPR:
1634       return 4;
1635
1636     case TRUTH_AND_EXPR:
1637     case TRUTH_ANDIF_EXPR:
1638       return 5;
1639
1640     case BIT_IOR_EXPR:
1641       return 6;
1642
1643     case BIT_XOR_EXPR:
1644     case TRUTH_XOR_EXPR:
1645       return 7;
1646
1647     case BIT_AND_EXPR:
1648       return 8;
1649
1650     case EQ_EXPR:
1651     case NE_EXPR:
1652       return 9;
1653
1654     case UNLT_EXPR:
1655     case UNLE_EXPR:
1656     case UNGT_EXPR:
1657     case UNGE_EXPR:
1658     case UNEQ_EXPR:
1659     case LTGT_EXPR:
1660     case ORDERED_EXPR:
1661     case UNORDERED_EXPR:
1662     case LT_EXPR:
1663     case LE_EXPR:
1664     case GT_EXPR:
1665     case GE_EXPR:
1666       return 10;
1667
1668     case LSHIFT_EXPR:
1669     case RSHIFT_EXPR:
1670     case LROTATE_EXPR:
1671     case RROTATE_EXPR:
1672       return 11;
1673
1674     case PLUS_EXPR:
1675     case MINUS_EXPR:
1676       return 12;
1677
1678     case MULT_EXPR:
1679     case TRUNC_DIV_EXPR:
1680     case CEIL_DIV_EXPR:
1681     case FLOOR_DIV_EXPR:
1682     case ROUND_DIV_EXPR:
1683     case RDIV_EXPR:
1684     case EXACT_DIV_EXPR:
1685     case TRUNC_MOD_EXPR:
1686     case CEIL_MOD_EXPR:
1687     case FLOOR_MOD_EXPR:
1688     case ROUND_MOD_EXPR:
1689       return 13;
1690
1691     case TRUTH_NOT_EXPR:
1692     case BIT_NOT_EXPR:
1693     case POSTINCREMENT_EXPR:
1694     case POSTDECREMENT_EXPR:
1695     case PREINCREMENT_EXPR:
1696     case PREDECREMENT_EXPR:
1697     case NEGATE_EXPR:
1698     case INDIRECT_REF:
1699     case ADDR_EXPR:
1700     case FLOAT_EXPR:
1701     case NOP_EXPR:
1702     case CONVERT_EXPR:
1703     case FIX_TRUNC_EXPR:
1704     case FIX_CEIL_EXPR:
1705     case FIX_FLOOR_EXPR:
1706     case FIX_ROUND_EXPR:
1707     case TARGET_EXPR:
1708       return 14;
1709
1710     case CALL_EXPR:
1711     case ARRAY_REF:
1712     case ARRAY_RANGE_REF:
1713     case COMPONENT_REF:
1714       return 15;
1715
1716       /* Special expressions.  */
1717     case MIN_EXPR:
1718     case MAX_EXPR:
1719     case ABS_EXPR:
1720     case REALPART_EXPR:
1721     case IMAGPART_EXPR:
1722       return 16;
1723
1724     case SAVE_EXPR:
1725     case NON_LVALUE_EXPR:
1726       return op_prio (TREE_OPERAND (op, 0));
1727
1728     default:
1729       /* Return an arbitrarily high precedence to avoid surrounding single
1730          VAR_DECLs in ()s.  */
1731       return 9999;
1732     }
1733 }
1734
1735
1736 /* Return the symbol associated with operator OP.  */
1737
1738 static const char *
1739 op_symbol (tree op)
1740 {
1741   if (op == NULL)
1742     abort ();
1743
1744   switch (TREE_CODE (op))
1745     {
1746     case MODIFY_EXPR:
1747       return "=";
1748
1749     case TRUTH_OR_EXPR:
1750     case TRUTH_ORIF_EXPR:
1751       return "||";
1752
1753     case TRUTH_AND_EXPR:
1754     case TRUTH_ANDIF_EXPR:
1755       return "&&";
1756
1757     case BIT_IOR_EXPR:
1758       return "|";
1759
1760     case TRUTH_XOR_EXPR:
1761     case BIT_XOR_EXPR:
1762       return "^";
1763
1764     case ADDR_EXPR:
1765     case BIT_AND_EXPR:
1766       return "&";
1767
1768     case ORDERED_EXPR:
1769       return "ord";
1770     case UNORDERED_EXPR:
1771       return "unord";
1772
1773     case EQ_EXPR:
1774       return "==";
1775     case UNEQ_EXPR:
1776       return "u==";
1777
1778     case NE_EXPR:
1779       return "!=";
1780
1781     case LT_EXPR:
1782       return "<";
1783     case UNLT_EXPR:
1784       return "u<";
1785
1786     case LE_EXPR:
1787       return "<=";
1788     case UNLE_EXPR:
1789       return "u<=";
1790
1791     case GT_EXPR:
1792       return ">";
1793     case UNGT_EXPR:
1794       return "u>";
1795
1796     case GE_EXPR:
1797       return ">=";
1798     case UNGE_EXPR:
1799       return "u>=";
1800
1801     case LTGT_EXPR:
1802       return "<>";
1803
1804     case LSHIFT_EXPR:
1805       return "<<";
1806
1807     case RSHIFT_EXPR:
1808       return ">>";
1809
1810     case PLUS_EXPR:
1811       return "+";
1812
1813     case NEGATE_EXPR:
1814     case MINUS_EXPR:
1815       return "-";
1816
1817     case BIT_NOT_EXPR:
1818       return "~";
1819
1820     case TRUTH_NOT_EXPR:
1821       return "!";
1822
1823     case MULT_EXPR:
1824     case INDIRECT_REF:
1825       return "*";
1826
1827     case TRUNC_DIV_EXPR:
1828     case CEIL_DIV_EXPR:
1829     case FLOOR_DIV_EXPR:
1830     case ROUND_DIV_EXPR:
1831     case RDIV_EXPR:
1832     case EXACT_DIV_EXPR:
1833       return "/";
1834
1835     case TRUNC_MOD_EXPR:
1836     case CEIL_MOD_EXPR:
1837     case FLOOR_MOD_EXPR:
1838     case ROUND_MOD_EXPR:
1839       return "%";
1840
1841     case PREDECREMENT_EXPR:
1842       return " --";
1843
1844     case PREINCREMENT_EXPR:
1845       return " ++";
1846
1847     case POSTDECREMENT_EXPR:
1848       return "-- ";
1849
1850     case POSTINCREMENT_EXPR:
1851       return "++ ";
1852
1853     default:
1854       return "<<< ??? >>>";
1855     }
1856 }
1857
1858 /* Prints the name of a CALL_EXPR.  */
1859
1860 static void
1861 print_call_name (pretty_printer *buffer, tree node)
1862 {
1863   tree op0;
1864
1865   if (TREE_CODE (node) != CALL_EXPR)
1866     abort ();
1867
1868   op0 = TREE_OPERAND (node, 0);
1869
1870   if (TREE_CODE (op0) == NON_LVALUE_EXPR)
1871     op0 = TREE_OPERAND (op0, 0);
1872
1873   switch (TREE_CODE (op0))
1874     {
1875     case VAR_DECL:
1876     case PARM_DECL:
1877       PRINT_FUNCTION_NAME (op0);
1878       break;
1879
1880     case ADDR_EXPR:
1881     case INDIRECT_REF:
1882     case NOP_EXPR:
1883       dump_generic_node (buffer, TREE_OPERAND (op0, 0), 0, 0, false);
1884       break;
1885
1886     case COND_EXPR:
1887       pp_string (buffer, "(");
1888       dump_generic_node (buffer, TREE_OPERAND (op0, 0), 0, 0, false);
1889       pp_string (buffer, ") ? ");
1890       dump_generic_node (buffer, TREE_OPERAND (op0, 1), 0, 0, false);
1891       pp_string (buffer, " : ");
1892       dump_generic_node (buffer, TREE_OPERAND (op0, 2), 0, 0, false);
1893       break;
1894
1895     case COMPONENT_REF:
1896       /* The function is a pointer contained in a structure.  */
1897       if (TREE_CODE (TREE_OPERAND (op0, 0)) == INDIRECT_REF ||
1898           TREE_CODE (TREE_OPERAND (op0, 0)) == VAR_DECL)
1899         PRINT_FUNCTION_NAME (TREE_OPERAND (op0, 1));
1900       else
1901         dump_generic_node (buffer, TREE_OPERAND (op0, 0), 0, 0, false);
1902       /* else
1903          We can have several levels of structures and a function
1904          pointer inside.  This is not implemented yet...  */
1905       /*                  NIY;*/
1906       break;
1907
1908     case ARRAY_REF:
1909       if (TREE_CODE (TREE_OPERAND (op0, 0)) == VAR_DECL)
1910         PRINT_FUNCTION_NAME (TREE_OPERAND (op0, 0));
1911       else
1912         dump_generic_node (buffer, op0, 0, 0, false);
1913       break;
1914
1915     case SSA_NAME:
1916     case OBJ_TYPE_REF:
1917       dump_generic_node (buffer, op0, 0, 0, false);
1918       break;
1919
1920     default:
1921       NIY;
1922     }
1923 }
1924
1925 /* Parses the string STR and replaces new-lines by '\n', tabs by '\t', ...  */
1926
1927 static void
1928 pretty_print_string (pretty_printer *buffer, const char *str)
1929 {
1930   if (str == NULL)
1931     return;
1932
1933   while (*str)
1934     {
1935       switch (str[0])
1936         {
1937         case '\b':
1938           pp_string (buffer, "\\b");
1939           break;
1940
1941         case '\f':
1942           pp_string (buffer, "\\f");
1943           break;
1944
1945         case '\n':
1946           pp_string (buffer, "\\n");
1947           break;
1948
1949         case '\r':
1950           pp_string (buffer, "\\r");
1951           break;
1952
1953         case '\t':
1954           pp_string (buffer, "\\t");
1955           break;
1956
1957         case '\v':
1958           pp_string (buffer, "\\v");
1959           break;
1960
1961         case '\\':
1962           pp_string (buffer, "\\\\");
1963           break;
1964
1965         case '\"':
1966           pp_string (buffer, "\\\"");
1967           break;
1968
1969         case '\'':
1970           pp_string (buffer, "\\'");
1971           break;
1972
1973         case '\0':
1974           pp_string (buffer, "\\0");
1975           break;
1976
1977         case '\1':
1978           pp_string (buffer, "\\1");
1979           break;
1980
1981         case '\2':
1982           pp_string (buffer, "\\2");
1983           break;
1984
1985         case '\3':
1986           pp_string (buffer, "\\3");
1987           break;
1988
1989         case '\4':
1990           pp_string (buffer, "\\4");
1991           break;
1992
1993         case '\5':
1994           pp_string (buffer, "\\5");
1995           break;
1996
1997         case '\6':
1998           pp_string (buffer, "\\6");
1999           break;
2000
2001         case '\7':
2002           pp_string (buffer, "\\7");
2003           break;
2004
2005         default:
2006           pp_character (buffer, str[0]);
2007           break;
2008         }
2009       str++;
2010     }
2011 }
2012
2013 static void
2014 maybe_init_pretty_print (FILE *file)
2015 {
2016   if (!initialized)
2017     {
2018       pp_construct (&buffer, /* prefix */NULL, /* line-width */0);
2019       pp_needs_newline (&buffer) = true;
2020       initialized = 1;
2021     }
2022
2023   buffer.buffer->stream = file;
2024 }
2025
2026 static void
2027 newline_and_indent (pretty_printer *buffer, int spc)
2028 {
2029   pp_newline (buffer);
2030   INDENT (spc);
2031 }
2032
2033 static void
2034 dump_vops (pretty_printer *buffer, tree stmt, int spc, int flags)
2035 {
2036   size_t i;
2037   stmt_ann_t ann = stmt_ann (stmt);
2038   v_may_def_optype v_may_defs = V_MAY_DEF_OPS (ann);
2039   v_must_def_optype v_must_defs = V_MUST_DEF_OPS (ann);
2040   vuse_optype vuses = VUSE_OPS (ann);
2041
2042   for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++)
2043     {
2044       pp_string (buffer, "#   ");
2045       dump_generic_node (buffer, V_MAY_DEF_RESULT (v_may_defs, i), 
2046                          spc + 2, flags, false);
2047       pp_string (buffer, " = V_MAY_DEF <");
2048       dump_generic_node (buffer, V_MAY_DEF_OP (v_may_defs, i), 
2049                          spc + 2, flags, false);
2050       pp_string (buffer, ">;");
2051       newline_and_indent (buffer, spc);
2052     }
2053
2054   for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++)
2055     {
2056       tree v_must_def = V_MUST_DEF_OP (v_must_defs, i);
2057       pp_string (buffer, "#   V_MUST_DEF <");
2058       dump_generic_node (buffer, v_must_def, spc + 2, flags, false);
2059       pp_string (buffer, ">;");
2060       newline_and_indent (buffer, spc);
2061     }
2062
2063   for (i = 0; i < NUM_VUSES (vuses); i++)
2064     {
2065       tree vuse = VUSE_OP (vuses, i);
2066       pp_string (buffer, "#   VUSE <");
2067       dump_generic_node (buffer, vuse, spc + 2, flags, false);
2068       pp_string (buffer, ">;");
2069       newline_and_indent (buffer, spc);
2070     }
2071 }
2072
2073 /* Dumps basic block BB to FILE with details described by FLAGS and
2074    indented by INDENT spaces.  */
2075
2076 void
2077 dump_generic_bb (FILE *file, basic_block bb, int indent, int flags)
2078 {
2079   maybe_init_pretty_print (file);
2080   dumping_stmts = true;
2081   dump_generic_bb_buff (&buffer, bb, indent, flags);
2082   pp_flush (&buffer);
2083 }
2084
2085 /* Dumps header of basic block BB to buffer BUFFER indented by INDENT
2086    spaces and details described by flags.  */
2087
2088 static void
2089 dump_bb_header (pretty_printer *buffer, basic_block bb, int indent, int flags)
2090 {
2091   edge e;
2092   tree stmt;
2093
2094   if (flags & TDF_BLOCKS)
2095     {
2096       INDENT (indent);
2097       pp_string (buffer, "# BLOCK ");
2098       pp_decimal_int (buffer, bb->index);
2099
2100       if (flags & TDF_LINENO)
2101         {
2102           block_stmt_iterator bsi;
2103
2104           for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
2105             if (get_lineno (bsi_stmt (bsi)) != -1)
2106               {
2107                 pp_string (buffer, ", starting at line ");
2108                 pp_decimal_int (buffer, get_lineno (bsi_stmt (bsi)));
2109                 break;
2110               }
2111         }
2112       newline_and_indent (buffer, indent);
2113
2114       pp_string (buffer, "# PRED:");
2115       pp_write_text_to_stream (buffer);
2116       for (e = bb->pred; e; e = e->pred_next)
2117         if (flags & TDF_SLIM)
2118           {
2119             pp_string (buffer, " ");
2120             if (e->src == ENTRY_BLOCK_PTR)
2121               pp_string (buffer, "ENTRY");
2122             else
2123               pp_decimal_int (buffer, e->src->index);
2124           }
2125         else
2126           dump_edge_info (buffer->buffer->stream, e, 0);
2127       pp_newline (buffer);
2128     }
2129   else
2130     {
2131       stmt = first_stmt (bb);
2132       if (!stmt || TREE_CODE (stmt) != LABEL_EXPR)
2133         {
2134           INDENT (indent - 2);
2135           pp_string (buffer, "<bb ");
2136           pp_decimal_int (buffer, bb->index);
2137           pp_string (buffer, ">:");
2138           pp_newline (buffer);
2139         }
2140     }
2141 }
2142
2143 /* Dumps end of basic block BB to buffer BUFFER indented by INDENT
2144    spaces.  */
2145
2146 static void
2147 dump_bb_end (pretty_printer *buffer, basic_block bb, int indent, int flags)
2148 {
2149   edge e;
2150
2151   INDENT (indent);
2152   pp_string (buffer, "# SUCC:");
2153   pp_write_text_to_stream (buffer);
2154   for (e = bb->succ; e; e = e->succ_next)
2155     if (flags & TDF_SLIM)
2156       {
2157         pp_string (buffer, " ");
2158         if (e->dest == EXIT_BLOCK_PTR)
2159           pp_string (buffer, "EXIT");
2160         else
2161           pp_decimal_int (buffer, e->dest->index);
2162       }
2163     else
2164       dump_edge_info (buffer->buffer->stream, e, 1);
2165   pp_newline (buffer);
2166 }
2167
2168 /* Dumps phi nodes of basic block BB to buffer BUFFER with details described by
2169    FLAGS indented by INDENT spaces.  */
2170
2171 static void
2172 dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags)
2173 {
2174   tree phi = phi_nodes (bb);
2175   if (!phi)
2176     return;
2177
2178   for (; phi; phi = PHI_CHAIN (phi))
2179     {
2180       if (is_gimple_reg (PHI_RESULT (phi)) || (flags & TDF_VOPS))
2181         {
2182           INDENT (indent);
2183           pp_string (buffer, "# ");
2184           dump_generic_node (buffer, phi, indent, flags, false);
2185           pp_newline (buffer);
2186         }
2187     }
2188 }
2189
2190 /* Dump jump to basic block BB that is represented implicitly in the cfg
2191    to BUFFER.  */
2192
2193 static void
2194 pp_cfg_jump (pretty_printer *buffer, basic_block bb)
2195 {
2196   tree stmt;
2197
2198   stmt = first_stmt (bb);
2199
2200   pp_string (buffer, "goto <bb ");
2201   pp_decimal_int (buffer, bb->index);
2202   pp_string (buffer, ">");
2203   if (stmt && TREE_CODE (stmt) == LABEL_EXPR)
2204     {
2205       pp_string (buffer, " (");
2206       dump_generic_node (buffer, LABEL_EXPR_LABEL (stmt), 0, 0, false);
2207       pp_string (buffer, ")");
2208     }
2209   pp_semicolon (buffer);
2210 }
2211
2212 /* Dump edges represented implicitly in basic block BB to BUFFER, indented
2213    by INDENT spaces, with details given by FLAGS.  */
2214
2215 static void
2216 dump_implicit_edges (pretty_printer *buffer, basic_block bb, int indent,
2217                      int flags)
2218 {
2219   edge e;
2220
2221   /* If there is a fallthru edge, we may need to add an artificial goto to the
2222      dump.  */
2223   for (e = bb->succ; e; e = e->succ_next)
2224     if (e->flags & EDGE_FALLTHRU)
2225       break;
2226   if (e && e->dest != bb->next_bb)
2227     {
2228       INDENT (indent);
2229
2230       if ((flags & TDF_LINENO)
2231 #ifdef USE_MAPPED_LOCATION
2232           && e->goto_locus != UNKNOWN_LOCATION
2233 #else
2234           && e->goto_locus
2235 #endif
2236           )
2237         {
2238           expanded_location goto_xloc;
2239 #ifdef USE_MAPPED_LOCATION
2240           goto_xloc = expand_location (e->goto_locus);
2241 #else
2242           goto_xloc = *e->goto_locus;
2243 #endif
2244           pp_character (buffer, '[');
2245           if (goto_xloc.file)
2246             {
2247               pp_string (buffer, goto_xloc.file);
2248               pp_string (buffer, " : ");
2249             }
2250           pp_decimal_int (buffer, goto_xloc.line);
2251           pp_string (buffer, "] ");
2252         }
2253
2254       pp_cfg_jump (buffer, e->dest);
2255       pp_newline (buffer);
2256     }
2257 }
2258
2259 /* Dumps basic block BB to buffer BUFFER with details described by FLAGS and
2260    indented by INDENT spaces.  */
2261
2262 static void
2263 dump_generic_bb_buff (pretty_printer *buffer, basic_block bb,
2264                       int indent, int flags)
2265 {
2266   block_stmt_iterator bsi;
2267   tree stmt;
2268   int label_indent = indent - 2;
2269
2270   if (label_indent < 0)
2271     label_indent = 0;
2272
2273   dump_bb_header (buffer, bb, indent, flags);
2274
2275   if (bb_ann (bb))
2276     dump_phi_nodes (buffer, bb, indent, flags);
2277   
2278   for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
2279     {
2280       int curr_indent;
2281
2282       stmt = bsi_stmt (bsi);
2283
2284       curr_indent = TREE_CODE (stmt) == LABEL_EXPR ? label_indent : indent;
2285
2286       INDENT (curr_indent);
2287       dump_generic_node (buffer, stmt, curr_indent, flags, true);
2288       pp_newline (buffer);
2289     }
2290
2291   dump_implicit_edges (buffer, bb, indent, flags);
2292
2293   if (flags & TDF_BLOCKS)
2294     dump_bb_end (buffer, bb, indent, flags);
2295 }