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