OSDN Git Service

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