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