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