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