added missing parameter and initializer
[libfirm] / ir / ir / irdump.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/ir/irdump.c
4  * Purpose:     Write vcg representation of firm to file.
5  * Author:      Martin Trapp, Christian Schaefer
6  * Modified by: Goetz Lindenmaier, Hubert Schmidt
7  * Created:
8  * CVS-ID:      $Id$
9  * Copyright:   (c) 1998-2003 Universit�t Karlsruhe
10  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
11  */
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15
16 #ifdef HAVE_STRING_H
17 #include <string.h>
18 #endif
19 #ifdef HAVE_STDLIB_H
20 #include <stdlib.h>
21 #endif
22 #include <stdarg.h>
23
24 #include "firm_common_t.h"
25
26 #include "irnode.h"
27 #include "irgraph.h"
28 #include "irprog_t.h"
29 #include "entity_t.h"
30 #include "irop.h"
31
32 #include "irdump_t.h"
33
34 #include "irgwalk.h"
35 #include "typewalk.h"
36 #include "tv_t.h"
37 #include "type_or_entity.h"
38 #include "irouts.h"
39 #include "irdom.h"
40 #include "irloop_t.h"
41 #include "callgraph.h"
42 #include "irextbb_t.h"
43 #include "dbginfo_t.h"
44 #include "irtools.h"
45
46 #include "irvrfy.h"
47
48 #include "error.h"
49 #include "array.h"
50 #include "pmap.h"
51 #include "eset.h"
52 #include "pset.h"
53
54 #if DO_HEAPANALYSIS
55 extern void dump_irn_chi_term(FILE *FL, ir_node *n);
56 extern void dump_irn_state(FILE *FL, ir_node *n);
57 extern int  get_opt_dump_abstvals(void);
58 typedef unsigned long SeqNo;
59 extern SeqNo get_Block_seqno(ir_node *n);
60 #endif
61
62 /* basis for a color range for vcg */
63 static int n_colors   = 0;
64 static int base_color = 0;
65
66 /** Dump only irgs with names that start with this string */
67 static ident *dump_file_filter_id = NULL;
68
69 #define ERROR_TXT       "<ERROR>"
70
71 /*******************************************************************/
72 /* flags to steer output                                           */
73 /*******************************************************************/
74
75 /** An option to turn off edge labels */
76 static int edge_label = 1;
77 /** An option to turn off dumping values of constant entities */
78 static int const_entities = 1;
79 /** An option to dump the keep alive edges */
80 static int dump_keepalive = 0;
81 /** An option to dump ld_names instead of names. */
82 static int dump_ld_name = 1;
83 /** Compiler options to dump analysis information in dump_ir_graph */
84 static int dump_out_edge_flag = 0;
85 static int dump_loop_information_flag = 0;
86 static int dump_backedge_information_flag = 1;
87 static int dump_const_local = 0;
88 /** An option to dump all graph anchors */
89 static int dump_anchors = 0;
90
91 int dump_dominator_information_flag = 0;
92 int opt_dump_analysed_type_info = 1;
93 int opt_dump_pointer_values_to_info = 0;  /* default off: for test compares!! */
94
95 static dumper_colors overrule_nodecolor = ird_color_default;
96
97 /** An additional edge hook. */
98 static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
99
100 void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func)
101 {
102   dump_node_edge_hook = func;
103 }
104
105 DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void)
106 {
107   return dump_node_edge_hook;
108 }
109
110
111 /** The vcg node attribute hook. */
112 static DUMP_IR_GRAPH_FUNC dump_ir_graph_hook = NULL;
113 /** The vcg node attribute hook. */
114 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
115 /** The vcg edge attribute hook. */
116 static DUMP_EDGE_VCGATTR_FUNC dump_edge_vcgattr_hook = NULL;
117
118 /* set the ir graph hook */
119 void set_dump_ir_graph_hook(DUMP_IR_GRAPH_FUNC hook) {
120   dump_ir_graph_hook = hook;
121 }
122 /* set the node attribute hook */
123 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
124   dump_node_vcgattr_hook = hook;
125 }
126 /* set the edge attribute hook */
127 void set_dump_edge_vcgattr_hook(DUMP_EDGE_VCGATTR_FUNC hook) {
128   dump_edge_vcgattr_hook = hook;
129 }
130
131 int get_opt_dump_const_local(void) {
132   if (!dump_out_edge_flag && !dump_loop_information_flag)
133     return dump_const_local;
134   else
135     return 0;
136 }
137
138 void only_dump_method_with_name(ident *name) {
139   dump_file_filter_id = name;
140 }
141
142 ident *get_dump_file_filter_ident(void) {
143   return dump_file_filter_id;
144 }
145
146 /** Returns non-zero if dump file filter is not set, or if it is a
147  *  prefix of name. */
148 int is_filtered_dump_name(ident *name) {
149   if (!dump_file_filter_id) return 1;
150   return id_is_prefix(dump_file_filter_id, name);
151 }
152
153 /* To turn off display of edge labels.  Edge labels often cause xvcg to
154    abort with a segmentation fault. */
155 void turn_off_edge_labels(void) {
156   edge_label = 0;
157 }
158
159 void dump_consts_local(int flag) {
160   dump_const_local = flag;
161 }
162
163 void dump_constant_entity_values(int flag) {
164   const_entities = flag;
165 }
166
167 void dump_keepalive_edges(int flag) {
168   dump_keepalive = flag;
169 }
170
171 int get_opt_dump_keepalive_edges(void) {
172   return dump_keepalive;
173 }
174
175 void dump_out_edges(int flag) {
176   dump_out_edge_flag = flag;
177 }
178
179 void dump_dominator_information(int flag) {
180   dump_dominator_information_flag = flag;
181 }
182
183 void dump_loop_information(int flag) {
184   dump_loop_information_flag = flag;
185 }
186
187 void dump_backedge_information(int flag) {
188   dump_backedge_information_flag = flag;
189 }
190
191 /* Dump the information of type field specified in ana/irtypeinfo.h.
192  * If the flag is set, the type name is output in [] in the node label,
193  * else it is output as info.
194  */
195 void set_opt_dump_analysed_type_info(int flag) {
196   opt_dump_analysed_type_info = flag;
197 }
198
199 void dump_pointer_values_to_info(int flag) {
200   opt_dump_pointer_values_to_info = flag;
201 }
202
203 void dump_ld_names(int flag) {
204   dump_ld_name = flag;
205 }
206
207 void dump_all_anchors(int flag) {
208   dump_anchors = flag;
209 }
210
211 /* -------------- some extended helper functions ----------------- */
212
213 /**
214  * returns the name of a mode or <ERROR> if mode is NOT a mode object.
215  * in the later case, sets bad
216  */
217 const char *get_mode_name_ex(ir_mode *mode, int *bad)
218 {
219   if (is_mode(mode))
220     return get_mode_name(mode);
221   *bad |= 1;
222   return ERROR_TXT;
223 }
224
225 /**
226  * returns the name of a type or <ERROR> if mode is NOT a mode object.
227  * in the later case, sets bad
228  */
229 const char *get_type_name_ex(ir_type *tp, int *bad)
230 {
231   if (is_type(tp))
232     return get_type_name(tp);
233   *bad |= 1;
234   return ERROR_TXT;
235 }
236
237 /**
238  * printf the VCG color
239  */
240 static void print_vcg_color(FILE *F, dumper_colors color) {
241   static const char *color_names[32] = {
242     "white",        "blue",      "red",        "green",
243     "yellow",       "magenta",   "cyan",       "darkgray",
244     "darkblue",     "darkred",   "darkgreen",  "darkyellow",
245     "darkmagenta",  "darkcyan",  "gold",       "lightgray",
246     "lightblue",    "lightred",  "lightgreen", "lightyellow",
247     "lightmagenta", "lightcyan", "lilac",      "turquoise",
248     "aquamarine",   "khaki",     "purple",     "yellowgreen",
249     "pink",         "orange",    "orchid",     "black"
250   };
251
252   if (color != ird_color_default)
253     fprintf(F, "color:%s", color_names[color]);
254 }
255
256 /**
257  * prints the edge from a type S to a type T with additional info fmt, ...
258  * to the file F
259  */
260 static void print_type_type_edge(FILE *F, ir_type *S, ir_type *T, const char *fmt, ...)
261 {
262   va_list ap;
263
264   va_start(ap, fmt);
265   fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
266   fprintf(F, " targetname: "); PRINT_TYPEID(T);
267   vfprintf(F, fmt, ap);
268   fprintf(F,"}\n");
269   va_end(ap);
270 }
271
272 /**
273  * prints the edge from a type T to an entity E with additional info fmt, ...
274  * to the file F
275  */
276 static void print_type_ent_edge(FILE *F, ir_type *T, entity *E, const char *fmt, ...)
277 {
278   va_list ap;
279
280   va_start(ap, fmt);
281   fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
282   fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
283   vfprintf(F, fmt, ap);
284   fprintf(F, "}\n");
285   va_end(ap);
286 }
287
288 /**
289  * prints the edge from an entity E to an entity T with additional info fmt, ...
290  * to the file F
291  */
292 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
293 {
294   va_list ap;
295
296   va_start(ap, fmt);
297   if (backedge)
298     fprintf(F, "backedge: { sourcename: \"");
299    else
300     fprintf(F, "edge: { sourcename: \"");
301   PRINT_ENTID(E);
302   fprintf(F, "\" targetname: \""); PRINT_ENTID(T);  fprintf(F, "\"");
303   vfprintf(F, fmt, ap);
304   fprintf(F, "}\n");
305   va_end(ap);
306 }
307
308 /**
309  * prints the edge from an entity E to a type T with additional info fmt, ...
310  * to the file F
311  */
312 static void print_ent_type_edge(FILE *F, entity *E, ir_type *T, const char *fmt, ...)
313 {
314   va_list ap;
315
316   va_start(ap, fmt);
317   fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
318   fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
319   vfprintf(F, fmt, ap);
320   fprintf(F,"}\n");
321   va_end(ap);
322 }
323
324 /**
325  * prints the edge from a node N to a type T with additional info fmt, ...
326  * to the file F
327  */
328 static void print_node_type_edge(FILE *F, const ir_node *N, ir_type *T, const char *fmt, ...)
329 {
330   va_list ap;
331
332   va_start(ap, fmt);
333   fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
334   fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
335   vfprintf(F, fmt, ap);
336   fprintf(F,"}\n");
337   va_end(ap);
338 }
339
340 /**
341  * prints the edge from a node N to an entity E with additional info fmt, ...
342  * to the file F
343  */
344 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
345 {
346   va_list ap;
347
348   va_start(ap, fmt);
349   fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
350   fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
351   fprintf(F, "\"");
352   vfprintf(F, fmt, ap);
353   fprintf(F,"}\n");
354   va_end(ap);
355 }
356
357 /**
358  * prints the edge from an entity E to a node N with additional info fmt, ...
359  * to the file F
360  */
361 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
362 {
363   va_list ap;
364
365   va_start(ap, fmt);
366   fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
367   fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
368   vfprintf(F, fmt, ap);
369   fprintf(F,"}\n");
370   va_end(ap);
371 }
372
373 /**
374  * prints the edge from a type E to an enumeration item item with additional info fmt, ...
375  * to the file F
376  */
377 static void print_enum_item_edge(FILE *F, ir_type *E, int item, const char *fmt, ...)
378 {
379   va_list ap;
380
381   va_start(ap, fmt);
382   fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
383   fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
384   vfprintf(F, fmt, ap);
385   fprintf(F,"}\n");
386   va_end(ap);
387 }
388
389 /*-----------------------------------------------------------------*/
390 /* global and ahead declarations                                   */
391 /*-----------------------------------------------------------------*/
392
393 static void dump_whole_node(ir_node *n, void *env);
394 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
395
396 /*-----------------------------------------------------------------*/
397 /* Helper functions.                                                */
398 /*-----------------------------------------------------------------*/
399
400 /**
401  * This map is used as a private link attr to be able to call dumper
402  * anywhere without destroying link fields.
403  */
404 static pmap *irdump_link_map = NULL;
405
406 /** NOT A STANDARD LIBFIRM INIT METHOD
407  *
408  * We do not want to integrate dumping into libfirm, i.e., if the dumpers
409  * are off, we want to have as few interferences as possible.  Therefore the
410  * initialization is performed lazily and not called from within init_firm.
411  *
412  * Creates the link attribute map. */
413 static void init_irdump(void) {
414   /* We need a new, empty map. */
415   if (irdump_link_map) pmap_destroy(irdump_link_map);
416   irdump_link_map = pmap_create();
417   if (!dump_file_filter_id)
418     dump_file_filter_id = new_id_from_str("");
419 }
420 /**
421  * Returns the private link field.
422  */
423 static void *ird_get_irn_link(ir_node *n) {
424   void *res = NULL;
425   if (!irdump_link_map) return NULL;
426
427   if (pmap_contains(irdump_link_map, (void *)n))
428     res = pmap_get(irdump_link_map, (void *)n);
429   return res;
430 }
431
432 /**
433  * Sets the private link field.
434  */
435 static void ird_set_irn_link(ir_node *n, void *x) {
436   if (!irdump_link_map)
437     init_irdump();
438   pmap_insert(irdump_link_map, (void *)n, x);
439 }
440
441 /**
442  * Gets the private link field of an irg.
443  */
444 static void *ird_get_irg_link(ir_graph *irg) {
445   void *res = NULL;
446   if (!irdump_link_map) return NULL;
447
448   if (pmap_contains(irdump_link_map, (void *)irg))
449     res = pmap_get(irdump_link_map, (void *)irg);
450   return res;
451 }
452
453 /**
454  * Sets the private link field of an irg.
455  */
456 static void ird_set_irg_link(ir_graph *irg, void *x) {
457   if (!irdump_link_map) init_irdump();
458   pmap_insert(irdump_link_map, (void *)irg, x);
459 }
460
461 /**
462  * Walker, clears the private link field.
463  */
464 static void clear_link(ir_node * node, void * env) {
465   ird_set_irn_link(node, NULL);
466 }
467
468 /**
469  * If the entity has a ld_name, returns it if the dump_ld_name is set,
470  * else returns the name of the entity.
471  */
472 static const char *_get_ent_dump_name(entity *ent, int dump_ld_name) {
473   if (!ent)
474     return "<NULL entity>";
475   if (dump_ld_name) {
476     /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
477     if (ent->ld_name) return get_id_str(ent->ld_name);
478   }
479   return get_id_str(ent->name);
480 }
481
482 /**
483  * If the entity has a ld_name, returns it if the option dump_ld_name is set,
484  * else returns the name of the entity.
485  */
486 const char *get_ent_dump_name(entity *ent) {
487   return _get_ent_dump_name(ent, dump_ld_name);
488 }
489
490 /* Returns the name of an IRG. */
491 const char *get_irg_dump_name(ir_graph *irg) {
492   /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
493   return _get_ent_dump_name(get_irg_entity(irg), 1);
494 }
495
496 /**
497  * Returns non-zero if a node is in floating state.
498  */
499 static int node_floats(ir_node *n) {
500   return ((get_irn_pinned(n) == op_pin_state_floats) &&
501       (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
502 }
503
504 /**
505  *  Walker that visits the anchors
506  */
507 static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
508   irg_walk_graph(irg, pre, post, env);
509
510   if (dump_anchors) {
511     int i;
512
513     for (i = anchor_max - 1; i >= 0; --i) {
514       ir_node *n = irg->anchors[i];
515
516       if (n) {
517         /* reset the visit flag: will be increase in the walker */
518         set_irg_visited(irg, get_irg_visited(irg) - 1);
519         irg_walk(n, pre, post, env);
520       }
521     }
522   }
523 }
524
525 /**
526  * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
527  */
528 static void collect_node(ir_node * node, void *env) {
529   if (is_Block(node)
530       || node_floats(node)
531       || get_irn_op(node) == op_Bad
532       || get_irn_op(node) == op_Unknown
533       || get_irn_op(node) == op_NoMem) {
534     ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
535     if (!arr) arr = NEW_ARR_F(ir_node *, 0);
536     ARR_APP1(ir_node *, arr, node);
537     ird_set_irg_link(get_irn_irg(node), arr);    /* arr is an l-value, APP_ARR might change it! */
538   } else {
539     ir_node * block = get_nodes_block(node);
540
541     if (is_Bad(block)) {
542       /* this node is in a Bad block, so we must place it into the graph's list */
543       ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
544       if (!arr) arr = NEW_ARR_F(ir_node *, 0);
545       ARR_APP1(ir_node *, arr, node);
546       ird_set_irg_link(get_irn_irg(node), arr);    /* arr is an l-value, APP_ARR might change it! */
547     }
548     else {
549       ird_set_irn_link(node, ird_get_irn_link(block));
550       ird_set_irn_link(block, node);
551     }
552   }
553 }
554
555 /** Construct lists to walk ir block-wise.
556  *
557  * Collects all blocks, nodes not op_pin_state_pinned,
558  * Bad, NoMem and Unknown into a flexible array in link field of
559  * irg they belong to.  Sets the irg link field to NULL in all
560  * graphs not visited.
561  * Free the list with DEL_ARR_F().
562  */
563 static ir_node **construct_block_lists(ir_graph *irg) {
564   int i, rem_view = get_interprocedural_view();
565   ir_graph *rem = current_ir_graph;
566   current_ir_graph = irg;
567
568   for (i = get_irp_n_irgs() - 1; i >= 0; --i)
569     ird_set_irg_link(get_irp_irg(i), NULL);
570
571   ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
572
573   /* Collect also EndReg and EndExcept. We do not want to change the walker. */
574   set_interprocedural_view(0);
575
576   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
577   irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
578   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
579   irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
580
581   set_interprocedural_view(rem_view);
582
583   current_ir_graph = rem;
584   return ird_get_irg_link(irg);
585 }
586
587 typedef struct _list_tuple {
588   ir_node **blk_list;
589   ir_extblk **extbb_list;
590 } list_tuple;
591
592 /** Construct lists to walk IR extended block-wise.
593  * Free the lists in the tuple with DEL_ARR_F().
594  * Sets the irg link field to NULL in all
595  * graphs not visited.
596  */
597 static list_tuple *construct_extblock_lists(ir_graph *irg) {
598   ir_node **blk_list = construct_block_lists(irg);
599   int i;
600   ir_graph *rem = current_ir_graph;
601   list_tuple *lists = xmalloc(sizeof(*lists));
602
603   current_ir_graph = irg;
604
605   lists->blk_list   = NEW_ARR_F(ir_node *, 0);
606   lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
607
608   inc_irg_block_visited(irg);
609   for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
610     ir_extblk *ext;
611
612     if (is_Block(blk_list[i])) {
613       ext = get_Block_extbb(blk_list[i]);
614
615       if (extbb_not_visited(ext)) {
616         ARR_APP1(ir_extblk *, lists->extbb_list, ext);
617         mark_extbb_visited(ext);
618       }
619     }
620     else
621       ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
622   }
623   DEL_ARR_F(blk_list);
624
625   current_ir_graph = rem;
626   ird_set_irg_link(irg, lists);
627   return lists;
628 }
629
630 /*-----------------------------------------------------------------*/
631 /* Routines to dump information about a single ir node.            */
632 /*-----------------------------------------------------------------*/
633
634 /*
635  * dump the name of a node n to the File F.
636  */
637 int dump_node_opcode(FILE *F, ir_node *n)
638 {
639   int bad = 0;
640   const ir_op_ops *ops = get_op_ops(get_irn_op(n));
641
642   /* call the dump_node operation if available */
643   if (ops->dump_node)
644     return ops->dump_node(n, F, dump_node_opcode_txt);
645
646   /* implementation for default nodes */
647   switch (get_irn_opcode(n)) {
648
649   case iro_Const: {
650     int res;
651     char buf[1024];
652     res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
653     assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
654     fprintf(F, buf);
655   } break;
656
657   case iro_SymConst: {
658     if (get_SymConst_kind(n) == symconst_addr_name) {
659       /* don't use get_SymConst_ptr_info as it mangles the name. */
660       fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
661     } else if (get_SymConst_kind(n) == symconst_addr_ent) {
662       assert(get_SymConst_entity(n));
663       assert(is_entity(get_SymConst_entity(n)));
664       fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
665     } else {
666       assert(get_kind(get_SymConst_type(n)) == k_type);
667       assert(get_type_ident(get_SymConst_type(n)));
668       fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
669       if (get_SymConst_kind(n) == symconst_type_tag)
670         fprintf (F, "tag");
671       else
672         fprintf (F, "size");
673     }
674   } break;
675
676   case iro_Filter: {
677     if (!get_interprocedural_view())
678       fprintf(F, "Proj'");
679     else
680       goto default_case;
681   } break;
682
683   case iro_Proj: {
684     ir_node *pred = get_Proj_pred(n);
685
686     if (get_irn_opcode(pred) == iro_Cond
687         && get_Proj_proj(n) == get_Cond_defaultProj(pred)
688         && get_irn_mode(get_Cond_selector(pred)) != mode_b)
689       fprintf (F, "defProj");
690     else
691       goto default_case;
692   } break;
693   case iro_Start:
694   case iro_End:
695   case iro_EndExcept:
696   case iro_EndReg: {
697     if (get_interprocedural_view()) {
698       fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
699       break;
700     } else
701       goto default_case;
702   }
703   case iro_CallBegin: {
704     ir_node *addr = get_CallBegin_ptr(n);
705     entity *ent = NULL;
706     if (get_irn_op(addr) == op_Sel)
707       ent = get_Sel_entity(addr);
708     else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
709       ent = get_SymConst_entity(addr);
710     fprintf (F, "%s", get_irn_opname(n));
711     if (ent) fprintf (F, " %s", get_entity_name(ent));
712     break;
713   }
714   case iro_Load:
715     fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
716     break;
717   case iro_Block:
718     fprintf (F, "%s%s", is_Block_dead(n) ? "Dead " : "", get_irn_opname(n));
719     break;
720
721   default:
722 default_case:
723     fprintf (F, "%s", get_irn_opname(n));
724
725   }  /* end switch */
726   return bad;
727 }
728
729 /**
730  * Dump the mode of a node n to a file F.
731  * Ignore modes that are "always known".
732  */
733 static int dump_node_mode(FILE *F, ir_node *n)
734 {
735   int bad = 0;
736   const ir_op_ops *ops = get_op_ops(get_irn_op(n));
737   opcode iro;
738
739   /* call the dump_node operation if available */
740   if (ops->dump_node)
741     return ops->dump_node(n, F, dump_node_mode_txt);
742
743   /* default implementation */
744   iro = get_irn_opcode(n);
745   switch (iro) {
746     case iro_SymConst:
747     case iro_Sel:
748     case iro_End:
749     case iro_Return:
750     case iro_Free:
751     case iro_Sync:
752     case iro_Jmp:
753     case iro_NoMem:
754       break;
755     default: {
756       ir_mode *mode = get_irn_mode(n);
757
758       if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
759           (mode != mode_T || iro == iro_Proj))
760         fprintf(F, "%s", get_mode_name_ex(mode, &bad));
761     }
762   }
763
764   return bad;
765 }
766
767 /**
768  * Dump the type of a node n to a file F if it's known.
769  */
770 static int dump_node_typeinfo(FILE *F, ir_node *n) {
771   int bad = 0;
772
773   if (opt_dump_analysed_type_info) {
774     if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent  ||
775         get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
776       ir_type *tp = get_irn_typeinfo_type(n);
777       if (tp != firm_none_type)
778         fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
779       else
780         fprintf(F, "[] ");
781     }
782   }
783   return bad;
784 }
785
786 typedef struct _pns_lookup {
787   long       nr;      /**< the proj number */
788   const char *name;   /**< the name of the Proj */
789 } pns_lookup_t;
790
791 typedef struct _proj_lookup {
792   opcode             code;      /**< the opcode of the Proj predecessor */
793   unsigned           num_data;  /**< number of data entries */
794   const pns_lookup_t *data;     /**< the data */
795 } proj_lookup_t;
796
797 #define ARR_SIZE(a)       (sizeof(a)/sizeof(a[0]))
798
799 /** the lookup table for Proj(Start) names */
800 static const pns_lookup_t start_lut[] = {
801 #define X(a)    { pn_Start_##a, #a }
802   X(X_initial_exec),
803   X(P_frame_base),
804   X(P_globals),
805   X(T_args),
806   X(P_value_arg_base)
807 #undef X
808 };
809
810 /** the lookup table for Proj(Cond) names */
811 static const pns_lookup_t cond_lut[] = {
812 #define X(a)    { pn_Cond_##a, #a }
813   X(false),
814   X(true)
815 #undef X
816 };
817
818 /** the lookup table for Proj(Call) names */
819 static const pns_lookup_t call_lut[] = {
820 #define X(a)    { pn_Call_##a, #a }
821   X(M_regular),
822   X(T_result),
823   X(P_value_res_base),
824   X(X_except),
825   X(M_except)
826 #undef X
827 };
828
829 /** the lookup table for Proj(Quot) names */
830 static const pns_lookup_t quot_lut[] = {
831 #define X(a)    { pn_Quot_##a, #a }
832   X(M),
833   X(X_except),
834   X(res)
835 #undef X
836 };
837
838 /** the lookup table for Proj(DivMod) names */
839 static const pns_lookup_t divmod_lut[] = {
840 #define X(a)    { pn_DivMod_##a, #a }
841   X(M),
842   X(X_except),
843   X(res_div),
844   X(res_mod)
845 #undef X
846 };
847
848 /** the lookup table for Proj(Div) names */
849 static const pns_lookup_t div_lut[] = {
850 #define X(a)    { pn_Div_##a, #a }
851   X(M),
852   X(X_except),
853   X(res)
854 #undef X
855 };
856
857 /** the lookup table for Proj(Mod) names */
858 static const pns_lookup_t mod_lut[] = {
859 #define X(a)    { pn_Mod_##a, #a }
860   X(M),
861   X(X_except),
862   X(res)
863 #undef X
864 };
865
866 /** the lookup table for Proj(Load) names */
867 static const pns_lookup_t load_lut[] = {
868 #define X(a)    { pn_Load_##a, #a }
869   X(M),
870   X(X_except),
871   X(res)
872 #undef X
873 };
874
875 /** the lookup table for Proj(Store) names */
876 static const pns_lookup_t store_lut[] = {
877 #define X(a)    { pn_Store_##a, #a }
878   X(M),
879   X(X_except)
880 #undef X
881 };
882
883 /** the lookup table for Proj(Alloc) names */
884 static const pns_lookup_t alloc_lut[] = {
885 #define X(a)    { pn_Alloc_##a, #a }
886   X(M),
887   X(X_except),
888   X(res)
889 #undef X
890 };
891
892 /** the lookup table for Proj(CopyB) names */
893 static const pns_lookup_t copyb_lut[] = {
894 #define X(a)    { pn_CopyB_##a, #a }
895   X(M),
896   X(X_except),
897   X(M_except)
898 #undef X
899 };
900
901 /** the lookup table for Proj(InstOf) names */
902 static const pns_lookup_t instof_lut[] = {
903 #define X(a)    { pn_InstOf_##a, #a }
904   X(M),
905   X(X_except),
906   X(res),
907   X(M_except),
908 #undef X
909 };
910
911 /** the lookup table for Proj(Raise) names */
912 static const pns_lookup_t raise_lut[] = {
913 #define X(a)    { pn_Raise_##a, #a }
914   X(M),
915   X(X),
916 #undef X
917 };
918
919 /** the lookup table for Proj(Bound) names */
920 static const pns_lookup_t bound_lut[] = {
921 #define X(a)    { pn_Bound_##a, #a }
922   X(M),
923   X(X_except),
924   X(res),
925   X(M_except)
926 #undef X
927 };
928
929 /** the Proj lookup table */
930 static const proj_lookup_t proj_lut[] = {
931 #define E(a)  ARR_SIZE(a), a
932   { iro_Start,   E(start_lut) },
933   { iro_Cond,    E(cond_lut) },
934   { iro_Call,    E(call_lut) },
935   { iro_Quot,    E(quot_lut) },
936   { iro_DivMod,  E(divmod_lut) },
937   { iro_Div,     E(div_lut) },
938   { iro_Mod,     E(mod_lut) },
939   { iro_Load,    E(load_lut) },
940   { iro_Store,   E(store_lut) },
941   { iro_Alloc,   E(alloc_lut) },
942   { iro_CopyB,   E(copyb_lut) },
943   { iro_InstOf,  E(instof_lut) },
944   { iro_Raise,   E(raise_lut) },
945   { iro_Bound,   E(bound_lut) }
946 #undef E
947 };
948
949 /**
950  * Dump additional node attributes of some nodes to a file F.
951  */
952 static int
953 dump_node_nodeattr(FILE *F, ir_node *n)
954 {
955   int bad = 0;
956   ir_node *pred;
957   opcode code;
958   long proj_nr;
959   const ir_op_ops *ops = get_op_ops(get_irn_op(n));
960
961   /* call the dump_node operation if available */
962   if (ops->dump_node)
963     return ops->dump_node(n, F, dump_node_nodeattr_txt);
964
965   switch (get_irn_opcode(n)) {
966   case iro_Start:
967     if (0 && get_interprocedural_view()) {
968       fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
969     }
970     break;
971
972   case iro_Proj:
973     pred    = get_Proj_pred(n);
974     proj_nr = get_Proj_proj(n);
975 handle_lut:
976     code    = get_irn_opcode(pred);
977
978     if (code == iro_Cmp)
979       fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
980     else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
981       fprintf (F, "Arg %ld ", proj_nr);
982     else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
983       fprintf (F, "%ld ", proj_nr);
984     else {
985       unsigned i, j, f = 0;
986
987       for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
988         if (code == proj_lut[i].code) {
989           for (j = 0; j < proj_lut[i].num_data; ++j) {
990             if (proj_nr == proj_lut[i].data[j].nr) {
991               fprintf (F, "%s ", proj_lut[i].data[j].name);
992               f = 1;
993               break;
994             }
995           }
996           break;
997         }
998       }
999       if (! f)
1000         fprintf (F, "%ld ", proj_nr);
1001       if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
1002         if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
1003           fprintf(F, "PRED ");
1004         if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
1005           fprintf(F, "PRED ");
1006       }
1007     }
1008     break;
1009   case iro_Filter:
1010     proj_nr = get_Filter_proj(n);
1011     if (! get_interprocedural_view()) {
1012       /* it's a Proj' */
1013       pred    = get_Filter_pred(n);
1014       goto handle_lut;
1015     }
1016     else
1017       fprintf (F, "%ld ", proj_nr);
1018     break;
1019   case iro_Sel:
1020     fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
1021     break;
1022   case iro_Cast:
1023     fprintf (F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
1024     break;
1025   case iro_Confirm:
1026     fprintf (F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
1027     break;
1028   case iro_CopyB:
1029     fprintf (F, "(%s) ", get_type_name_ex(get_CopyB_type(n), &bad));
1030     break;
1031
1032   default:
1033     ;
1034   } /* end switch */
1035
1036   return bad;
1037 }
1038
1039 #include <math.h>
1040 #include "execution_frequency.h"
1041 #include "callgraph.h"
1042
1043 void dump_node_ana_vals(FILE *F, ir_node *n) {
1044   return;
1045   fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
1046           get_irn_exec_freq(n),
1047           get_irg_method_execution_frequency(get_irn_irg(n)),
1048           pow(5, get_irg_recursion_depth(get_irn_irg(n))),
1049           get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
1050           );
1051 }
1052
1053
1054 /* Dumps a node label without the enclosing ". */
1055 int dump_node_label(FILE *F, ir_node *n) {
1056   int bad = 0;
1057
1058   bad |= dump_node_opcode(F, n);
1059   bad |= dump_node_mode(F, n);
1060   fprintf (F, " ");
1061   bad |= dump_node_typeinfo(F, n);
1062   bad |= dump_node_nodeattr(F, n);
1063   fprintf(F, "%ld", get_irn_node_nr(n));
1064
1065   return bad;
1066 }
1067
1068
1069 /**
1070  * Dumps the attributes of a node n into the file F.
1071  * Currently this is only the color of a node.
1072  */
1073 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
1074 {
1075   ir_node *n;
1076
1077   if (bad) {
1078     print_vcg_color(F, ird_color_red);
1079     return;
1080   }
1081
1082   if (dump_node_vcgattr_hook)
1083     if (dump_node_vcgattr_hook(F, node, local))
1084       return;
1085
1086   n = local ? local : node;
1087
1088   if (overrule_nodecolor != ird_color_default) {
1089     print_vcg_color(F, overrule_nodecolor);
1090     return;
1091   }
1092
1093   switch (get_irn_opcode(n)) {
1094   case iro_Start:
1095   case iro_EndReg:
1096     /* fall through */
1097   case iro_EndExcept:
1098     /* fall through */
1099   case iro_End:
1100     print_vcg_color(F, ird_color_blue);
1101     break;
1102   case iro_Block:
1103     if (is_Block_dead(n))
1104       print_vcg_color(F, ird_color_lightred);
1105     else
1106       print_vcg_color(F, ird_color_lightyellow);
1107     break;
1108   case iro_Phi:
1109     print_vcg_color(F, ird_color_green);
1110     break;
1111   case iro_Mux:
1112   case iro_Psi:
1113     print_vcg_color(F, ird_color_gold);
1114     break;
1115   case iro_Const:
1116   case iro_Proj:
1117   case iro_Filter:
1118   case iro_Tuple:
1119     print_vcg_color(F, ird_color_yellow);
1120     break;
1121   default:
1122     PRINT_DEFAULT_NODE_ATTR;
1123   }
1124 }
1125
1126
1127 /**
1128  * Dump the node information of a node n to a file F.
1129  */
1130 static INLINE int dump_node_info(FILE *F, ir_node *n)
1131 {
1132   int bad = 0;
1133   const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1134
1135   fprintf (F, " info1: \"");
1136   bad = dump_irnode_to_file(F, n);
1137   /* call the dump_node operation if available */
1138   if (ops->dump_node)
1139     bad = ops->dump_node(n, F, dump_node_info_txt);
1140   fprintf(F, "\"\n");
1141
1142   return bad;
1143 }
1144
1145 /**
1146  * checks whether a node is "constant-like" ie can be treated "block-less"
1147  */
1148 static INLINE
1149 int is_constlike_node(ir_node *n) {
1150   ir_op *op = get_irn_op(n);
1151   return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
1152 }
1153
1154
1155 /** outputs the predecessors of n, that are constants, local.  I.e.,
1156    generates a copy of the constant predecessors for each node called with. */
1157 static void dump_const_node_local(FILE *F, ir_node *n) {
1158   int i;
1159   if (!get_opt_dump_const_local()) return;
1160
1161   /* Use visited flag to avoid outputting nodes twice.
1162      initialize it first. */
1163   for (i = 0; i < get_irn_arity(n); i++) {
1164     ir_node *con = get_irn_n(n, i);
1165     if (is_constlike_node(con)) {
1166       set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1167     }
1168   }
1169
1170   for (i = 0; i < get_irn_arity(n); i++) {
1171     ir_node *con = get_irn_n(n, i);
1172     if (is_constlike_node(con) && irn_not_visited(con)) {
1173       int bad = 0;
1174
1175       mark_irn_visited(con);
1176       /* Generate a new name for the node by appending the names of
1177          n and const. */
1178       fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1179       fprintf(F, " label: \"");
1180       bad |= dump_node_label(F, con);
1181       fprintf(F, "\" ");
1182       bad |= dump_node_info(F, con);
1183       dump_node_vcgattr(F, n, con, bad);
1184       fprintf(F, "}\n");
1185     }
1186   }
1187 }
1188
1189 /** If the block of an edge is a const_like node, dump it local with an edge */
1190 static void dump_const_block_local(FILE *F, ir_node *n) {
1191   ir_node *blk;
1192
1193   if (!get_opt_dump_const_local()) return;
1194
1195   blk = get_nodes_block(n);
1196   if (is_constlike_node(blk)) {
1197     int bad = 0;
1198
1199     /* Generate a new name for the node by appending the names of
1200        n and blk. */
1201     fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1202     fprintf(F, "\" label: \"");
1203     bad |= dump_node_label(F, blk);
1204     fprintf(F, "\" ");
1205     bad |= dump_node_info(F, blk);
1206     dump_node_vcgattr(F, n, blk, bad);
1207     fprintf(F, "}\n");
1208
1209     fprintf (F, "edge: { sourcename: \"");
1210     PRINT_NODEID(n);
1211     fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1212
1213     if (dump_edge_vcgattr_hook) {
1214       fprintf (F, "\" ");
1215       if (dump_edge_vcgattr_hook(F, n, -1)) {
1216         fprintf (F, "}\n");
1217         return;
1218       }
1219       else {
1220         fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1221         return;
1222       }
1223     }
1224
1225     fprintf (F, "\" "   BLOCK_EDGE_ATTR "}\n");
1226   }
1227 }
1228
1229 /**
1230  * prints the error message of a node to a file F as info2.
1231  */
1232 static void INLINE print_node_error(FILE *F, const char *err_msg)
1233 {
1234   if (! err_msg)
1235     return;
1236
1237   fprintf (F, " info2: \"%s\"", err_msg);
1238 }
1239
1240 /**
1241  * prints debug messages of a node to file F as info3.
1242  */
1243 static void print_dbg_info(FILE *F, dbg_info *dbg)
1244 {
1245   char buf[1024];
1246
1247   if (__dbg_info_snprint) {
1248     buf[0] = '\0';
1249     if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1250       fprintf (F, " info3: \"%s\"\n", buf);
1251   }
1252 }
1253
1254 /**
1255  * Dump a node
1256  */
1257 static void dump_node(FILE *F, ir_node *n)
1258 {
1259   int bad = 0;
1260   const char *p;
1261
1262   if (get_opt_dump_const_local() && is_constlike_node(n))
1263     return;
1264
1265   /* dump this node */
1266   fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1267
1268   bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1269   bad |= dump_node_label(F, n);
1270   dump_node_ana_vals(F, n);
1271   //dump_node_ana_info(F, n);
1272   fprintf(F, "\" ");
1273   bad |= dump_node_info(F, n);
1274   print_node_error(F, p);
1275   print_dbg_info(F, get_irn_dbg_info(n));
1276   dump_node_vcgattr(F, n, NULL, bad);
1277   fprintf(F, "}\n");
1278   dump_const_node_local(F, n);
1279
1280   if(dump_node_edge_hook)
1281     dump_node_edge_hook(F, n);
1282 #if DO_HEAPANALYSIS
1283   dump_irn_chi_term(F, n);
1284   dump_irn_state(F, n);
1285 #endif
1286 }
1287
1288 /** dump the edge to the block this node belongs to */
1289 static void
1290 dump_ir_block_edge(FILE *F, ir_node *n)  {
1291   if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1292   if (is_no_Block(n)) {
1293     ir_node *block = get_nodes_block(n);
1294
1295     if (get_opt_dump_const_local() && is_constlike_node(block)) {
1296       dump_const_block_local(F, n);
1297     }
1298     else {
1299       fprintf (F, "edge: { sourcename: \"");
1300       PRINT_NODEID(n);
1301       fprintf (F, "\" targetname: ");
1302       fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1303
1304       if (dump_edge_vcgattr_hook) {
1305         fprintf (F, " ");
1306         if (dump_edge_vcgattr_hook(F, n, -1)) {
1307           fprintf (F, "}\n");
1308           return;
1309         }
1310         else {
1311           fprintf (F, " "  BLOCK_EDGE_ATTR "}\n");
1312           return;
1313         }
1314       }
1315
1316       fprintf (F, " "   BLOCK_EDGE_ATTR "}\n");
1317     }
1318   }
1319 }
1320
1321 static void
1322 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1323   /*
1324    * do not use get_nodes_block() here, will fail
1325    * if the irg is not pinned.
1326    */
1327   if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1328     fprintf (F, INTRA_DATA_EDGE_ATTR);
1329   else
1330     fprintf (F, INTER_DATA_EDGE_ATTR);
1331 }
1332
1333 static void
1334 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1335   /*
1336    * do not use get_nodes_block() here, will fail
1337    * if the irg is not pinned.
1338    */
1339   if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1340     fprintf (F, INTRA_MEM_EDGE_ATTR);
1341   else
1342     fprintf (F, INTER_MEM_EDGE_ATTR);
1343 }
1344
1345 static void
1346 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1347   assert(from);
1348
1349   if (dump_edge_vcgattr_hook)
1350     if (dump_edge_vcgattr_hook(F, from, to))
1351       return;
1352
1353   if (dump_backedge_information_flag && is_backedge(from, to))
1354     fprintf (F, BACK_EDGE_ATTR);
1355
1356   switch (get_irn_opcode(from)) {
1357   case iro_Block:
1358     fprintf (F, CF_EDGE_ATTR);
1359     break;
1360   case iro_Start:  break;
1361   case iro_End:
1362     if (to >= 0) {
1363       if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1364     fprintf (F, CF_EDGE_ATTR);
1365       if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1366     fprintf (F, INTER_MEM_EDGE_ATTR);
1367     }
1368     break;
1369   default:
1370     if (is_Proj(from)) {
1371       if (get_irn_mode(from) == mode_M)
1372         print_mem_edge_vcgattr(F, from, to);
1373       else if (get_irn_mode(from) == mode_X)
1374         fprintf(F, CF_EDGE_ATTR);
1375       else
1376         print_data_edge_vcgattr(F, from, to);
1377     }
1378     else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1379       print_mem_edge_vcgattr(F, from, to);
1380     else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1381       fprintf (F, CF_EDGE_ATTR);
1382     else
1383       print_data_edge_vcgattr(F, from, to);
1384   }
1385 }
1386
1387 /* dump edges to our inputs */
1388 static void
1389 dump_ir_data_edges(FILE *F, ir_node *n)  {
1390   int i;
1391   unsigned long visited = get_irn_visited(n);
1392
1393   if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1394     return;
1395
1396   for (i = 0; i < get_irn_arity(n); i++) {
1397     ir_node * pred = get_irn_n(n, i);
1398     assert(pred);
1399
1400     if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1401       continue; /* pred not dumped */
1402
1403     if (dump_backedge_information_flag && is_backedge(n, i))
1404       fprintf (F, "backedge: {sourcename: \"");
1405     else
1406       fprintf (F, "edge: {sourcename: \"");
1407     PRINT_NODEID(n);
1408     fprintf (F, "\" targetname: ");
1409     if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1410       PRINT_CONSTID(n, pred);
1411     } else {
1412       fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1413     }
1414     fprintf (F, " label: \"%d\" ", i);
1415     print_edge_vcgattr(F, n, i);
1416     fprintf (F, "}\n");
1417   }
1418 }
1419
1420 /** Dumps a node and its edges but not the block edge
1421  */
1422 static INLINE void
1423 dump_node_wo_blockedge (ir_node *n, void *env) {
1424   FILE *F = env;
1425   dump_node(F, n);
1426   dump_ir_data_edges(F, n);
1427 }
1428
1429 /** Dumps a node and its edges.
1430  */
1431 static void
1432 dump_whole_node (ir_node *n, void *env) {
1433   FILE *F = env;
1434   dump_node_wo_blockedge(n, env);
1435   if (!node_floats(n)) dump_ir_block_edge(F, n);
1436 }
1437
1438 static void
1439 dump_const_node(ir_node *n, void *env) {
1440   if (is_Block(n)) return;
1441   dump_node_wo_blockedge(n, env);
1442 }
1443
1444 /***********************************************************************/
1445 /* the following routines dump the nodes/irgs bracketed to graphs.     */
1446 /***********************************************************************/
1447
1448 /** Dumps a constant expression as entity initializer, array bound ...
1449  */
1450 static void dump_const_expression(FILE *F, ir_node *value) {
1451   ir_graph *rem = current_ir_graph;
1452   int rem_dump_const_local = dump_const_local;
1453   dump_const_local = 0;
1454   current_ir_graph = get_const_code_irg();
1455   irg_walk(value, dump_const_node, NULL, F);
1456   /* Decrease visited flag so that we walk with the same flag for the next
1457      expression.  This guarantees that we don't dump the same node twice,
1458      as for const expressions cse is performed to save memory. */
1459   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1460   current_ir_graph = rem;
1461   dump_const_local = rem_dump_const_local;
1462 }
1463
1464 /** Dump a block as graph containing its nodes.
1465  *
1466  *  Expects to find nodes belonging to the block as list in its
1467  *  link field.
1468  *  Dumps the edges of all nodes including itself. */
1469 static void
1470 dump_whole_block(FILE *F, ir_node *block) {
1471   ir_node *node;
1472   dumper_colors color = ird_color_yellow;
1473
1474   assert(is_Block(block));
1475
1476   fprintf(F, "graph: { title: \"");
1477   PRINT_NODEID(block);
1478   fprintf(F, "\"  label: \"");
1479   dump_node_label(F, block);
1480 #if DO_HEAPANALYSIS
1481   if (get_opt_dump_abstvals())
1482     fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1483 #endif
1484
1485   /* colorize blocks */
1486   if (! get_Block_matured(block))
1487     color = ird_color_red;
1488   if (is_Block_dead(block))
1489     color = ird_color_orange;
1490
1491   fprintf(F, "\" status:clustered ");
1492   print_vcg_color(F, color);
1493   fprintf(F, "\n");
1494
1495   /* yComp can show attributes for blocks, XVCG parses but ignores them */
1496   dump_node_info(F, block);
1497   print_dbg_info(F, get_irn_dbg_info(block));
1498
1499   /* dump the blocks edges */
1500   dump_ir_data_edges(F, block);
1501
1502   /* dump the nodes that go into the block */
1503   for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1504     dump_node(F, node);
1505     dump_ir_data_edges(F, node);
1506   }
1507
1508   /* Close the vcg information for the block */
1509   fprintf(F, "}\n");
1510   dump_const_node_local(F, block);
1511 #if DO_HEAPANALYSIS
1512   dump_irn_chi_term(F, block);
1513 #endif
1514   fprintf(F, "\n");
1515 }
1516
1517 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1518  *  The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1519 static void
1520 dump_block_graph(FILE *F, ir_graph *irg) {
1521   int i;
1522   ir_graph *rem = current_ir_graph;
1523   ir_node **arr = ird_get_irg_link(irg);
1524   current_ir_graph = irg;
1525
1526   for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1527     ir_node * node = arr[i];
1528     if (is_Block(node)) {
1529       /* Dumps the block and all the nodes in the block, which are to
1530          be found in Block->link. */
1531       dump_whole_block(F, node);
1532     } else {
1533       /* Nodes that are not in a Block. */
1534       dump_node(F, node);
1535       if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1536         dump_const_block_local(F, node);
1537       }
1538       dump_ir_data_edges(F, node);
1539     }
1540   }
1541
1542   if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1543     dump_loop_nodes_into_graph(F, irg);
1544
1545   current_ir_graph = rem;
1546 }
1547
1548 /**
1549  * Dump the info for an irg.
1550  * Parsed by XVCG but not shown. use yComp.
1551  */
1552 static void dump_graph_info(FILE *F, ir_graph *irg) {
1553   fprintf(F, "info1: \"");
1554   dump_entity_to_file(F, get_irg_entity(irg), dump_verbosity_entattrs | dump_verbosity_entconsts);
1555   fprintf(F, "\"\n");
1556 }
1557
1558 /** Dumps an irg as a graph clustered by block nodes.
1559  *  If interprocedural view edges can point to nodes out of this graph.
1560  */
1561 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1562   entity *ent = get_irg_entity(irg);
1563
1564   fprintf(F, "graph: { title: \"");
1565   PRINT_IRGID(irg);
1566   fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1567       get_ent_dump_name(ent));
1568
1569   dump_graph_info(F, irg);
1570   print_dbg_info(F, get_entity_dbg_info(ent));
1571
1572   dump_block_graph(F, irg);
1573
1574   /* Close the vcg information for the irg */
1575   fprintf(F, "}\n\n");
1576 }
1577
1578 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1579  *  The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1580 static void
1581 dump_extblock_graph(FILE *F, ir_graph *irg) {
1582   int i;
1583   ir_graph *rem = current_ir_graph;
1584   ir_extblk **arr = ird_get_irg_link(irg);
1585   current_ir_graph = irg;
1586
1587   for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1588     ir_extblk *extbb = arr[i];
1589     ir_node *leader = get_extbb_leader(extbb);
1590     int j;
1591
1592     fprintf(F, "graph: { title: \"");
1593     PRINT_EXTBBID(leader);
1594     fprintf(F, "\"  label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1595             get_irn_node_nr(leader));
1596
1597     for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1598       ir_node * node = extbb->blks[j];
1599       if (is_Block(node)) {
1600         /* Dumps the block and all the nodes in the block, which are to
1601            be found in Block->link. */
1602         dump_whole_block(F, node);
1603       } else {
1604         /* Nodes that are not in a Block. */
1605         dump_node(F, node);
1606         if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1607           dump_const_block_local(F, node);
1608         }
1609         dump_ir_data_edges(F, node);
1610       }
1611     }
1612     fprintf(F, "}\n");
1613   }
1614
1615   if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1616     dump_loop_nodes_into_graph(F, irg);
1617
1618   current_ir_graph = rem;
1619   free_extbb(irg);
1620 }
1621
1622
1623 /*******************************************************************/
1624 /* Basic type and entity nodes and edges.                          */
1625 /*******************************************************************/
1626
1627 /** dumps the edges between nodes and their type or entity attributes. */
1628 static void dump_node2type_edges(ir_node *n, void *env)
1629 {
1630   FILE *F = env;
1631   assert(n);
1632
1633   switch (get_irn_opcode(n)) {
1634   case iro_Const :
1635     /* @@@ some consts have an entity */
1636     break;
1637   case iro_SymConst:
1638     if (   (get_SymConst_kind(n) ==symconst_type_tag)
1639        || (get_SymConst_kind(n) ==symconst_size))
1640       {
1641         print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1642       }
1643     break;
1644   case iro_Sel: {
1645       print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1646     } break;
1647   case iro_Call: {
1648       print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1649     } break;
1650   case iro_Alloc: {
1651       print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1652     } break;
1653   case iro_Free: {
1654       print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1655     } break;
1656   case iro_Cast: {
1657       print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1658     } break;
1659   default:
1660     break;
1661   }
1662 }
1663
1664 #if 0
1665 static int print_type_info(FILE *F, ir_type *tp) {
1666   int bad = 0;
1667
1668   if (get_type_state(tp) == layout_undefined) {
1669     fprintf(F, "state: layout_undefined\n");
1670   } else {
1671     fprintf(F, "state: layout_fixed,\n");
1672   }
1673   if (get_type_mode(tp))
1674     fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1675   fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1676
1677   return bad;
1678 }
1679
1680 static void print_typespecific_info(FILE *F, ir_type *tp) {
1681   switch (get_type_tpop_code(tp)) {
1682   case tpo_class:
1683     {
1684       fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1685     } break;
1686   case tpo_struct:
1687     {
1688     } break;
1689   case tpo_method:
1690     {
1691       fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1692       fprintf(F, "params: %d\n", get_method_n_params(tp));
1693       fprintf(F, "results: %d\n", get_method_n_ress(tp));
1694     } break;
1695   case tpo_union:
1696     {
1697     } break;
1698   case tpo_array:
1699     {
1700     } break;
1701   case tpo_enumeration:
1702     {
1703     } break;
1704   case tpo_pointer:
1705     {
1706     } break;
1707   case tpo_primitive:
1708     {
1709     } break;
1710   default: break;
1711   } /* switch type */
1712 }
1713 #endif
1714
1715 static void print_typespecific_vcgattr(FILE *F, ir_type *tp) {
1716   switch (get_type_tpop_code(tp)) {
1717   case tpo_class:
1718     {
1719       if (peculiarity_existent == get_class_peculiarity(tp))
1720     fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1721       else
1722     fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1723     } break;
1724   case tpo_struct:
1725     {
1726       fprintf (F, " " TYPE_METH_NODE_ATTR);
1727     } break;
1728   case tpo_method:
1729     {
1730     } break;
1731   case tpo_union:
1732     {
1733     } break;
1734   case tpo_array:
1735     {
1736     } break;
1737   case tpo_enumeration:
1738     {
1739     } break;
1740   case tpo_pointer:
1741     {
1742     } break;
1743   case tpo_primitive:
1744     {
1745     } break;
1746   default: break;
1747   } /* switch type */
1748 }
1749
1750
1751 int dump_type_node(FILE *F, ir_type *tp)
1752 {
1753   int bad = 0;
1754
1755   fprintf (F, "node: {title: ");
1756   PRINT_TYPEID(tp);
1757   fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1758   fprintf (F, " info1: \"");
1759 #if 0
1760   bad |= print_type_info(F, tp);
1761   print_typespecific_info(F, tp);
1762 #else
1763   dump_type_to_file(F, tp, dump_verbosity_max);
1764 #endif
1765   fprintf (F, "\"\n");
1766   print_dbg_info(F, get_type_dbg_info(tp));
1767   print_typespecific_vcgattr(F, tp);
1768   fprintf (F, "}\n");
1769
1770   return bad;
1771 }
1772
1773
1774 #define X(a)    case a: fprintf(F, #a); break
1775 void dump_entity_node(FILE *F, entity *ent, int color)
1776 {
1777   fprintf (F, "node: {title: \"");
1778   PRINT_ENTID(ent); fprintf(F, "\"");
1779   fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1780   fprintf (F, "label: ");
1781   fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1782   if (color)
1783     fprintf(F, "color:%d", color);
1784   else
1785     fprintf (F, ENTITY_NODE_ATTR);
1786   fprintf (F, "\n info1: \"");
1787
1788   dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1789
1790   fprintf(F, "\"\n");
1791   print_dbg_info(F, get_entity_dbg_info(ent));
1792   fprintf(F, "}\n");
1793 }
1794 #undef X
1795
1796 static void dump_enum_item(FILE *F, ir_type *tp, int pos)
1797 {
1798   char buf[1024];
1799   ident *id  = get_enumeration_nameid(tp, pos);
1800   tarval *tv = get_enumeration_enum(tp, pos);
1801
1802   tarval_snprintf(buf, sizeof(buf), tv);
1803   fprintf (F, "node: {title: \"");
1804   PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1805   fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1806   fprintf (F, "label: ");
1807   fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1808   fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1809 }
1810
1811 /* dumps a type or entity and it's edges. */
1812 static void
1813 dump_type_info(type_or_ent *tore, void *env) {
1814   FILE *F = env;
1815   int i = 0;  /* to shutup gcc */
1816
1817   /* dump this type or entity */
1818
1819   switch (get_kind(tore)) {
1820   case k_entity:
1821     {
1822       entity *ent = (entity *)tore;
1823       ir_node *value;
1824       /* The node */
1825       dump_entity_node(F, ent, 0);
1826       /* The Edges */
1827       /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
1828       fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1829                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1830       print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1831       if (is_Class_type(get_entity_owner(ent))) {
1832         for(i = 0; i < get_entity_n_overwrites(ent); i++)
1833           print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1834       }
1835       /* attached subgraphs */
1836       if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1837         if (is_atomic_entity(ent)) {
1838           value = get_atomic_ent_value(ent);
1839           if (value) {
1840             print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1841             /* DDMN(value);  $$$ */
1842             dump_const_expression(F, value);
1843           }
1844         }
1845         if (is_compound_entity(ent)) {
1846           for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1847             value = get_compound_ent_value(ent, i);
1848             if (value) {
1849               print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1850               dump_const_expression(F, value);
1851               print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1852               /*
1853               fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1854               ENT_CORR_EDGE_ATTR  "}\n", GET_ENTID(ent),
1855               get_compound_ent_value_member(ent, i), i);
1856               */
1857             }
1858           }
1859         }
1860       }
1861     } break;
1862   case k_type:
1863     {
1864       ir_type *tp = (ir_type *)tore;
1865       dump_type_node(F, tp);
1866       /* and now the edges */
1867       switch (get_type_tpop_code(tp)) {
1868       case tpo_class:
1869         {
1870           for (i=0; i < get_class_n_supertypes(tp); i++)
1871             print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1872           for (i=0; i < get_class_n_members(tp); i++)
1873             print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1874         } break;
1875       case tpo_struct:
1876         {
1877           for (i=0; i < get_struct_n_members(tp); i++)
1878             print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1879         } break;
1880       case tpo_method:
1881         {
1882           for (i = 0; i < get_method_n_params(tp); i++)
1883             print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1884           for (i = 0; i < get_method_n_ress(tp); i++)
1885             print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1886         } break;
1887       case tpo_union:
1888         {
1889           for (i = 0; i < get_union_n_members(tp); i++)
1890             print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1891         } break;
1892       case tpo_array:
1893         {
1894           print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1895           print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1896           for (i = 0; i < get_array_n_dimensions(tp); i++) {
1897             ir_node *upper = get_array_upper_bound(tp, i);
1898             ir_node *lower = get_array_lower_bound(tp, i);
1899             print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1900             print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1901             dump_const_expression(F, upper);
1902             dump_const_expression(F, lower);
1903           }
1904
1905         } break;
1906       case tpo_enumeration:
1907         {
1908           for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1909             dump_enum_item(F, tp, i);
1910             print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1911           }
1912         } break;
1913       case tpo_pointer:
1914         {
1915           print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1916         } break;
1917       case tpo_primitive:
1918         {
1919         } break;
1920       default: break;
1921       } /* switch type */
1922     }
1923     break; /* case k_type */
1924   default:
1925     {
1926       printf(" *** irdump,  dump_type_info(l.%i), faulty type.\n", __LINE__);
1927     } break;
1928   } /* switch kind_or_entity */
1929 }
1930
1931 typedef struct _h_env {
1932   int dump_ent;
1933   FILE *f;
1934 } h_env_t;
1935
1936 /** For dumping class hierarchies.
1937  * Dumps a class type node and a superclass edge.
1938  * If env->dump_ent dumps entities of classes and overwrites edges.
1939  */
1940 static void
1941 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1942   h_env_t *env = ctx;
1943   FILE *F = env->f;
1944   int i = 0;  /* to shutup gcc */
1945
1946   /* dump this type or entity */
1947   switch (get_kind(tore)) {
1948   case k_entity: {
1949     entity *ent = (entity *)tore;
1950     if (get_entity_owner(ent) == get_glob_type()) break;
1951     if (!is_Method_type(get_entity_type(ent))) break;  /* GL */
1952     if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1953       /* The node */
1954       dump_entity_node(F, ent, 0);
1955       /* The edges */
1956       print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1957       for(i = 0; i < get_entity_n_overwrites(ent); i++)
1958         print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1959     }
1960   } break; /* case k_entity */
1961   case k_type:
1962     {
1963       ir_type *tp = (ir_type *)tore;
1964       if (tp == get_glob_type()) break;
1965       switch (get_type_tpop_code(tp)) {
1966         case tpo_class: {
1967           dump_type_node(F, tp);
1968           /* and now the edges */
1969           for (i=0; i < get_class_n_supertypes(tp); i++)
1970           {
1971               print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1972           }
1973         } break;
1974         default: break;
1975       } /* switch type */
1976     }
1977     break; /* case k_type */
1978   default:
1979     {
1980       printf(" *** irdump,  dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1981     } break;
1982   } /* switch kind_or_entity */
1983 }
1984
1985 /*******************************************************************/
1986 /* dump analysis information that is expressed in graph terms.     */
1987 /*******************************************************************/
1988
1989 /* dump out edges */
1990 static void
1991 dump_out_edge(ir_node *n, void *env) {
1992   FILE *F = env;
1993   int i;
1994   for (i = 0; i < get_irn_n_outs(n); i++) {
1995     assert(get_irn_out(n, i));
1996     fprintf (F, "edge: {sourcename: \"");
1997     PRINT_NODEID(n);
1998     fprintf (F, "\" targetname: \"");
1999     PRINT_NODEID(get_irn_out(n, i));
2000     fprintf (F, "\" color: red linestyle: dashed");
2001     fprintf (F, "}\n");
2002   }
2003 }
2004
2005 static INLINE void
2006 dump_loop_label(FILE *F, ir_loop *loop) {
2007   fprintf (F, "loop %d, %d sons, %d nodes",
2008        get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
2009 }
2010
2011 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
2012   fprintf (F, " info1: \"");
2013   fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
2014 #if DEBUG_libfirm   /* GL @@@ debug analyses */
2015   fprintf (F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
2016 #endif
2017   fprintf (F, "\"");
2018 }
2019
2020 static INLINE void
2021 dump_loop_node(FILE *F, ir_loop *loop) {
2022   fprintf (F, "node: {title: \"");
2023   PRINT_LOOPID(loop);
2024   fprintf (F, "\" label: \"");
2025   dump_loop_label(F, loop);
2026   fprintf (F, "\" ");
2027   dump_loop_info(F, loop);
2028   fprintf (F, "}\n");
2029
2030 }
2031
2032 static INLINE void
2033 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
2034   assert(loop);
2035   fprintf (F, "edge: {sourcename: \"");
2036   PRINT_LOOPID(loop);
2037   fprintf (F, "\" targetname: \"");
2038   PRINT_NODEID(get_loop_node(loop, i));
2039   fprintf (F, "\" color: green");
2040   fprintf (F, "}\n");
2041 }
2042
2043 static INLINE void
2044 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
2045   assert(loop);
2046   fprintf (F, "edge: {sourcename: \"");
2047   PRINT_LOOPID(loop);
2048   fprintf (F, "\" targetname: \"");
2049   PRINT_LOOPID(get_loop_son(loop, i));
2050   fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
2051        get_loop_element_pos(loop, get_loop_son(loop, i)));
2052 }
2053
2054 static
2055 void dump_loops(FILE *F, ir_loop *loop) {
2056   int i;
2057   /* dump this loop node */
2058   dump_loop_node(F, loop);
2059
2060   /* dump edges to nodes in loop -- only if it is a real loop */
2061   if (get_loop_depth(loop) != 0) {
2062     for (i = 0; i < get_loop_n_nodes(loop); i++) {
2063       dump_loop_node_edge(F, loop, i);
2064     }
2065   }
2066   for (i = 0; i < get_loop_n_sons(loop); i++) {
2067     dump_loops(F, get_loop_son(loop, i));
2068     dump_loop_son_edge(F, loop, i);
2069   }
2070 }
2071
2072 static INLINE
2073 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
2074   ir_graph *rem = current_ir_graph;
2075   current_ir_graph = irg;
2076
2077   if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
2078
2079   current_ir_graph = rem;
2080 }
2081
2082
2083 /**
2084  * dumps the VCG header
2085  */
2086 void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
2087   char *label;
2088
2089   if (edge_label) {
2090     label = "yes";
2091   } else {
2092     label = "no";
2093   }
2094
2095   if (!orientation) orientation = "bottom_to_top";
2096
2097   /* print header */
2098   fprintf (F,
2099        "graph: { title: \"ir graph of %s\"\n"
2100        "display_edge_labels: %s\n"
2101        "layoutalgorithm: mindepth\n"
2102        "manhattan_edges: yes\n"
2103        "port_sharing: no\n"
2104        "orientation: %s\n"
2105        "classname 1:  \"intrablock Data\"\n"
2106        "classname 2:  \"Block\"\n"
2107        "classname 3:  \"Entity type\"\n"
2108        "classname 4:  \"Entity owner\"\n"
2109        "classname 5:  \"Method Param\"\n"
2110        "classname 6:  \"Method Res\"\n"
2111        "classname 7:  \"Super\"\n"
2112        "classname 8:  \"Union\"\n"
2113        "classname 9:  \"Points-to\"\n"
2114        "classname 10: \"Array Element Type\"\n"
2115        "classname 11: \"Overwrites\"\n"
2116        "classname 12: \"Member\"\n"
2117        "classname 13: \"Control Flow\"\n"
2118        "classname 14: \"intrablock Memory\"\n"
2119        "classname 15: \"Dominators\"\n"
2120        "classname 16: \"interblock Data\"\n"
2121        "classname 17: \"interblock Memory\"\n"
2122        "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2123        "classname 19: \"Postdominators\"\n"
2124        "infoname 1: \"Attribute\"\n"
2125        "infoname 2: \"Verification errors\"\n"
2126        "infoname 3: \"Debug info\"\n",
2127        name, label, orientation);
2128
2129   /* don't use all, the range is too whith/black. */
2130   n_colors   = 18;
2131   base_color = 105;
2132   fprintf (F,
2133        "colorentry 100:    0   0    0\n"
2134        "colorentry 101:   20   0    0\n"
2135        "colorentry 102:   40   0    0\n"
2136        "colorentry 103:   60   0    0\n"
2137        "colorentry 104:   80   0    0\n"
2138        "colorentry 105:  100   0    0\n"
2139        "colorentry 106:  120   0    0\n"
2140        "colorentry 107:  140   0    0\n"
2141        "colorentry 108:  150   0    0\n"
2142        "colorentry 109:  180   0    0\n"
2143        "colorentry 110:  200   0    0\n"
2144        "colorentry 111:  220   0    0\n"
2145        "colorentry 112:  240   0    0\n"
2146        "colorentry 113:  255   0    0\n"
2147        "colorentry 113:  255  20   20\n"
2148        "colorentry 114:  255  40   40\n"
2149        "colorentry 115:  255  60   60\n"
2150        "colorentry 116:  255  80   80\n"
2151        "colorentry 117:  255 100  100\n"
2152        "colorentry 118:  255 120  120\n"
2153        "colorentry 119:  255 140  140\n"
2154        "colorentry 120:  255 150  150\n"
2155        "colorentry 121:  255 180  180\n"
2156        "colorentry 122:  255 200  200\n"
2157        "colorentry 123:  255 220  220\n"
2158        "colorentry 124:  255 240  240\n"
2159        "colorentry 125:  255 250  250\n"
2160        );
2161
2162   fprintf (F, "\n");        /* a separator */
2163 }
2164
2165 /**
2166  * open a vcg file
2167  *
2168  * @param irg     The graph to be dumped
2169  * @param suffix1 first filename suffix
2170  * @param suffix2 second filename suffix
2171  */
2172 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
2173   FILE *F;
2174   const char *nm = get_irg_dump_name(irg);
2175   int len = strlen(nm), i, j;
2176   char *fname;  /* filename to put the vcg information in */
2177
2178   if (!suffix1) suffix1 = "";
2179   if (!suffix2) suffix2 = "";
2180
2181   /* open file for vcg graph */
2182   fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2183
2184   /* strncpy (fname, nm, len); */     /* copy the filename */
2185   j = 0;
2186   for (i = 0; i < len; ++i) {  /* replace '/' in the name: escape by @. */
2187     if (nm[i] == '/') {
2188       fname[j] = '@'; j++; fname[j] = '1'; j++;
2189     } else if (nm[i] == '@') {
2190       fname[j] = '@'; j++; fname[j] = '2'; j++;
2191     } else {
2192       fname[j] = nm[i]; j++;
2193     }
2194   }
2195   fname[j] = '\0';
2196   strcat (fname, suffix1);  /* append file suffix */
2197   strcat (fname, suffix2);  /* append file suffix */
2198   strcat (fname, ".vcg");   /* append the .vcg suffix */
2199
2200   /* vcg really expect only a <CR> at end of line, so
2201    * the "b"inary mode is what you mean (and even needed for Win32)
2202    */
2203   F = fopen (fname, "wb");  /* open file for writing */
2204   if (!F) {
2205     panic("cannot open %s for writing (%m)", fname);  /* not reached */
2206   }
2207   free(fname);
2208
2209   return F;
2210 }
2211
2212 /**
2213  * open a vcg file
2214  *
2215  * @param name    prefix file name
2216  * @param suffix  filename suffix
2217  */
2218 FILE *vcg_open_name (const char *name, const char *suffix) {
2219   FILE *F;
2220   char *fname;  /* filename to put the vcg information in */
2221   int i, j, len = strlen(name);
2222
2223   if (!suffix) suffix = "";
2224
2225   /** open file for vcg graph */
2226   fname = xmalloc(len * 2 + 5 + strlen(suffix));
2227   /* strcpy (fname, name);*/    /* copy the filename */
2228   j = 0;
2229   for (i = 0; i < len; ++i) {  /* replace '/' in the name: escape by @. */
2230     if (name[i] == '/') {
2231       fname[j] = '@'; j++; fname[j] = '1'; j++;
2232     } else if (name[i] == '@') {
2233       fname[j] = '@'; j++; fname[j] = '2'; j++;
2234     } else {
2235       fname[j] = name[i]; j++;
2236     }
2237   }
2238   fname[j] = '\0';
2239   strcat (fname, suffix);
2240   strcat (fname, ".vcg");  /* append the .vcg suffix */
2241
2242   /* vcg really expect only a <CR> at end of line, so
2243    * the "b"inary mode is what you mean (and even needed for Win32)
2244    */
2245   F = fopen (fname, "wb");  /* open file for writing */
2246   if (!F) {
2247     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
2248   }
2249   free(fname);
2250
2251   return F;
2252 }
2253
2254 /**
2255  * Dumps the vcg file footer
2256  */
2257 static INLINE void dump_vcg_footer (FILE *F) {
2258   fprintf (F, "}\n");
2259 }
2260
2261 /**
2262  * close the vcg file
2263  */
2264 void vcg_close (FILE *F) {
2265   dump_vcg_footer(F);    /* print footer */
2266   fclose (F);           /* close vcg file */
2267 }
2268
2269 /************************************************************************/
2270 /************************************************************************/
2271 /* Routines that dump all or parts of the firm representation to a file */
2272 /************************************************************************/
2273 /************************************************************************/
2274
2275 /************************************************************************/
2276 /* Dump ir graphs, different formats and additional information.        */
2277 /************************************************************************/
2278
2279 /** Routine to dump a graph, blocks as conventional nodes.  */
2280 void
2281 dump_ir_graph (ir_graph *irg, const char *suffix )
2282 {
2283   FILE *f;
2284   ir_graph *rem;
2285   char *suffix1;
2286   rem = current_ir_graph;
2287
2288   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2289
2290   current_ir_graph = irg;
2291   if (get_interprocedural_view()) suffix1 = "-pure-ip";
2292   else                            suffix1 = "-pure";
2293   f = vcg_open(irg, suffix, suffix1);
2294   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2295
2296   /* call the dump graph hook */
2297   if (dump_ir_graph_hook)
2298     if (dump_ir_graph_hook(f, irg))
2299       return;
2300
2301   /* walk over the graph */
2302   /* dump_whole_node must be called in post visiting predecessors */
2303   ird_walk_graph(irg, NULL, dump_whole_node, f);
2304
2305   /* dump the out edges in a separate walk */
2306   if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2307     irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2308   }
2309
2310   vcg_close(f);
2311
2312   current_ir_graph = rem;
2313 }
2314
2315 /* Dump a firm graph without explicit block nodes. */
2316 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2317 {
2318   FILE *f;
2319   int i;
2320   char *suffix1;
2321
2322   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2323     return;
2324
2325   if (get_interprocedural_view()) suffix1 = "-ip";
2326   else                            suffix1 = "";
2327   f = vcg_open(irg, suffix, suffix1);
2328   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2329
2330   construct_block_lists(irg);
2331
2332   /*
2333    * If we are in the interprocedural view, we dump not
2334    * only the requested irg but also all irgs that can be reached
2335    * from irg.
2336    */
2337   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2338     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2339     if (arr) {
2340       dump_graph_from_list(f, get_irp_irg(i));
2341       DEL_ARR_F(arr);
2342     }
2343   }
2344
2345   vcg_close(f);
2346 }
2347
2348 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2349 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2350 {
2351   FILE *F;
2352   int i;
2353   char *suffix1;
2354   entity *ent;
2355
2356   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2357     return;
2358
2359   if (get_irg_extblk_state(irg) != extblk_valid)
2360     compute_extbb(irg);
2361
2362   if (get_interprocedural_view()) suffix1 = "-ip";
2363   else                            suffix1 = "";
2364
2365   ent = get_irg_entity(irg);
2366
2367   F = vcg_open(irg, suffix, suffix1);
2368   dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2369
2370   construct_extblock_lists(irg);
2371
2372   fprintf(F, "graph: { title: \"");
2373   PRINT_IRGID(irg);
2374   fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2375     get_ent_dump_name(ent));
2376
2377   dump_graph_info(F, irg);
2378   print_dbg_info(F, get_entity_dbg_info(ent));
2379
2380   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2381     ir_graph *irg     = get_irp_irg(i);
2382     list_tuple *lists = ird_get_irg_link(irg);
2383
2384     if (lists) {
2385       /* dump the extended blocks first */
2386       if (ARR_LEN(lists->extbb_list)) {
2387         ird_set_irg_link(irg, lists->extbb_list);
2388         dump_extblock_graph(F, irg);
2389       }
2390
2391       /* we may have blocks without extended blocks, bad for instance */
2392       if (ARR_LEN(lists->blk_list)) {
2393         ird_set_irg_link(irg, lists->blk_list);
2394         dump_block_graph(F, irg);
2395       }
2396
2397       DEL_ARR_F(lists->extbb_list);
2398       DEL_ARR_F(lists->blk_list);
2399       xfree(lists);
2400     }
2401   }
2402
2403   /* Close the vcg information for the irg */
2404   fprintf(F, "}\n\n");
2405
2406   vcg_close(F);
2407   free_extbb(irg);
2408 }
2409
2410 /* dumps a graph with type information */
2411 void
2412 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2413 {
2414   FILE *f;
2415   ir_graph *rem = current_ir_graph;
2416   char *suffix1;
2417   int rem_dump_const_local;
2418
2419   /* if a filter is set, dump only the irg's that match the filter */
2420   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2421     return;
2422
2423   current_ir_graph = irg;
2424   rem_dump_const_local = dump_const_local;
2425   /* dumping types does not work with local nodes */
2426   dump_const_local = 0;
2427
2428   if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2429   else                            suffix1 = "-pure-wtypes";
2430   f = vcg_open(irg,suffix, suffix1);
2431   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2432
2433   /* dump common ir graph */
2434   irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2435   /* dump type info */
2436   type_walk_irg(irg, dump_type_info, NULL, f);
2437   inc_irg_visited(get_const_code_irg());
2438   /* dump edges from graph to type info */
2439   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2440
2441   vcg_close(f);
2442   dump_const_local = rem_dump_const_local;
2443   current_ir_graph = rem;
2444 }
2445
2446 void
2447 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2448 {
2449   FILE *f;
2450   int i;
2451   char *suffix1;
2452   ir_graph *rem = current_ir_graph;
2453   int rem_dump_const_local;
2454
2455   /* if a filter is set, dump only the irg's that match the filter */
2456   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2457     return;
2458
2459   rem_dump_const_local = dump_const_local;
2460   /* dumping types does not work with local nodes */
2461   dump_const_local = 0;
2462
2463   if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2464   else                            suffix1 = "-wtypes";
2465   f = vcg_open(irg, suffix, suffix1);
2466   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2467
2468   /* dump common blocked ir graph */
2469   construct_block_lists(irg);
2470
2471   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2472     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2473     if (arr) {
2474       dump_graph_from_list(f, get_irp_irg(i));
2475       DEL_ARR_F(arr);
2476     }
2477   }
2478
2479   /* dump type info */
2480   current_ir_graph = irg;
2481   type_walk_irg(irg, dump_type_info, NULL, f);
2482   inc_irg_visited(get_const_code_irg());
2483
2484   /* dump edges from graph to type info */
2485   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2486
2487   vcg_close(f);
2488   dump_const_local = rem_dump_const_local;
2489   current_ir_graph = rem;
2490 }
2491
2492 /*---------------------------------------------------------------------*/
2493 /* The following routines dump a control flow graph.                   */
2494 /*---------------------------------------------------------------------*/
2495
2496 static void
2497 dump_block_to_cfg(ir_node *block, void *env) {
2498   FILE *F = env;
2499   int i, fl = 0;
2500   ir_node *pred;
2501
2502   if (is_Block(block)) {
2503     /* This is a block. Dump a node for the block. */
2504     fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2505     fprintf (F, "\" label: \"");
2506     if (block == get_irg_start_block(get_irn_irg(block)))
2507       fprintf(F, "Start ");
2508     if (block == get_irg_end_block(get_irn_irg(block)))
2509       fprintf(F, "End ");
2510
2511     fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2512     PRINT_NODEID(block);
2513     fprintf (F, "\" ");
2514     fprintf(F, "info1:\"");
2515
2516     /* the generic version. */
2517     dump_irnode_to_file(F, block);
2518
2519     /* Check whether we have bad predecessors to color the block. */
2520     for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2521       if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2522         break;
2523
2524     fprintf (F, "\"");  /* closing quote of info */
2525
2526     if ((block == get_irg_start_block(get_irn_irg(block))) ||
2527     (block == get_irg_end_block(get_irn_irg(block)))     )
2528       fprintf(F, " color:blue ");
2529     else if (fl)
2530       fprintf(F, " color:yellow ");
2531
2532     fprintf (F, "}\n");
2533     /* Dump the edges */
2534     for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2535       if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2536         pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2537         fprintf (F, "edge: { sourcename: \"");
2538         PRINT_NODEID(block);
2539         fprintf (F, "\" targetname: \"");
2540         PRINT_NODEID(pred);
2541         fprintf (F, "\"}\n");
2542       }
2543
2544     /* Dump dominator/postdominator edge */
2545     if (dump_dominator_information_flag) {
2546       if (get_irg_dom_state(current_ir_graph) == dom_consistent && get_Block_idom(block)) {
2547         pred = get_Block_idom(block);
2548         fprintf (F, "edge: { sourcename: \"");
2549         PRINT_NODEID(block);
2550         fprintf (F, "\" targetname: \"");
2551         PRINT_NODEID(pred);
2552         fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2553       }
2554       if (get_irg_postdom_state(current_ir_graph) == dom_consistent && get_Block_ipostdom(block)) {
2555         pred = get_Block_ipostdom(block);
2556         fprintf (F, "edge: { sourcename: \"");
2557         PRINT_NODEID(block);
2558         fprintf (F, "\" targetname: \"");
2559         PRINT_NODEID(pred);
2560         fprintf (F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2561       }
2562     }
2563   }
2564 }
2565
2566 void
2567 dump_cfg (ir_graph *irg, const char *suffix)
2568 {
2569   FILE *f;
2570   ir_graph *rem = current_ir_graph;
2571   int ipv = get_interprocedural_view();
2572
2573   /* if a filter is set, dump only the irg's that match the filter */
2574   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2575     return;
2576
2577   current_ir_graph = irg;
2578
2579   f = vcg_open(irg, suffix, "-cfg");
2580   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2581
2582   if (ipv) {
2583     printf("Warning: dumping cfg not in interprocedural view!\n");
2584     set_interprocedural_view(0);
2585   }
2586
2587   /* walk over the blocks in the graph */
2588   irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2589   dump_node(f, get_irg_bad(irg));
2590
2591   set_interprocedural_view(ipv);
2592   vcg_close(f);
2593   current_ir_graph = rem;
2594 }
2595
2596
2597 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2598   if (pset_find_ptr(mark_set, n)) return;
2599
2600   pset_insert_ptr(mark_set, n);
2601
2602   if (depth > 0) {
2603     int i, start = is_Block(n) ? 0 : -1;
2604     dump_whole_node(n, F);
2605     for (i = start; i < get_irn_arity(n); ++i)
2606       descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2607   } else {
2608     dump_node(F, n);
2609     /* Don't dump edges to nodes further out.  These might be edges to
2610        nodes we already dumped, if there is a shorter path to these. */
2611   }
2612 }
2613
2614 static int subgraph_counter = 0;
2615 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2616   FILE *F;
2617   char buf[32];
2618   pset *mark_set = pset_new_ptr(1);
2619   sprintf(buf, "-subg_%03d", subgraph_counter++);
2620   F = vcg_open(get_irn_irg(root), suffix, buf);
2621   dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2622   descend_and_dump(F, root, depth, mark_set);
2623   vcg_close(F);
2624   del_pset(mark_set);
2625 }
2626
2627
2628 static int weight_overall(int rec, int loop) {
2629   return 2*rec + loop;
2630 }
2631
2632 static int compute_color (int my, int max) {
2633   int color;
2634   if (!max) {
2635     color = 0;
2636   } else {
2637     int step;
2638
2639     /* if small, scale to the full color range. */
2640     if (max < n_colors)
2641       my = my * (n_colors/max);
2642
2643     step = 1 + (max / n_colors);
2644
2645     color = my/step;
2646   }
2647   return base_color + n_colors - color;
2648 }
2649
2650 static int get_entity_color(entity *ent) {
2651   ir_graph *irg = get_entity_irg(ent);
2652   assert(irg);
2653
2654   {
2655     int rec_depth     = get_irg_recursion_depth(irg);
2656     int loop_depth    = get_irg_loop_depth(irg);
2657     int overall_depth = weight_overall(rec_depth, loop_depth);
2658
2659     int max_rec_depth     = irp->max_callgraph_recursion_depth;
2660     int max_loop_depth    = irp->max_callgraph_loop_depth;
2661     int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2662
2663     /* int my_rec_color     = compute_color(rec_depth, max_rec_depth); */
2664     /* int my_loop_color    = compute_color(loop_depth, max_loop_depth); */
2665     int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2666
2667     return my_overall_color;
2668   }
2669 }
2670
2671 void dump_callgraph(const char *suffix) {
2672   FILE *F;
2673   int i;
2674   int rem = edge_label;
2675   edge_label = 1;
2676   //ident *prefix = new_id_from_str("java/");
2677
2678   F = vcg_open_name("Callgraph", suffix);
2679   dump_vcg_header(F, "Callgraph", NULL);
2680
2681   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2682     ir_graph *irg = get_irp_irg(i);
2683     entity *ent = get_irg_entity(irg);
2684     int j, n_callees = get_irg_n_callees(irg);
2685
2686     /* Do not dump runtime system. */
2687     //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2688
2689     dump_entity_node(F, ent, get_entity_color(ent));
2690     for (j = 0; j < n_callees; ++j) {
2691       entity *c = get_irg_entity(get_irg_callee(irg, j));
2692       //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2693       int be = is_irg_callee_backedge(irg, j);
2694       char *attr;
2695       attr = (be) ?
2696         "label:\"recursion %d\" color:%d" :
2697         "label:\"calls %d\" color:%d";
2698       print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2699     }
2700   }
2701
2702   edge_label = rem;
2703   vcg_close(F);
2704 }
2705
2706 /* Dump all irgs in interprocedural view to a single file. */
2707 void dump_all_cg_block_graph(const char *suffix) {
2708   FILE *f;
2709   int i;
2710   int rem_view = get_interprocedural_view();
2711   set_interprocedural_view(1);
2712
2713   f = vcg_open_name("All_graphs", suffix);
2714   dump_vcg_header(f, "All_graphs", NULL);
2715
2716   /* collect nodes in all irgs reachable in call graph*/
2717   for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2718     ird_set_irg_link(get_irp_irg(i), NULL);
2719
2720   cg_walk(clear_link, collect_node, NULL);
2721
2722   /* dump all graphs */
2723   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2724     current_ir_graph = get_irp_irg(i);
2725     assert(ird_get_irg_link(current_ir_graph));
2726     dump_graph_from_list(f, current_ir_graph);
2727     DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2728   }
2729
2730   vcg_close(f);
2731   set_interprocedural_view(rem_view);
2732 }
2733
2734 /*---------------------------------------------------------------------*/
2735 /* the following routines dumps type information without any ir nodes. */
2736 /*---------------------------------------------------------------------*/
2737
2738 void
2739 dump_type_graph (ir_graph *irg, const char *suffix)
2740 {
2741   FILE *f;
2742   ir_graph *rem;
2743   rem = current_ir_graph;
2744
2745   /* if a filter is set, dump only the irg's that match the filter */
2746   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2747
2748   current_ir_graph = irg;
2749
2750   f = vcg_open(irg, suffix, "-type");
2751   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2752
2753   /* walk over the blocks in the graph */
2754   type_walk_irg(irg, dump_type_info, NULL, f);
2755   /* The walker for the const code can be called several times for the
2756      same (sub) expression.  So that no nodes are dumped several times
2757      we decrease the visited flag of the corresponding graph after each
2758      walk.  So now increase it finally. */
2759   inc_irg_visited(get_const_code_irg());
2760
2761   vcg_close(f);
2762   current_ir_graph = rem;
2763 }
2764
2765 void
2766 dump_all_types (const char *suffix)
2767 {
2768   FILE *f = vcg_open_name("All_types", suffix);
2769   dump_vcg_header(f, "All_types", NULL);
2770   type_walk(dump_type_info, NULL, f);
2771   inc_irg_visited(get_const_code_irg());
2772   vcg_close(f);
2773 }
2774
2775 void
2776 dump_class_hierarchy (int entities, const char *suffix)
2777 {
2778   FILE *f = vcg_open_name("class_hierarchy", suffix);
2779   h_env_t env;
2780
2781   env.f        = f;
2782   env.dump_ent = entities;
2783   dump_vcg_header(f, "class_hierarchy", NULL);
2784   type_walk(dump_class_hierarchy_node, NULL, &env);
2785   vcg_close(f);
2786 }
2787
2788 /*---------------------------------------------------------------------*/
2789 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
2790 /*  dump_ir_graph                                                      */
2791 /*  dump_ir_block_graph                                                */
2792 /*  dump_cfg                                                           */
2793 /*  dump_type_graph                                                    */
2794 /*  dump_ir_graph_w_types                                              */
2795 /*---------------------------------------------------------------------*/
2796
2797 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2798   int i;
2799   for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2800     dmp_grph(get_irp_irg(i), suffix);
2801 }
2802
2803
2804 /*--------------------------------------------------------------------------------*
2805  * Dumps a stand alone loop graph with firm nodes which belong to one loop node   *
2806  * packed together in one subgraph/box                                            *
2807  *--------------------------------------------------------------------------------*/
2808
2809 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2810   int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2811   loop_element le;
2812   ir_loop *son = NULL;
2813
2814   /* Dump a new loop node. */
2815   dump_loop_node(F, loop);
2816
2817   /* Dump the loop elements. */
2818
2819   for(i = 0; i < get_loop_n_elements(loop); i++) {
2820     le = get_loop_element(loop, i);
2821     son = le.son;
2822     if (get_kind(son) == k_ir_loop) {
2823
2824       /* We are a loop son -> Recurse */
2825
2826       if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2827         fprintf(F, "\" }\n");
2828         fprintf (F, "edge: {sourcename: \"");
2829         PRINT_LOOPID(loop);
2830         fprintf (F, "\" targetname: \"");
2831         PRINT_LOOPID(loop);
2832         fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2833         loop_node_started = 0;
2834       }
2835       dump_loop_son_edge(F, loop, son_number++);
2836       dump_loops_standalone(F, son);
2837     } else if (get_kind(son) == k_ir_node) {
2838       /* We are a loop node -> Collect firm nodes */
2839
2840       ir_node *n = le.node;
2841       int bad = 0;
2842
2843       if (!loop_node_started) {
2844         /* Start a new node which contains all firm nodes of the current loop */
2845         fprintf (F, "node: { title: \"");
2846         PRINT_LOOPID(loop);
2847         fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2848         loop_node_started = 1;
2849         first = i;
2850       }
2851       else
2852         fprintf(F, "\n");
2853
2854       bad |= dump_node_label(F, n);
2855       /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2856       if (has_backedges(n)) fprintf(F, "\t loop head!");
2857     } else { /* for callgraph loop tree */
2858       ir_graph *n;
2859       assert(get_kind(son) == k_ir_graph);
2860
2861       /* We are a loop node -> Collect firm graphs */
2862       n = (ir_graph *)le.node;
2863       if (!loop_node_started) {
2864         /* Start a new node which contains all firm nodes of the current loop */
2865         fprintf (F, "node: { title: \"");
2866         PRINT_LOOPID(loop);
2867         fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2868         loop_node_started = 1;
2869         first = i;
2870       }
2871       else
2872         fprintf(F, "\n");
2873       fprintf (F, " %s", get_irg_dump_name(n));
2874       /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2875     }
2876   }
2877
2878   if (loop_node_started) {
2879     fprintf(F, "\" }\n");
2880     fprintf (F, "edge: {sourcename: \"");
2881     PRINT_LOOPID(loop);
2882     fprintf (F, "\" targetname: \"");
2883     PRINT_LOOPID(loop);
2884     fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2885     loop_node_started = 0;
2886   }
2887 }
2888
2889 void dump_loop_tree(ir_graph *irg, const char *suffix)
2890 {
2891   FILE *f;
2892   ir_graph *rem = current_ir_graph;
2893   int el_rem = edge_label;
2894   edge_label = 1;
2895
2896   /* if a filter is set, dump only the irg's that match the filter */
2897   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2898
2899   current_ir_graph = irg;
2900
2901   f = vcg_open(irg, suffix, "-looptree");
2902   dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2903
2904   if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2905
2906   vcg_close(f);
2907
2908   edge_label = el_rem;
2909   current_ir_graph = rem;
2910 }
2911
2912 void dump_callgraph_loop_tree(const char *suffix) {
2913   FILE *F;
2914   F = vcg_open_name("Callgraph_looptree", suffix);
2915   dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2916   dump_loops_standalone(F, irp->outermost_cg_loop);
2917   vcg_close(F);
2918 }
2919
2920
2921 /*-----------------------------------------------------------------------------*/
2922 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2923 /*-----------------------------------------------------------------------------*/
2924
2925 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2926   int i, son_number = 0, node_number = 0;
2927
2928   if (dump_loop_information_flag) dump_loop_node(F, loop);
2929
2930   for (i = 0; i < get_loop_n_elements(loop); i++) {
2931     loop_element le = get_loop_element(loop, i);
2932     if (*(le.kind) == k_ir_loop) {
2933       if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2934       /* Recur */
2935       collect_nodeloop(F, le.son, loopnodes);
2936     } else {
2937       if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2938       eset_insert(loopnodes, le.node);
2939     }
2940   }
2941 }
2942
2943 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2944   int i, j, start;
2945
2946   for(i = 0; i < get_loop_n_elements(loop); i++) {
2947     loop_element le = get_loop_element(loop, i);
2948     if (*(le.kind) == k_ir_loop) {
2949       /* Recur */
2950       collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2951     } else {
2952       if (is_Block(le.node)) start = 0; else start = -1;
2953       for (j = start; j < get_irn_arity(le.node); j++) {
2954         ir_node *pred = get_irn_n(le.node, j);
2955         if (!eset_contains(loopnodes, pred)) {
2956           eset_insert(extnodes, pred);
2957           if (!is_Block(pred)) {
2958             pred = get_nodes_block(pred);
2959             if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2960           }
2961         }
2962       }
2963     }
2964   }
2965 }
2966
2967 void dump_loop(ir_loop *l, const char *suffix) {
2968   FILE *F;
2969   char name[50];
2970   eset *loopnodes = eset_create();
2971   eset *extnodes = eset_create();
2972   ir_node *n, *b;
2973
2974   snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2975   F = vcg_open_name (name, suffix);
2976   dump_vcg_header(F, name, NULL);
2977
2978   /* collect all nodes to dump */
2979   collect_nodeloop(F, l, loopnodes);
2980   collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2981
2982   /* build block lists */
2983   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2984     set_irn_link(n, NULL);
2985   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2986     set_irn_link(n, NULL);
2987   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2988     if (!is_Block(n)) {
2989       b = get_nodes_block(n);
2990       set_irn_link(n, get_irn_link(b));
2991       set_irn_link(b, n);
2992     }
2993   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2994     if (!is_Block(n)) {
2995       b = get_nodes_block(n);
2996       set_irn_link(n, get_irn_link(b));
2997       set_irn_link(b, n);
2998     }
2999
3000   for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
3001     if (is_Block(b)) {
3002       fprintf(F, "graph: { title: \"");
3003       PRINT_NODEID(b);
3004       fprintf(F, "\"  label: \"");
3005       dump_node_opcode(F, b);
3006       fprintf (F, " %ld", get_irn_node_nr(b));
3007       fprintf(F, "\" status:clustered color:yellow\n");
3008
3009       /* dump the blocks edges */
3010       dump_ir_data_edges(F, b);
3011
3012       /* dump the nodes that go into the block */
3013       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3014         if (eset_contains(extnodes, n))
3015           overrule_nodecolor = ird_color_lightblue;
3016         dump_node(F, n);
3017         overrule_nodecolor = ird_color_default;
3018         if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
3019       }
3020
3021       /* Close the vcg information for the block */
3022       fprintf(F, "}\n");
3023       dump_const_node_local(F, b);
3024       fprintf(F, "\n");
3025     }
3026   for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
3027     if (is_Block(b)) {
3028       fprintf(F, "graph: { title: \"");
3029       PRINT_NODEID(b);
3030       fprintf(F, "\"  label: \"");
3031       dump_node_opcode(F, b);
3032       fprintf (F, " %ld", get_irn_node_nr(b));
3033       fprintf(F, "\" status:clustered color:lightblue\n");
3034
3035       /* dump the nodes that go into the block */
3036       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3037         if (!eset_contains(loopnodes, n))
3038           overrule_nodecolor = ird_color_lightblue;
3039         dump_node(F, n);
3040         overrule_nodecolor = ird_color_default;
3041         if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
3042       }
3043
3044       /* Close the vcg information for the block */
3045       fprintf(F, "}\n");
3046       dump_const_node_local(F, b);
3047       fprintf(F, "\n");
3048     }
3049
3050   eset_destroy(loopnodes);
3051   eset_destroy(extnodes);
3052   vcg_close(F);
3053 }