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