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