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