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