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