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