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