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