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