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