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