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