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