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