after color: no space should follow
[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 bool opt_dump_analysed_type_info = 1;
90 bool 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 bool 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 false;
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 true 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(bool b) {
157   dump_const_local = b;
158 }
159
160 void dump_constant_entity_values(bool b) {
161   const_entities = b;
162 }
163
164 void dump_keepalive_edges(bool b) {
165   dump_keepalive = b;
166 }
167
168 bool get_opt_dump_keepalive_edges(void) {
169   return dump_keepalive;
170 }
171
172 void dump_out_edges(bool b) {
173   dump_out_edge_flag = b;
174 }
175
176 void dump_dominator_information(bool b) {
177   dump_dominator_information_flag = b;
178 }
179
180 void dump_loop_information(bool b) {
181   dump_loop_information_flag = b;
182 }
183
184 void dump_backedge_information(bool b) {
185   dump_backedge_information_flag = b;
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(bool b) {
193   opt_dump_analysed_type_info = b;
194 }
195
196 void dump_pointer_values_to_info(bool b) {
197   opt_dump_pointer_values_to_info = b;
198 }
199
200 void dump_ld_names(bool b) {
201   dump_ld_name = b;
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(false);
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 (false && 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 { int bad = 0;
1055   fprintf (F, " info1: \"");
1056   bad = dump_irnode_to_file(F, n);
1057   fprintf(F, "\"\n");
1058   return bad;
1059 }
1060
1061 /**
1062  * checks whether a node is "constant-like" ie can be treated "block-less"
1063  */
1064 static INLINE
1065 bool is_constlike_node(ir_node *n) {
1066   ir_op *op = get_irn_op(n);
1067   return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
1068 }
1069
1070
1071 /** outputs the predecessors of n, that are constants, local.  I.e.,
1072    generates a copy of the constant predecessors for each node called with. */
1073 static void dump_const_node_local(FILE *F, ir_node *n) {
1074   int i;
1075   if (!get_opt_dump_const_local()) return;
1076
1077   /* Use visited flag to avoid outputting nodes twice.
1078      initialize it first. */
1079   for (i = 0; i < get_irn_arity(n); i++) {
1080     ir_node *con = get_irn_n(n, i);
1081     if (is_constlike_node(con)) {
1082       set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1083     }
1084   }
1085
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) && irn_not_visited(con)) {
1089       int bad = 0;
1090
1091       mark_irn_visited(con);
1092       /* Generate a new name for the node by appending the names of
1093          n and const. */
1094       fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1095       fprintf(F, " label: \"");
1096       bad |= dump_node_label(F, con);
1097       fprintf(F, "\" ");
1098       bad |= dump_node_info(F, con);
1099       dump_node_vcgattr(F, n, con, bad);
1100       fprintf(F, "}\n");
1101     }
1102   }
1103 }
1104
1105 /** If the block of an edge is a const_like node, dump it local with an edge */
1106 static void dump_const_block_local(FILE *F, ir_node *n) {
1107   ir_node *blk;
1108
1109   if (!get_opt_dump_const_local()) return;
1110
1111   blk = get_nodes_block(n);
1112   if (is_constlike_node(blk)) {
1113     int bad = 0;
1114
1115     /* Generate a new name for the node by appending the names of
1116        n and blk. */
1117     fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1118     fprintf(F, "\" label: \"");
1119     bad |= dump_node_label(F, blk);
1120     fprintf(F, "\" ");
1121     bad |= dump_node_info(F, blk);
1122     dump_node_vcgattr(F, n, blk, bad);
1123     fprintf(F, "}\n");
1124
1125     fprintf (F, "edge: { sourcename: \"");
1126     PRINT_NODEID(n);
1127     fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1128
1129         if (dump_edge_vcgattr_hook) {
1130           fprintf (F, "\" ");
1131       if (dump_edge_vcgattr_hook(F, n, -1)) {
1132         fprintf (F, "}\n");
1133         return;
1134       }
1135           else {
1136         fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1137                 return;
1138           }
1139     }
1140
1141     fprintf (F, "\" "   BLOCK_EDGE_ATTR "}\n");
1142   }
1143 }
1144
1145 /**
1146  * prints the error message of a node to a file F as info2.
1147  */
1148 static void INLINE print_node_error(FILE *F, const char *err_msg)
1149 {
1150   if (! err_msg)
1151     return;
1152
1153   fprintf (F, " info2: \"%s\"", err_msg);
1154 }
1155
1156 /**
1157  * prints debug messages of a node to file F as info3.
1158  */
1159 static void print_dbg_info(FILE *F, dbg_info *dbg)
1160 {
1161   char buf[1024];
1162
1163   if (__dbg_info_snprint) {
1164     buf[0] = '\0';
1165     if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1166       fprintf (F, " info3: \"%s\"\n", buf);
1167   }
1168 }
1169
1170 /**
1171  * Dump a node
1172  */
1173 static void dump_node(FILE *F, ir_node *n)
1174 {
1175   int bad = 0;
1176   const char *p;
1177
1178   if (get_opt_dump_const_local() && is_constlike_node(n))
1179     return;
1180
1181   /* dump this node */
1182   fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1183
1184   bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1185   bad |= dump_node_label(F, n);
1186   dump_node_ana_vals(F, n);
1187   //dump_node_ana_info(F, n);
1188   fprintf(F, "\" ");
1189   bad |= dump_node_info(F, n);
1190   print_node_error(F, p);
1191   print_dbg_info(F, get_irn_dbg_info(n));
1192   dump_node_vcgattr(F, n, NULL, bad);
1193   fprintf(F, "}\n");
1194   dump_const_node_local(F, n);
1195
1196   if(dump_node_edge_hook)
1197     dump_node_edge_hook(F, n);
1198 #if DO_HEAPANALYSIS
1199   dump_irn_chi_term(F, n);
1200   dump_irn_state(F, n);
1201 #endif
1202 }
1203
1204 /** dump the edge to the block this node belongs to */
1205 static void
1206 dump_ir_block_edge(FILE *F, ir_node *n)  {
1207   if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1208   if (is_no_Block(n)) {
1209     ir_node *block = get_nodes_block(n);
1210
1211     if (get_opt_dump_const_local() && is_constlike_node(block)) {
1212       dump_const_block_local(F, n);
1213     }
1214     else {
1215       fprintf (F, "edge: { sourcename: \"");
1216       PRINT_NODEID(n);
1217       fprintf (F, "\" targetname: ");
1218       fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1219
1220           if (dump_edge_vcgattr_hook) {
1221             fprintf (F, " ");
1222         if (dump_edge_vcgattr_hook(F, n, -1)) {
1223           fprintf (F, "}\n");
1224           return;
1225         }
1226             else {
1227           fprintf (F, " "  BLOCK_EDGE_ATTR "}\n");
1228                   return;
1229             }
1230       }
1231
1232       fprintf (F, " "   BLOCK_EDGE_ATTR "}\n");
1233     }
1234   }
1235 }
1236
1237 static void
1238 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1239         /*
1240          * do not use get_nodes_block() here, will fail
1241          * if the irg is not pinned.
1242          */
1243   if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1244     fprintf (F, INTRA_DATA_EDGE_ATTR);
1245   else
1246     fprintf (F, INTER_DATA_EDGE_ATTR);
1247 }
1248
1249 static void
1250 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1251         /*
1252          * do not use get_nodes_block() here, will fail
1253          * if the irg is not pinned.
1254          */
1255   if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1256     fprintf (F, INTRA_MEM_EDGE_ATTR);
1257   else
1258     fprintf (F, INTER_MEM_EDGE_ATTR);
1259 }
1260
1261 static void
1262 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1263   assert(from);
1264
1265   if (dump_edge_vcgattr_hook)
1266         if (dump_edge_vcgattr_hook(F, from, to))
1267                 return;
1268
1269   if (dump_backedge_information_flag && is_backedge(from, to))
1270     fprintf (F, BACK_EDGE_ATTR);
1271
1272   switch (get_irn_opcode(from)) {
1273   case iro_Block:
1274     fprintf (F, CF_EDGE_ATTR);
1275     break;
1276   case iro_Start:   break;
1277   case iro_End:
1278     if (to >= 0) {
1279       if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1280     fprintf (F, CF_EDGE_ATTR);
1281       if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1282     fprintf (F, INTER_MEM_EDGE_ATTR);
1283     }
1284     break;
1285   case iro_EndReg:
1286   case iro_EndExcept:
1287   case iro_Jmp:
1288   case iro_Break:
1289   case iro_Cond:
1290     print_data_edge_vcgattr(F, from, to);
1291     break;
1292   case iro_Return:
1293   case iro_Raise:
1294     if (to == 0)
1295       print_mem_edge_vcgattr(F, from, to);
1296     else
1297       print_data_edge_vcgattr(F, from, to);
1298     break;
1299   case iro_Const:
1300   case iro_SymConst:
1301     print_data_edge_vcgattr(F, from, to);
1302     break;
1303   case iro_Sel:
1304   case iro_Call:
1305     if (to == 0)
1306       print_mem_edge_vcgattr(F, from, to);
1307     else
1308       print_data_edge_vcgattr(F, from, to);
1309     break;
1310   case iro_CallBegin:
1311   case iro_Add:
1312   case iro_Sub:
1313   case iro_Minus:
1314   case iro_Mul:
1315     print_data_edge_vcgattr(F, from, to);
1316     break;
1317   case iro_Quot:
1318   case iro_DivMod:
1319   case iro_Div:
1320   case iro_Mod:
1321     if (to == 0)
1322       print_mem_edge_vcgattr(F, from, to);
1323     else
1324       print_data_edge_vcgattr(F, from, to);
1325     break;
1326   case iro_Abs:
1327   case iro_And:
1328   case iro_Or:
1329   case iro_Eor:
1330   case iro_Shl:
1331   case iro_Shr:
1332   case iro_Shrs:
1333   case iro_Rot:
1334   case iro_Cmp:
1335   case iro_Conv:
1336       print_data_edge_vcgattr(F, from, to);
1337     break;
1338   case iro_Phi:
1339     if (get_irn_modecode(from) == irm_M)
1340       fprintf (F, INTER_MEM_EDGE_ATTR);
1341     else
1342       print_data_edge_vcgattr(F, from, to);
1343     break;
1344   case iro_Load:
1345   case iro_Store:
1346   case iro_Alloc:
1347   case iro_Free:
1348     if (to == 0)
1349       print_mem_edge_vcgattr(F, from, to);
1350     else
1351       print_data_edge_vcgattr(F, from, to);
1352     break;
1353   case iro_Sync:
1354     print_mem_edge_vcgattr(F, from, to);
1355     break;
1356   case iro_Tuple:  break;
1357   case iro_Proj:
1358   case iro_Filter:
1359     switch (get_irn_modecode(from)) {
1360     case irm_X:
1361       fprintf (F, CF_EDGE_ATTR);
1362       break;
1363     case irm_M:
1364       fprintf (F, INTER_MEM_EDGE_ATTR);
1365       break;
1366     default:
1367       print_data_edge_vcgattr(F, from, to);
1368       break;
1369     }
1370     break;
1371   case iro_Bad:     break;
1372   case iro_Unknown: break;
1373   case iro_Id:
1374     switch (get_irn_modecode(from)) {
1375     case irm_M:
1376       fprintf (F, INTRA_MEM_EDGE_ATTR);
1377       break;
1378     case irm_X:
1379       fprintf (F, CF_EDGE_ATTR);
1380       break;
1381     default:
1382       print_data_edge_vcgattr(F, from, to);
1383       break;
1384     } break;
1385   default:
1386     ;
1387   }
1388 }
1389
1390 /* dump edges to our inputs */
1391 static void
1392 dump_ir_data_edges(FILE *F, ir_node *n)  {
1393   int i;
1394   unsigned long visited = get_irn_visited(n);
1395
1396   if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1397     return;
1398
1399   for (i = 0; i < get_irn_arity(n); i++) {
1400     ir_node * pred = get_irn_n(n, i);
1401     assert(pred);
1402
1403     if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1404       continue; /* pred not dumped */
1405
1406     if (dump_backedge_information_flag && is_backedge(n, i))
1407       fprintf (F, "backedge: {sourcename: \"");
1408     else
1409       fprintf (F, "edge: {sourcename: \"");
1410     PRINT_NODEID(n);
1411     fprintf (F, "\" targetname: ");
1412     if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1413       PRINT_CONSTID(n, pred);
1414     } else {
1415       fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1416     }
1417     fprintf (F, " label: \"%d\" ", i);
1418     print_edge_vcgattr(F, n, i);
1419     fprintf (F, "}\n");
1420   }
1421 }
1422
1423 /** Dumps a node and its edges but not the block edge
1424  */
1425 static INLINE void
1426 dump_node_wo_blockedge (ir_node *n, void *env) {
1427   FILE *F = env;
1428   dump_node(F, n);
1429   dump_ir_data_edges(F, n);
1430 }
1431
1432 /** Dumps a node and its edges.
1433  */
1434 static void
1435 dump_whole_node (ir_node *n, void *env) {
1436   FILE *F = env;
1437   dump_node_wo_blockedge(n, env);
1438   if (!node_floats(n)) dump_ir_block_edge(F, n);
1439 }
1440
1441 static void
1442 dump_const_node(ir_node *n, void *env) {
1443   if (is_Block(n)) return;
1444   dump_node_wo_blockedge(n, env);
1445 }
1446
1447 /***********************************************************************/
1448 /* the following routines dump the nodes/irgs bracketed to graphs.     */
1449 /***********************************************************************/
1450
1451 /** Dumps a constant expression as entity initializer, array bound ...
1452  */
1453 static void dump_const_expression(FILE *F, ir_node *value) {
1454   ir_graph *rem = current_ir_graph;
1455   int rem_dump_const_local = dump_const_local;
1456   dump_const_local = 0;
1457   current_ir_graph = get_const_code_irg();
1458   irg_walk(value, dump_const_node, NULL, F);
1459   /* Decrease visited flag so that we walk with the same flag for the next
1460      expression.  This guarantees that we don't dump the same node twice,
1461      as for const expressions cse is performed to save memory. */
1462   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1463   current_ir_graph = rem;
1464   dump_const_local = rem_dump_const_local;
1465 }
1466
1467 /** Dump a block as graph containing its nodes.
1468  *
1469  *  Expects to find nodes belonging to the block as list in its
1470  *  link field.
1471  *  Dumps the edges of all nodes including itself. */
1472 static void
1473 dump_whole_block(FILE *F, ir_node *block) {
1474   ir_node *node;
1475   dumper_colors color = ird_color_yellow;
1476
1477   assert(is_Block(block));
1478
1479   fprintf(F, "graph: { title: \"");
1480   PRINT_NODEID(block);
1481   fprintf(F, "\"  label: \"");
1482   dump_node_label(F, block);
1483 #if DO_HEAPANALYSIS
1484   if (get_opt_dump_abstvals())
1485     fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1486 #endif
1487
1488   /* colorize blocks */
1489   if (! get_Block_matured(block))
1490     color = ird_color_red;
1491   if (is_Block_dead(block))
1492     color = ird_color_orange;
1493
1494   fprintf(F, "\" status:clustered ");
1495   print_vcg_color(F, color);
1496   fprintf(F, "\n");
1497
1498   /* yComp can show attributes for blocks, XVCG parses but ignores them */
1499   dump_node_info(F, block);
1500   print_dbg_info(F, get_irn_dbg_info(block));
1501
1502   /* dump the blocks edges */
1503   dump_ir_data_edges(F, block);
1504
1505   /* dump the nodes that go into the block */
1506   for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1507     dump_node(F, node);
1508     dump_ir_data_edges(F, node);
1509   }
1510
1511   /* Close the vcg information for the block */
1512   fprintf(F, "}\n");
1513   dump_const_node_local(F, block);
1514 #if DO_HEAPANALYSIS
1515   dump_irn_chi_term(F, block);
1516 #endif
1517   fprintf(F, "\n");
1518 }
1519
1520 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1521  *  The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1522 static void
1523 dump_block_graph(FILE *F, ir_graph *irg) {
1524   int i;
1525   ir_graph *rem = current_ir_graph;
1526   ir_node **arr = ird_get_irg_link(irg);
1527   current_ir_graph = irg;
1528
1529   for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1530     ir_node * node = arr[i];
1531     if (is_Block(node)) {
1532       /* Dumps the block and all the nodes in the block, which are to
1533          be found in Block->link. */
1534       dump_whole_block(F, node);
1535     } else {
1536       /* Nodes that are not in a Block. */
1537       dump_node(F, node);
1538       if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1539         dump_const_block_local(F, node);
1540       }
1541       dump_ir_data_edges(F, node);
1542     }
1543   }
1544
1545   if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1546     dump_loop_nodes_into_graph(F, irg);
1547
1548   current_ir_graph = rem;
1549 }
1550
1551 /**
1552  * Dump the info for an irg.
1553  * Parsed by XVCG but not shown. use yComp.
1554  */
1555 static void dump_graph_info(FILE *F, ir_graph *irg) {
1556   fprintf(F, "info1: \"");
1557   dump_entity_to_file(F, get_irg_entity(irg), dump_verbosity_entattrs | dump_verbosity_entconsts);
1558   fprintf(F, "\"\n");
1559 }
1560
1561 /** Dumps an irg as a graph clustered by block nodes.
1562  *  If interprocedural view edges can point to nodes out of this graph.
1563  */
1564 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1565   entity *ent = get_irg_entity(irg);
1566
1567   fprintf(F, "graph: { title: \"");
1568   PRINT_IRGID(irg);
1569   fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1570       get_ent_dump_name(ent));
1571
1572   dump_graph_info(F, irg);
1573   print_dbg_info(F, get_entity_dbg_info(ent));
1574
1575   dump_block_graph(F, irg);
1576
1577   /* Close the vcg information for the irg */
1578   fprintf(F, "}\n\n");
1579 }
1580
1581 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1582  *  The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1583 static void
1584 dump_extblock_graph(FILE *F, ir_graph *irg) {
1585   int i;
1586   ir_graph *rem = current_ir_graph;
1587   ir_extblk **arr = ird_get_irg_link(irg);
1588   current_ir_graph = irg;
1589
1590   compute_extbb(irg);
1591   for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1592     ir_extblk *extbb = arr[i];
1593     ir_node *leader = get_extbb_leader(extbb);
1594     int j;
1595
1596     fprintf(F, "graph: { title: \"");
1597     PRINT_EXTBBID(leader);
1598     fprintf(F, "\"  label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1599             get_irn_node_nr(leader));
1600
1601     for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1602       ir_node * node = extbb->blks[j];
1603       if (is_Block(node)) {
1604         /* Dumps the block and all the nodes in the block, which are to
1605            be found in Block->link. */
1606         dump_whole_block(F, node);
1607       } else {
1608         /* Nodes that are not in a Block. */
1609         dump_node(F, node);
1610         if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1611           dump_const_block_local(F, node);
1612         }
1613         dump_ir_data_edges(F, node);
1614       }
1615     }
1616     fprintf(F, "}\n");
1617   }
1618
1619   if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1620     dump_loop_nodes_into_graph(F, irg);
1621
1622   current_ir_graph = rem;
1623   free_extbb(irg);
1624 }
1625
1626
1627 /*******************************************************************/
1628 /* Basic type and entity nodes and edges.                          */
1629 /*******************************************************************/
1630
1631 /** dumps the edges between nodes and their type or entity attributes. */
1632 static void dump_node2type_edges(ir_node *n, void *env)
1633 {
1634   FILE *F = env;
1635   assert(n);
1636
1637   switch (get_irn_opcode(n)) {
1638   case iro_Const :
1639     /* @@@ some consts have an entity */
1640     break;
1641   case iro_SymConst:
1642     if (   (get_SymConst_kind(n) ==symconst_type_tag)
1643        || (get_SymConst_kind(n) ==symconst_size))
1644       {
1645         print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1646       }
1647     break;
1648   case iro_Sel: {
1649       print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1650     } break;
1651   case iro_Call: {
1652       print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1653     } break;
1654   case iro_Alloc: {
1655       print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1656     } break;
1657   case iro_Free: {
1658       print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1659     } break;
1660   case iro_Cast: {
1661       print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1662     } break;
1663   default:
1664     break;
1665   }
1666 }
1667
1668 #if 0
1669 static int print_type_info(FILE *F, type *tp) {
1670   int bad = 0;
1671
1672   if (get_type_state(tp) == layout_undefined) {
1673     fprintf(F, "state: layout_undefined\n");
1674   } else {
1675     fprintf(F, "state: layout_fixed,\n");
1676   }
1677   if (get_type_mode(tp))
1678     fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1679   fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1680
1681   return bad;
1682 }
1683
1684 static void print_typespecific_info(FILE *F, type *tp) {
1685   switch (get_type_tpop_code(tp)) {
1686   case tpo_class:
1687     {
1688       fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1689     } break;
1690   case tpo_struct:
1691     {
1692     } break;
1693   case tpo_method:
1694     {
1695       fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1696       fprintf(F, "params: %d\n", get_method_n_params(tp));
1697       fprintf(F, "results: %d\n", get_method_n_ress(tp));
1698     } break;
1699   case tpo_union:
1700     {
1701     } break;
1702   case tpo_array:
1703     {
1704     } break;
1705   case tpo_enumeration:
1706     {
1707     } break;
1708   case tpo_pointer:
1709     {
1710     } break;
1711   case tpo_primitive:
1712     {
1713     } break;
1714   default: break;
1715   } /* switch type */
1716 }
1717 #endif
1718
1719 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1720   switch (get_type_tpop_code(tp)) {
1721   case tpo_class:
1722     {
1723       if (peculiarity_existent == get_class_peculiarity(tp))
1724     fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1725       else
1726     fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1727     } break;
1728   case tpo_struct:
1729     {
1730       fprintf (F, " " TYPE_METH_NODE_ATTR);
1731     } break;
1732   case tpo_method:
1733     {
1734     } break;
1735   case tpo_union:
1736     {
1737     } break;
1738   case tpo_array:
1739     {
1740     } break;
1741   case tpo_enumeration:
1742     {
1743     } break;
1744   case tpo_pointer:
1745     {
1746     } break;
1747   case tpo_primitive:
1748     {
1749     } break;
1750   default: break;
1751   } /* switch type */
1752 }
1753
1754
1755 int dump_type_node(FILE *F, type *tp)
1756 {
1757   int bad = 0;
1758
1759   fprintf (F, "node: {title: ");
1760   PRINT_TYPEID(tp);
1761   fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1762   fprintf (F, " info1: \"");
1763 #if 0
1764   bad |= print_type_info(F, tp);
1765   print_typespecific_info(F, tp);
1766 #else
1767   dump_type_to_file(F, tp, dump_verbosity_max);
1768 #endif
1769   fprintf (F, "\"\n");
1770   print_dbg_info(F, get_type_dbg_info(tp));
1771   print_typespecific_vcgattr(F, tp);
1772   fprintf (F, "}\n");
1773
1774   return bad;
1775 }
1776
1777
1778 #define X(a)    case a: fprintf(F, #a); break
1779 void dump_entity_node(FILE *F, entity *ent, int color)
1780 {
1781   fprintf (F, "node: {title: \"");
1782   PRINT_ENTID(ent); fprintf(F, "\"");
1783   fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1784   fprintf (F, "label: ");
1785   fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1786   if (color)
1787     fprintf(F, "color:%d", color);
1788   else
1789     fprintf (F, ENTITY_NODE_ATTR);
1790   fprintf (F, "\n info1: \"");
1791
1792   dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1793
1794   fprintf(F, "\"\n");
1795   print_dbg_info(F, get_entity_dbg_info(ent));
1796   fprintf(F, "}\n");
1797 }
1798 #undef X
1799
1800 static void dump_enum_item(FILE *F, type *tp, int pos)
1801 {
1802   char buf[1024];
1803   ident *id  = get_enumeration_nameid(tp, pos);
1804   tarval *tv = get_enumeration_enum(tp, pos);
1805
1806   tarval_snprintf(buf, sizeof(buf), tv);
1807   fprintf (F, "node: {title: \"");
1808   PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1809   fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1810   fprintf (F, "label: ");
1811   fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1812   fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1813 }
1814
1815 /* dumps a type or entity and it's edges. */
1816 static void
1817 dump_type_info(type_or_ent *tore, void *env) {
1818   FILE *F = env;
1819   int i = 0;  /* to shutup gcc */
1820
1821   /* dump this type or entity */
1822
1823   switch (get_kind(tore)) {
1824   case k_entity:
1825     {
1826       entity *ent = (entity *)tore;
1827       ir_node *value;
1828       /* The node */
1829       dump_entity_node(F, ent, 0);
1830       /* The Edges */
1831       /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
1832       fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1833                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1834       print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1835       if (is_Class_type(get_entity_owner(ent))) {
1836         for(i = 0; i < get_entity_n_overwrites(ent); i++)
1837           print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1838       }
1839       /* attached subgraphs */
1840       if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1841         if (is_atomic_entity(ent)) {
1842           value = get_atomic_ent_value(ent);
1843           if (value) {
1844             print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1845             /* DDMN(value);  $$$ */
1846             dump_const_expression(F, value);
1847           }
1848         }
1849         if (is_compound_entity(ent)) {
1850           for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1851             value = get_compound_ent_value(ent, i);
1852             if (value) {
1853               print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1854               dump_const_expression(F, value);
1855               print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1856               /*
1857               fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1858               ENT_CORR_EDGE_ATTR  "}\n", GET_ENTID(ent),
1859               get_compound_ent_value_member(ent, i), i);
1860               */
1861             }
1862           }
1863         }
1864       }
1865     } break;
1866   case k_type:
1867     {
1868       type *tp = (type *)tore;
1869       dump_type_node(F, tp);
1870       /* and now the edges */
1871       switch (get_type_tpop_code(tp)) {
1872       case tpo_class:
1873         {
1874           for (i=0; i < get_class_n_supertypes(tp); i++)
1875             print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1876           for (i=0; i < get_class_n_members(tp); i++)
1877             print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1878         } break;
1879       case tpo_struct:
1880         {
1881           for (i=0; i < get_struct_n_members(tp); i++)
1882             print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1883         } break;
1884       case tpo_method:
1885         {
1886           for (i = 0; i < get_method_n_params(tp); i++)
1887             print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1888           for (i = 0; i < get_method_n_ress(tp); i++)
1889             print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1890         } break;
1891       case tpo_union:
1892         {
1893           for (i = 0; i < get_union_n_members(tp); i++)
1894             print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1895         } break;
1896       case tpo_array:
1897         {
1898           print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1899           print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1900           for (i = 0; i < get_array_n_dimensions(tp); i++) {
1901             ir_node *upper = get_array_upper_bound(tp, i);
1902             ir_node *lower = get_array_lower_bound(tp, i);
1903             print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1904             print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1905             dump_const_expression(F, upper);
1906             dump_const_expression(F, lower);
1907           }
1908
1909         } break;
1910       case tpo_enumeration:
1911         {
1912           for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1913             dump_enum_item(F, tp, i);
1914             print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1915           }
1916         } break;
1917       case tpo_pointer:
1918         {
1919           print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1920         } break;
1921       case tpo_primitive:
1922         {
1923         } break;
1924       default: break;
1925       } /* switch type */
1926     }
1927     break; /* case k_type */
1928   default:
1929     {
1930       printf(" *** irdump,  dump_type_info(l.%i), faulty type.\n", __LINE__);
1931     } break;
1932   } /* switch kind_or_entity */
1933 }
1934
1935 typedef struct _h_env {
1936   int dump_ent;
1937   FILE *f;
1938 } h_env_t;
1939
1940 /** For dumping class hierarchies.
1941  * Dumps a class type node and a superclass edge.
1942  * If env->dump_ent dumps entities of classes and overwrites edges.
1943  */
1944 static void
1945 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1946   h_env_t *env = ctx;
1947   FILE *F = env->f;
1948   int i = 0;  /* to shutup gcc */
1949
1950   /* dump this type or entity */
1951   switch (get_kind(tore)) {
1952   case k_entity: {
1953     entity *ent = (entity *)tore;
1954     if (get_entity_owner(ent) == get_glob_type()) break;
1955     if (!is_Method_type(get_entity_type(ent))) break;  /* GL */
1956     if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1957       /* The node */
1958       dump_entity_node(F, ent, 0);
1959       /* The edges */
1960       print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1961       for(i = 0; i < get_entity_n_overwrites(ent); i++)
1962         print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1963     }
1964   } break; /* case k_entity */
1965   case k_type:
1966     {
1967       type *tp = (type *)tore;
1968       if (tp == get_glob_type()) break;
1969       switch (get_type_tpop_code(tp)) {
1970         case tpo_class: {
1971           dump_type_node(F, tp);
1972           /* and now the edges */
1973           for (i=0; i < get_class_n_supertypes(tp); i++)
1974           {
1975               print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1976           }
1977         } break;
1978         default: break;
1979       } /* switch type */
1980     }
1981     break; /* case k_type */
1982   default:
1983     {
1984       printf(" *** irdump,  dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1985     } break;
1986   } /* switch kind_or_entity */
1987 }
1988
1989 /*******************************************************************/
1990 /* dump analysis information that is expressed in graph terms.     */
1991 /*******************************************************************/
1992
1993 /* dump out edges */
1994 static void
1995 dump_out_edge(ir_node *n, void *env) {
1996   FILE *F = env;
1997   int i;
1998   for (i = 0; i < get_irn_n_outs(n); i++) {
1999     assert(get_irn_out(n, i));
2000     fprintf (F, "edge: {sourcename: \"");
2001     PRINT_NODEID(n);
2002     fprintf (F, "\" targetname: \"");
2003     PRINT_NODEID(get_irn_out(n, i));
2004     fprintf (F, "\" color: red linestyle: dashed");
2005     fprintf (F, "}\n");
2006   }
2007 }
2008
2009 static INLINE void
2010 dump_loop_label(FILE *F, ir_loop *loop) {
2011   fprintf (F, "loop %d, %d sons, %d nodes",
2012        get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
2013 }
2014
2015 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
2016   fprintf (F, " info1: \"");
2017   fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
2018 #if DEBUG_libfirm   /* GL @@@ debug analyses */
2019   fprintf (F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
2020 #endif
2021   fprintf (F, "\"");
2022 }
2023
2024 static INLINE void
2025 dump_loop_node(FILE *F, ir_loop *loop) {
2026   fprintf (F, "node: {title: \"");
2027   PRINT_LOOPID(loop);
2028   fprintf (F, "\" label: \"");
2029   dump_loop_label(F, loop);
2030   fprintf (F, "\" ");
2031   dump_loop_info(F, loop);
2032   fprintf (F, "}\n");
2033
2034 }
2035
2036 static INLINE void
2037 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
2038   assert(loop);
2039   fprintf (F, "edge: {sourcename: \"");
2040   PRINT_LOOPID(loop);
2041   fprintf (F, "\" targetname: \"");
2042   PRINT_NODEID(get_loop_node(loop, i));
2043   fprintf (F, "\" color: green");
2044   fprintf (F, "}\n");
2045 }
2046
2047 static INLINE void
2048 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
2049   assert(loop);
2050   fprintf (F, "edge: {sourcename: \"");
2051   PRINT_LOOPID(loop);
2052   fprintf (F, "\" targetname: \"");
2053   PRINT_LOOPID(get_loop_son(loop, i));
2054   fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
2055        get_loop_element_pos(loop, get_loop_son(loop, i)));
2056 }
2057
2058 static
2059 void dump_loops(FILE *F, ir_loop *loop) {
2060   int i;
2061   /* dump this loop node */
2062   dump_loop_node(F, loop);
2063
2064   /* dump edges to nodes in loop -- only if it is a real loop */
2065   if (get_loop_depth(loop) != 0) {
2066     for (i = 0; i < get_loop_n_nodes(loop); i++) {
2067       dump_loop_node_edge(F, loop, i);
2068     }
2069   }
2070   for (i = 0; i < get_loop_n_sons(loop); i++) {
2071     dump_loops(F, get_loop_son(loop, i));
2072     dump_loop_son_edge(F, loop, i);
2073   }
2074 }
2075
2076 static INLINE
2077 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
2078   ir_graph *rem = current_ir_graph;
2079   current_ir_graph = irg;
2080
2081   if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
2082
2083   current_ir_graph = rem;
2084 }
2085
2086
2087 /**
2088  * dumps the VCG header
2089  */
2090 void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
2091   char *label;
2092
2093   if (edge_label) {
2094     label = "yes";
2095   } else {
2096     label = "no";
2097   }
2098
2099   if (!orientation) orientation = "bottom_to_top";
2100
2101   /* print header */
2102   fprintf (F,
2103        "graph: { title: \"ir graph of %s\"\n"
2104        "display_edge_labels: %s\n"
2105        "layoutalgorithm: mindepth\n"
2106        "manhattan_edges: yes\n"
2107        "port_sharing: no\n"
2108        "orientation: %s\n"
2109        "classname 1:  \"intrablock Data\"\n"
2110        "classname 16: \"interblock Data\"\n"
2111        "classname 2:  \"Block\"\n"
2112        "classname 13: \"Control Flow\"\n"
2113        "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2114        "classname 14: \"intrablock Memory\"\n"
2115        "classname 17: \"interblock Memory\"\n"
2116        "classname 15: \"Dominators\"\n"
2117        "classname 3:  \"Entity type\"\n"
2118        "classname 4:  \"Entity owner\"\n"
2119        "classname 5:  \"Method Param\"\n"
2120        "classname 6:  \"Method Res\"\n"
2121        "classname 7:  \"Super\"\n"
2122        "classname 8:  \"Union\"\n"
2123        "classname 9:  \"Points-to\"\n"
2124        "classname 10: \"Array Element Type\"\n"
2125        "classname 11: \"Overwrites\"\n"
2126        "classname 12: \"Member\"\n"
2127        "infoname 1: \"Attribute\"\n"
2128        "infoname 2: \"Verification errors\"\n"
2129        "infoname 3: \"Debug info\"\n",
2130        name, label, orientation);
2131
2132   /* don't use all, the range is too whith/black. */
2133   n_colors   = 18;
2134   base_color = 105;
2135   fprintf (F,
2136        "colorentry 100:    0   0    0\n"
2137        "colorentry 101:   20   0    0\n"
2138        "colorentry 102:   40   0    0\n"
2139        "colorentry 103:   60   0    0\n"
2140        "colorentry 104:   80   0    0\n"
2141        "colorentry 105:  100   0    0\n"
2142        "colorentry 106:  120   0    0\n"
2143        "colorentry 107:  140   0    0\n"
2144        "colorentry 108:  150   0    0\n"
2145        "colorentry 109:  180   0    0\n"
2146        "colorentry 110:  200   0    0\n"
2147        "colorentry 111:  220   0    0\n"
2148        "colorentry 112:  240   0    0\n"
2149        "colorentry 113:  255   0    0\n"
2150        "colorentry 113:  255  20   20\n"
2151        "colorentry 114:  255  40   40\n"
2152        "colorentry 115:  255  60   60\n"
2153        "colorentry 116:  255  80   80\n"
2154        "colorentry 117:  255 100  100\n"
2155        "colorentry 118:  255 120  120\n"
2156        "colorentry 119:  255 140  140\n"
2157        "colorentry 120:  255 150  150\n"
2158        "colorentry 121:  255 180  180\n"
2159        "colorentry 122:  255 200  200\n"
2160        "colorentry 123:  255 220  220\n"
2161        "colorentry 124:  255 240  240\n"
2162        "colorentry 125:  255 250  250\n"
2163        );
2164
2165   fprintf (F, "\n");        /* a separator */
2166 }
2167
2168 /**
2169  * open a vcg file
2170  *
2171  * @param irg     The graph to be dumped
2172  * @param suffix1 first filename suffix
2173  * @param suffix2 second filename suffix
2174  */
2175 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
2176   FILE *F;
2177   const char *nm = get_irg_dump_name(irg);
2178   int len = strlen(nm), i, j;
2179   char *fname;  /* filename to put the vcg information in */
2180
2181   if (!suffix1) suffix1 = "";
2182   if (!suffix2) suffix2 = "";
2183
2184   /* open file for vcg graph */
2185   fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2186
2187   /* strncpy (fname, nm, len); */     /* copy the filename */
2188   j = 0;
2189   for (i = 0; i < len; ++i) {  /* replace '/' in the name: escape by @. */
2190     if (nm[i] == '/') {
2191       fname[j] = '@'; j++; fname[j] = '1'; j++;
2192     } else if (nm[i] == '@') {
2193       fname[j] = '@'; j++; fname[j] = '2'; j++;
2194     } else {
2195       fname[j] = nm[i]; j++;
2196     }
2197   }
2198   fname[j] = '\0';
2199   strcat (fname, suffix1);  /* append file suffix */
2200   strcat (fname, suffix2);  /* append file suffix */
2201   strcat (fname, ".vcg");   /* append the .vcg suffix */
2202
2203   /* vcg really expect only a <CR> at end of line, so
2204    * the "b"inary mode is what you mean (and even needed for Win32)
2205    */
2206   F = fopen (fname, "wb");  /* open file for writing */
2207   if (!F) {
2208     panic("cannot open %s for writing (%m)", fname);  /* not reached */
2209   }
2210   free(fname);
2211
2212   return F;
2213 }
2214
2215 /**
2216  * open a vcg file
2217  *
2218  * @param name    prefix file name
2219  * @param suffix  filename suffix
2220  */
2221 FILE *vcg_open_name (const char *name, const char *suffix) {
2222   FILE *F;
2223   char *fname;  /* filename to put the vcg information in */
2224   int i, j, len = strlen(name);
2225
2226   if (!suffix) suffix = "";
2227
2228   /** open file for vcg graph */
2229   fname = xmalloc(len * 2 + 5 + strlen(suffix));
2230   /* strcpy (fname, name);*/    /* copy the filename */
2231   j = 0;
2232   for (i = 0; i < len; ++i) {  /* replace '/' in the name: escape by @. */
2233     if (name[i] == '/') {
2234       fname[j] = '@'; j++; fname[j] = '1'; j++;
2235     } else if (name[i] == '@') {
2236       fname[j] = '@'; j++; fname[j] = '2'; j++;
2237     } else {
2238       fname[j] = name[i]; j++;
2239     }
2240   }
2241   fname[j] = '\0';
2242   strcat (fname, suffix);
2243   strcat (fname, ".vcg");  /* append the .vcg suffix */
2244
2245   /* vcg really expect only a <CR> at end of line, so
2246    * the "b"inary mode is what you mean (and even needed for Win32)
2247    */
2248   F = fopen (fname, "wb");  /* open file for writing */
2249   if (!F) {
2250     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
2251   }
2252   free(fname);
2253
2254   return F;
2255 }
2256
2257 /**
2258  * Dumps the vcg file footer
2259  */
2260 static INLINE void dump_vcg_footer (FILE *F) {
2261   fprintf (F, "}\n");
2262 }
2263
2264 /**
2265  * close the vcg file
2266  */
2267 void vcg_close (FILE *F) {
2268   dump_vcg_footer(F);    /* print footer */
2269   fclose (F);           /* close vcg file */
2270 }
2271
2272 /************************************************************************/
2273 /************************************************************************/
2274 /* Routines that dump all or parts of the firm representation to a file */
2275 /************************************************************************/
2276 /************************************************************************/
2277
2278 /************************************************************************/
2279 /* Dump ir graphs, different formats and additional information.        */
2280 /************************************************************************/
2281
2282 /** Routine to dump a graph, blocks as conventional nodes.  */
2283 void
2284 dump_ir_graph (ir_graph *irg, const char *suffix )
2285 {
2286   FILE *f;
2287   ir_graph *rem;
2288   char *suffix1;
2289   rem = current_ir_graph;
2290
2291   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2292
2293   current_ir_graph = irg;
2294   if (get_interprocedural_view()) suffix1 = "-pure-ip";
2295   else                            suffix1 = "-pure";
2296   f = vcg_open(irg, suffix, suffix1);
2297   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2298
2299   /* call the dump graph hook */
2300   if (dump_ir_graph_hook)
2301     if (dump_ir_graph_hook(f, irg))
2302       return;
2303
2304   /* walk over the graph */
2305   /* dump_whole_node must be called in post visiting predecessors */
2306   irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2307
2308   /* dump the out edges in a separate walk */
2309   if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2310     irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2311   }
2312
2313   vcg_close(f);
2314
2315   current_ir_graph = rem;
2316 }
2317
2318 /* Dump a firm graph without explicit block nodes. */
2319 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2320 {
2321   FILE *f;
2322   int i;
2323   char *suffix1;
2324
2325   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2326     return;
2327
2328   if (get_interprocedural_view()) suffix1 = "-ip";
2329   else                            suffix1 = "";
2330   f = vcg_open(irg, suffix, suffix1);
2331   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2332
2333   construct_block_lists(irg);
2334
2335   /*
2336    * If we are in the interprocedural view, we dump not
2337    * only the requested irg but also all irgs that can be reached
2338    * from irg.
2339    */
2340   for (i = 0; i < get_irp_n_irgs(); i++) {
2341     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2342     if (arr) {
2343       dump_graph_from_list(f, get_irp_irg(i));
2344       DEL_ARR_F(arr);
2345     }
2346   }
2347
2348   vcg_close(f);
2349 }
2350
2351 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2352 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2353 {
2354   FILE *F;
2355   int i;
2356   char *suffix1;
2357   entity *ent;
2358
2359   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2360     return;
2361
2362   compute_extbb(irg);
2363
2364   if (get_interprocedural_view()) suffix1 = "-ip";
2365   else                            suffix1 = "";
2366
2367   ent = get_irg_entity(irg);
2368
2369   F = vcg_open(irg, suffix, suffix1);
2370   dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2371
2372   construct_extblock_lists(irg);
2373
2374   fprintf(F, "graph: { title: \"");
2375   PRINT_IRGID(irg);
2376   fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2377     get_ent_dump_name(ent));
2378
2379   dump_graph_info(F, irg);
2380   print_dbg_info(F, get_entity_dbg_info(ent));
2381
2382   for (i = 0; i < get_irp_n_irgs(); i++) {
2383     ir_graph *irg     = get_irp_irg(i);
2384     list_tuple *lists = ird_get_irg_link(irg);
2385
2386     if (lists) {
2387       /* dump the extended blocks first */
2388       if (ARR_LEN(lists->extbb_list)) {
2389         ird_set_irg_link(irg, lists->extbb_list);
2390         dump_extblock_graph(F, irg);
2391       }
2392
2393       /* we may have blocks without extended blocks, bad for instance */
2394       if (ARR_LEN(lists->blk_list)) {
2395         ird_set_irg_link(irg, lists->blk_list);
2396         dump_block_graph(F, irg);
2397       }
2398
2399       DEL_ARR_F(lists->extbb_list);
2400       DEL_ARR_F(lists->blk_list);
2401       xfree(lists);
2402     }
2403   }
2404
2405   /* Close the vcg information for the irg */
2406   fprintf(F, "}\n\n");
2407
2408   vcg_close(F);
2409   free_extbb(irg);
2410 }
2411
2412 /* dumps a graph with type information */
2413 void
2414 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2415 {
2416   FILE *f;
2417   ir_graph *rem = current_ir_graph;
2418   char *suffix1;
2419   int rem_dump_const_local;
2420
2421   /* if a filter is set, dump only the irg's that match the filter */
2422   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2423     return;
2424
2425   current_ir_graph = irg;
2426   rem_dump_const_local = dump_const_local;
2427   /* dumping types does not work with local nodes */
2428   dump_const_local = 0;
2429
2430   if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2431   else                            suffix1 = "-pure-wtypes";
2432   f = vcg_open(irg,suffix, suffix1);
2433   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2434
2435   /* dump common ir graph */
2436   irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2437   /* dump type info */
2438   type_walk_irg(irg, dump_type_info, NULL, f);
2439   inc_irg_visited(get_const_code_irg());
2440   /* dump edges from graph to type info */
2441   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2442
2443   vcg_close(f);
2444   dump_const_local = rem_dump_const_local;
2445   current_ir_graph = rem;
2446 }
2447
2448 void
2449 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2450 {
2451   FILE *f;
2452   int i;
2453   char *suffix1;
2454   ir_graph *rem = current_ir_graph;
2455   int rem_dump_const_local;
2456
2457   /* if a filter is set, dump only the irg's that match the filter */
2458   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2459     return;
2460
2461   rem_dump_const_local = dump_const_local;
2462   /* dumping types does not work with local nodes */
2463   dump_const_local = 0;
2464
2465   if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2466   else                            suffix1 = "-wtypes";
2467   f = vcg_open(irg, suffix, suffix1);
2468   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2469
2470   /* dump common blocked ir graph */
2471   construct_block_lists(irg);
2472
2473   for (i = 0; i < get_irp_n_irgs(); i++) {
2474     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2475     if (arr) {
2476       dump_graph_from_list(f, get_irp_irg(i));
2477       DEL_ARR_F(arr);
2478     }
2479   }
2480
2481   /* dump type info */
2482   current_ir_graph = irg;
2483   type_walk_irg(irg, dump_type_info, NULL, f);
2484   inc_irg_visited(get_const_code_irg());
2485
2486   /* dump edges from graph to type info */
2487   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2488
2489   vcg_close(f);
2490   dump_const_local = rem_dump_const_local;
2491   current_ir_graph = rem;
2492 }
2493
2494 /*---------------------------------------------------------------------*/
2495 /* The following routines dump a control flow graph.                   */
2496 /*---------------------------------------------------------------------*/
2497
2498 static void
2499 dump_block_to_cfg(ir_node *block, void *env) {
2500   FILE *F = env;
2501   int i, fl = 0;
2502   ir_node *pred;
2503
2504   if (is_Block(block)) {
2505     /* This is a block. Dump a node for the block. */
2506     fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2507     fprintf (F, "\" label: \"");
2508     if (block == get_irg_start_block(get_irn_irg(block)))
2509       fprintf(F, "Start ");
2510     if (block == get_irg_end_block(get_irn_irg(block)))
2511       fprintf(F, "End ");
2512
2513     fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2514     PRINT_NODEID(block);
2515     fprintf (F, "\" ");
2516     fprintf(F, "info1:\"");
2517
2518 #if 0
2519     if (dump_dominator_information_flag) {
2520       fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2521       fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block));
2522       fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block));
2523     }
2524
2525     /* show arity and possible Bad predecessors of the block */
2526     fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2527     for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2528       ir_node *pred = get_Block_cfgpred(block, i);
2529       if (is_Bad(pred)) {
2530         if (! fl)
2531           fprintf(F, "Bad pred at pos: ");
2532         fprintf(F, "%d ", i);
2533         fl = 1;
2534       }
2535     }
2536     if (fl)
2537       fprintf(F, "\n");
2538 #else
2539     /* the generic version. */
2540     dump_irnode_to_file(F, block);
2541
2542     /* Check whether we have bad predecessors to color the block. */
2543     for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2544       if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2545         break;
2546 #endif
2547
2548     fprintf (F, "\"");  /* closing quote of info */
2549
2550     if ((block == get_irg_start_block(get_irn_irg(block))) ||
2551     (block == get_irg_end_block(get_irn_irg(block)))     )
2552       fprintf(F, " color:blue ");
2553     else if (fl)
2554       fprintf(F, " color:yellow ");
2555
2556     fprintf (F, "}\n");
2557     /* Dump the edges */
2558     for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2559       if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2560         pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2561         fprintf (F, "edge: { sourcename: \"");
2562         PRINT_NODEID(block);
2563         fprintf (F, "\" targetname: \"");
2564         PRINT_NODEID(pred);
2565         fprintf (F, "\"}\n");
2566       }
2567
2568     /* Dump dominator edge */
2569     if (dump_dominator_information_flag && get_Block_idom(block)) {
2570       pred = get_Block_idom(block);
2571       fprintf (F, "edge: { sourcename: \"");
2572       PRINT_NODEID(block);
2573       fprintf (F, "\" targetname: \"");
2574       PRINT_NODEID(pred);
2575       fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2576     }
2577   }
2578 }
2579
2580 void
2581 dump_cfg (ir_graph *irg, const char *suffix)
2582 {
2583   FILE *f;
2584   ir_graph *rem = current_ir_graph;
2585   int ddif = dump_dominator_information_flag;
2586   int ipv = get_interprocedural_view();
2587
2588   /* if a filter is set, dump only the irg's that match the filter */
2589   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2590     return;
2591
2592   current_ir_graph = irg;
2593
2594   f = vcg_open(irg, suffix, "-cfg");
2595   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2596
2597   if (ipv) {
2598     printf("Warning: dumping cfg not in interprocedural view!\n");
2599     set_interprocedural_view(false);
2600   }
2601
2602   if (get_irg_dom_state(irg) != dom_consistent)
2603     dump_dominator_information_flag = 0;
2604
2605   /* walk over the blocks in the graph */
2606   irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2607   dump_node(f, get_irg_bad(irg));
2608
2609   dump_dominator_information_flag = ddif;
2610   set_interprocedural_view(ipv);
2611   vcg_close(f);
2612   current_ir_graph = rem;
2613 }
2614
2615
2616 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2617   if (pset_find_ptr(mark_set, n)) return;
2618
2619   pset_insert_ptr(mark_set, n);
2620
2621   if (depth > 0) {
2622     int i, start = is_Block(n) ? 0 : -1;
2623     dump_whole_node(n, F);
2624     for (i = start; i < get_irn_arity(n); ++i)
2625       descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2626   } else {
2627     dump_node(F, n);
2628     /* Don't dump edges to nodes further out.  These might be edges to
2629        nodes we already dumped, if there is a shorter path to these. */
2630   }
2631 }
2632
2633 static int subgraph_counter = 0;
2634 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2635   FILE *F;
2636   char buf[32];
2637   pset *mark_set = pset_new_ptr(1);
2638   sprintf(buf, "-subg_%03d", subgraph_counter++);
2639   F = vcg_open(get_irn_irg(root), suffix, buf);
2640   dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2641   descend_and_dump(F, root, depth, mark_set);
2642   vcg_close(F);
2643   del_pset(mark_set);
2644 }
2645
2646
2647 static int weight_overall(int rec, int loop) {
2648   return 2*rec + loop;
2649 }
2650
2651 static int compute_color (int my, int max) {
2652   int color;
2653   if (!max) {
2654     color = 0;
2655   } else {
2656     int step;
2657
2658     /* if small, scale to the full color range. */
2659     if (max < n_colors)
2660       my = my * (n_colors/max);
2661
2662     step = 1 + (max / n_colors);
2663
2664     color = my/step;
2665   }
2666   return base_color + n_colors - color;
2667 }
2668
2669 static int get_entity_color(entity *ent) {
2670   ir_graph *irg = get_entity_irg(ent);
2671   assert(irg);
2672
2673   {
2674     int rec_depth     = get_irg_recursion_depth(irg);
2675     int loop_depth    = get_irg_loop_depth(irg);
2676     int overall_depth = weight_overall(rec_depth, loop_depth);
2677
2678     int max_rec_depth     = irp->max_callgraph_recursion_depth;
2679     int max_loop_depth    = irp->max_callgraph_loop_depth;
2680     int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2681
2682     /* int my_rec_color     = compute_color(rec_depth, max_rec_depth); */
2683     /* int my_loop_color    = compute_color(loop_depth, max_loop_depth); */
2684     int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2685
2686     return my_overall_color;
2687   }
2688 }
2689
2690 void dump_callgraph(const char *suffix) {
2691   FILE *F;
2692   int i, n_irgs = get_irp_n_irgs();
2693   int rem = edge_label;
2694   edge_label = 1;
2695   //ident *prefix = new_id_from_str("java/");
2696
2697   F = vcg_open_name("Callgraph", suffix);
2698   dump_vcg_header(F, "Callgraph", NULL);
2699
2700   for (i = 0; i < n_irgs; ++i) {
2701     ir_graph *irg = get_irp_irg(i);
2702     entity *ent = get_irg_entity(irg);
2703     int j, n_callees = get_irg_n_callees(irg);
2704
2705     /* Do not dump runtime system. */
2706     //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2707
2708     dump_entity_node(F, ent, get_entity_color(ent));
2709     for (j = 0; j < n_callees; ++j) {
2710       entity *c = get_irg_entity(get_irg_callee(irg, j));
2711       //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2712       int be = is_irg_callee_backedge(irg, j);
2713       char *attr;
2714       attr = (be) ?
2715         "label:\"recursion %d\" color:%d" :
2716         "label:\"calls %d\" color:%d";
2717       print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2718     }
2719   }
2720
2721   edge_label = rem;
2722   vcg_close(F);
2723 }
2724
2725 /* Dump all irgs in interprocedural view to a single file. */
2726 void dump_all_cg_block_graph(const char *suffix) {
2727   FILE *f;
2728   int i;
2729   int rem_view = get_interprocedural_view();
2730   set_interprocedural_view(true);
2731
2732   f = vcg_open_name("All_graphs", suffix);
2733   dump_vcg_header(f, "All_graphs", NULL);
2734
2735   /* collect nodes in all irgs reachable in call graph*/
2736   for (i = 0; i < get_irp_n_irgs(); i++)
2737     ird_set_irg_link(get_irp_irg(i), NULL);
2738
2739   cg_walk(clear_link, collect_node, NULL);
2740
2741   /* dump all graphs */
2742   for (i = 0; i < get_irp_n_irgs(); i++) {
2743     current_ir_graph = get_irp_irg(i);
2744     assert(ird_get_irg_link(current_ir_graph));
2745     dump_graph_from_list(f, current_ir_graph);
2746     DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2747   }
2748
2749   vcg_close(f);
2750   set_interprocedural_view(rem_view);
2751 }
2752
2753 /*---------------------------------------------------------------------*/
2754 /* the following routines dumps type information without any ir nodes. */
2755 /*---------------------------------------------------------------------*/
2756
2757 void
2758 dump_type_graph (ir_graph *irg, const char *suffix)
2759 {
2760   FILE *f;
2761   ir_graph *rem;
2762   rem = current_ir_graph;
2763
2764   /* if a filter is set, dump only the irg's that match the filter */
2765   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2766
2767   current_ir_graph = irg;
2768
2769   f = vcg_open(irg, suffix, "-type");
2770   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2771
2772   /* walk over the blocks in the graph */
2773   type_walk_irg(irg, dump_type_info, NULL, f);
2774   /* The walker for the const code can be called several times for the
2775      same (sub) expression.  So that no nodes are dumped several times
2776      we decrease the visited flag of the corresponding graph after each
2777      walk.  So now increase it finally. */
2778   inc_irg_visited(get_const_code_irg());
2779
2780   vcg_close(f);
2781   current_ir_graph = rem;
2782 }
2783
2784 void
2785 dump_all_types (const char *suffix)
2786 {
2787   FILE *f = vcg_open_name("All_types", suffix);
2788   dump_vcg_header(f, "All_types", NULL);
2789   type_walk(dump_type_info, NULL, f);
2790   inc_irg_visited(get_const_code_irg());
2791   vcg_close(f);
2792 }
2793
2794 void
2795 dump_class_hierarchy (bool entities, const char *suffix)
2796 {
2797   FILE *f = vcg_open_name("class_hierarchy", suffix);
2798   h_env_t env;
2799
2800   env.f = f;
2801   dump_vcg_header(f, "class_hierarchy", NULL);
2802   if (entities)
2803     env.dump_ent = 1;
2804   else
2805     env.dump_ent = 0;
2806   type_walk(dump_class_hierarchy_node, NULL, &env);
2807   vcg_close(f);
2808 }
2809
2810 /*---------------------------------------------------------------------*/
2811 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
2812 /*  dump_ir_graph                                                      */
2813 /*  dump_ir_block_graph                                                */
2814 /*  dump_cfg                                                           */
2815 /*  dump_type_graph                                                    */
2816 /*  dump_ir_graph_w_types                                              */
2817 /*---------------------------------------------------------------------*/
2818
2819 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2820   int i;
2821   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2822     dmp_grph(get_irp_irg(i), suffix);
2823   }
2824 }
2825
2826
2827 /*--------------------------------------------------------------------------------*
2828  * Dumps a stand alone loop graph with firm nodes which belong to one loop node   *
2829  * packed together in one subgraph/box                                            *
2830  *--------------------------------------------------------------------------------*/
2831
2832 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2833   int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2834   loop_element le;
2835   ir_loop *son = NULL;
2836
2837   /* Dump a new loop node. */
2838   dump_loop_node(F, loop);
2839
2840   /* Dump the loop elements. */
2841
2842   for(i = 0; i < get_loop_n_elements(loop); i++) {
2843     le = get_loop_element(loop, i);
2844     son = le.son;
2845     if (get_kind(son) == k_ir_loop) {
2846
2847       /* We are a loop son -> Recurse */
2848
2849       if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2850         fprintf(F, "\" }\n");
2851         fprintf (F, "edge: {sourcename: \"");
2852         PRINT_LOOPID(loop);
2853         fprintf (F, "\" targetname: \"");
2854         PRINT_LOOPID(loop);
2855         fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2856         loop_node_started = 0;
2857       }
2858       dump_loop_son_edge(F, loop, son_number++);
2859       dump_loops_standalone(F, son);
2860     } else if (get_kind(son) == k_ir_node) {
2861       /* We are a loop node -> Collect firm nodes */
2862
2863       ir_node *n = le.node;
2864       int bad = 0;
2865
2866       if (!loop_node_started) {
2867         /* Start a new node which contains all firm nodes of the current loop */
2868         fprintf (F, "node: { title: \"");
2869         PRINT_LOOPID(loop);
2870         fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2871         loop_node_started = 1;
2872         first = i;
2873       }
2874       else
2875         fprintf(F, "\n");
2876
2877       bad |= dump_node_label(F, n);
2878       /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2879       if (has_backedges(n)) fprintf(F, "\t loop head!");
2880     } else { /* for callgraph loop tree */
2881       ir_graph *n;
2882       assert(get_kind(son) == k_ir_graph);
2883
2884       /* We are a loop node -> Collect firm graphs */
2885       n = (ir_graph *)le.node;
2886       if (!loop_node_started) {
2887         /* Start a new node which contains all firm nodes of the current loop */
2888         fprintf (F, "node: { title: \"");
2889         PRINT_LOOPID(loop);
2890         fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2891         loop_node_started = 1;
2892         first = i;
2893       }
2894       else
2895         fprintf(F, "\n");
2896       fprintf (F, " %s", get_irg_dump_name(n));
2897       /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2898     }
2899   }
2900
2901   if (loop_node_started) {
2902     fprintf(F, "\" }\n");
2903     fprintf (F, "edge: {sourcename: \"");
2904     PRINT_LOOPID(loop);
2905     fprintf (F, "\" targetname: \"");
2906     PRINT_LOOPID(loop);
2907     fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2908     loop_node_started = 0;
2909   }
2910 }
2911
2912 void dump_loop_tree(ir_graph *irg, const char *suffix)
2913 {
2914   FILE *f;
2915   ir_graph *rem = current_ir_graph;
2916   int el_rem = edge_label;
2917   edge_label = 1;
2918
2919   /* if a filter is set, dump only the irg's that match the filter */
2920   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2921
2922   current_ir_graph = irg;
2923
2924   f = vcg_open(irg, suffix, "-looptree");
2925   dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2926
2927   if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2928
2929   vcg_close(f);
2930
2931   edge_label = el_rem;
2932   current_ir_graph = rem;
2933 }
2934
2935 void dump_callgraph_loop_tree(const char *suffix) {
2936   FILE *F;
2937   F = vcg_open_name("Callgraph_looptree", suffix);
2938   dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2939   dump_loops_standalone(F, irp->outermost_cg_loop);
2940   vcg_close(F);
2941 }
2942
2943
2944 /*-----------------------------------------------------------------------------*/
2945 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2946 /*-----------------------------------------------------------------------------*/
2947
2948 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2949   int i, son_number = 0, node_number = 0;
2950
2951   if (dump_loop_information_flag) dump_loop_node(F, loop);
2952
2953   for (i = 0; i < get_loop_n_elements(loop); i++) {
2954     loop_element le = get_loop_element(loop, i);
2955     if (*(le.kind) == k_ir_loop) {
2956       if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2957       /* Recur */
2958       collect_nodeloop(F, le.son, loopnodes);
2959     } else {
2960       if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2961       eset_insert(loopnodes, le.node);
2962     }
2963   }
2964 }
2965
2966 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2967   int i, j, start;
2968
2969   for(i = 0; i < get_loop_n_elements(loop); i++) {
2970     loop_element le = get_loop_element(loop, i);
2971     if (*(le.kind) == k_ir_loop) {
2972       /* Recur */
2973       collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2974     } else {
2975       if (is_Block(le.node)) start = 0; else start = -1;
2976       for (j = start; j < get_irn_arity(le.node); j++) {
2977         ir_node *pred = get_irn_n(le.node, j);
2978         if (!eset_contains(loopnodes, pred)) {
2979           eset_insert(extnodes, pred);
2980           if (!is_Block(pred)) {
2981             pred = get_nodes_block(pred);
2982             if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2983           }
2984         }
2985       }
2986     }
2987   }
2988 }
2989
2990 void dump_loop(ir_loop *l, const char *suffix) {
2991   FILE *F;
2992   char name[50];
2993   eset *loopnodes = eset_create();
2994   eset *extnodes = eset_create();
2995   ir_node *n, *b;
2996
2997   snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2998   F = vcg_open_name (name, suffix);
2999   dump_vcg_header(F, name, NULL);
3000
3001   /* collect all nodes to dump */
3002   collect_nodeloop(F, l, loopnodes);
3003   collect_nodeloop_external_nodes(l, loopnodes, extnodes);
3004
3005   /* build block lists */
3006   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3007     set_irn_link(n, NULL);
3008   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3009     set_irn_link(n, NULL);
3010   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3011     if (!is_Block(n)) {
3012       b = get_nodes_block(n);
3013       set_irn_link(n, get_irn_link(b));
3014       set_irn_link(b, n);
3015     }
3016   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3017     if (!is_Block(n)) {
3018       b = get_nodes_block(n);
3019       set_irn_link(n, get_irn_link(b));
3020       set_irn_link(b, n);
3021     }
3022
3023   for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
3024     if (is_Block(b)) {
3025       fprintf(F, "graph: { title: \"");
3026       PRINT_NODEID(b);
3027       fprintf(F, "\"  label: \"");
3028       dump_node_opcode(F, b);
3029       fprintf (F, " %ld", get_irn_node_nr(b));
3030       fprintf(F, "\" status:clustered color:yellow\n");
3031
3032       /* dump the blocks edges */
3033       dump_ir_data_edges(F, b);
3034
3035       /* dump the nodes that go into the block */
3036       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3037         if (eset_contains(extnodes, n))
3038           overrule_nodecolor = ird_color_lightblue;
3039         dump_node(F, n);
3040         overrule_nodecolor = ird_color_default;
3041         if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
3042       }
3043
3044       /* Close the vcg information for the block */
3045       fprintf(F, "}\n");
3046       dump_const_node_local(F, b);
3047       fprintf(F, "\n");
3048     }
3049   for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
3050     if (is_Block(b)) {
3051       fprintf(F, "graph: { title: \"");
3052       PRINT_NODEID(b);
3053       fprintf(F, "\"  label: \"");
3054       dump_node_opcode(F, b);
3055       fprintf (F, " %ld", get_irn_node_nr(b));
3056       fprintf(F, "\" status:clustered color:lightblue\n");
3057
3058       /* dump the nodes that go into the block */
3059       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3060         if (!eset_contains(loopnodes, n))
3061           overrule_nodecolor = ird_color_lightblue;
3062         dump_node(F, n);
3063         overrule_nodecolor = ird_color_default;
3064         if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
3065       }
3066
3067       /* Close the vcg information for the block */
3068       fprintf(F, "}\n");
3069       dump_const_node_local(F, b);
3070       fprintf(F, "\n");
3071     }
3072
3073   eset_destroy(loopnodes);
3074   eset_destroy(extnodes);
3075   vcg_close(F);
3076 }