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