indentation fixed
[libfirm] / ir / ir / irdump.c
1 /*
2  * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   Write vcg representation of firm to file.
23  * @author  Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Hubert Schmidt
24  * @version $Id$
25  */
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #ifdef HAVE_STRING_H
31 #include <string.h>
32 #endif
33 #ifdef HAVE_STDLIB_H
34 #include <stdlib.h>
35 #endif
36 #include <stdarg.h>
37
38 #include "firm_common_t.h"
39
40 #include "list.h"
41
42 #include "irnode.h"
43 #include "irgraph.h"
44 #include "irprog_t.h"
45 #include "entity_t.h"
46 #include "irop.h"
47
48 #include "irdump_t.h"
49
50 #include "irgwalk.h"
51 #include "tv_t.h"
52 #include "irouts.h"
53 #include "irdom.h"
54 #include "irloop_t.h"
55 #include "callgraph.h"
56 #include "irextbb_t.h"
57 #include "irhooks.h"
58 #include "dbginfo_t.h"
59 #include "irtools.h"
60
61 #include "irvrfy.h"
62
63 #include "error.h"
64 #include "array.h"
65 #include "pmap.h"
66 #include "eset.h"
67 #include "pset.h"
68
69 #if DO_HEAPANALYSIS
70 extern void dump_irn_chi_term(FILE *FL, ir_node *n);
71 extern void dump_irn_state(FILE *FL, ir_node *n);
72 extern int  get_opt_dump_abstvals(void);
73 typedef unsigned long SeqNo;
74 extern SeqNo get_Block_seqno(ir_node *n);
75 #endif
76
77 /* basis for a color range for vcg */
78 static int n_colors   = 0;
79 static int base_color = 0;
80
81 /** Dump only irgs with names that start with this string */
82 static ident *dump_file_filter_id = NULL;
83
84 #define ERROR_TXT       "<ERROR>"
85
86 /*******************************************************************/
87 /* flags to steer output                                           */
88 /*******************************************************************/
89
90 /** An option to turn off edge labels */
91 static int edge_label = 1;
92 /** An option to turn off dumping values of constant entities */
93 static int const_entities = 1;
94 /** An option to dump the keep alive edges */
95 static int dump_keepalive = 0;
96 /** An option to dump ld_names instead of names. */
97 static int dump_ld_name = 1;
98 /** Compiler options to dump analysis information in dump_ir_graph */
99 static int dump_out_edge_flag = 0;
100 static int dump_loop_information_flag = 0;
101 static int dump_backedge_information_flag = 1;
102 static int dump_const_local = 0;
103 /** An option to dump all graph anchors */
104 static int dump_anchors = 0;
105
106 int dump_dominator_information_flag = 0;
107 int opt_dump_analysed_type_info = 1;
108 int opt_dump_pointer_values_to_info = 0;  /* default off: for test compares!! */
109
110 static dumper_colors overrule_nodecolor = ird_color_default;
111
112 /** The vcg node attribute hook. */
113 static DUMP_IR_GRAPH_FUNC dump_ir_graph_hook = NULL;
114 /** The vcg node attribute hook. */
115 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
116 /** The vcg edge attribute hook. */
117 static DUMP_EDGE_VCGATTR_FUNC dump_edge_vcgattr_hook = NULL;
118 /** The vcg dump block edge hook */
119 static DUMP_NODE_EDGE_FUNC dump_block_edge_hook = NULL;
120 /** The vcg dump node edge hook. */
121 static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
122
123 /* Set the hook to be called to dump additional edges to a node. */
124 void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func) {
125         dump_node_edge_hook = func;
126 }
127
128 /* Get the additional edge dump hook. */
129 DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void) {
130         return dump_node_edge_hook;
131 }
132
133 /* Set the hook to be called to dump additional edges to a block. */
134 void set_dump_block_edge_hook(DUMP_NODE_EDGE_FUNC func) {
135         dump_block_edge_hook = func;
136 }
137
138 /* Get the additional block edge dump hook. */
139 DUMP_NODE_EDGE_FUNC get_dump_block_edge_hook(void) {
140         return dump_node_edge_hook;
141 }
142
143 /* set the ir graph hook */
144 void set_dump_ir_graph_hook(DUMP_IR_GRAPH_FUNC hook) {
145         dump_ir_graph_hook = hook;
146 }
147
148 /* set the node attribute hook */
149 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
150         dump_node_vcgattr_hook = hook;
151 }
152
153 /* set the edge attribute hook */
154 void set_dump_edge_vcgattr_hook(DUMP_EDGE_VCGATTR_FUNC hook) {
155         dump_edge_vcgattr_hook = hook;
156 }
157
158 /* Returns 0 if dump_out_edge_flag or dump_loop_information_flag
159  * are set, else returns dump_const_local_flag.
160  */
161 int get_opt_dump_const_local(void) {
162         if (!dump_out_edge_flag && !dump_loop_information_flag)
163                 return dump_const_local;
164         else
165                 return 0;
166 }
167
168 /* Set a prefix filter for output functions. */
169 void only_dump_method_with_name(ident *name) {
170         dump_file_filter_id = name;
171 }
172
173 /* Returns the prefix filter set with only_dump_method_with_name(). */
174 ident *get_dump_file_filter_ident(void) {
175         return dump_file_filter_id;
176 }
177
178 /* Returns non-zero if dump file filter is not set, or if it is a prefix of name. */
179 int is_filtered_dump_name(ident *name) {
180         if (!dump_file_filter_id) return 1;
181         return id_is_prefix(dump_file_filter_id, name);
182 }
183
184 /* To turn off display of edge labels.  Edge labels often cause xvcg to
185    abort with a segmentation fault. */
186 void turn_off_edge_labels(void) {
187         edge_label = 0;
188 }
189
190 void dump_consts_local(int flag) {
191         dump_const_local = flag;
192 }
193
194 void dump_constant_entity_values(int flag) {
195         const_entities = flag;
196 }
197
198 void dump_keepalive_edges(int flag) {
199         dump_keepalive = flag;
200 }
201
202 int get_opt_dump_keepalive_edges(void) {
203         return dump_keepalive;
204 }
205
206 void dump_out_edges(int flag) {
207         dump_out_edge_flag = flag;
208 }
209
210 void dump_dominator_information(int flag) {
211         dump_dominator_information_flag = flag;
212 }
213
214 void dump_loop_information(int flag) {
215         dump_loop_information_flag = flag;
216 }
217
218 void dump_backedge_information(int flag) {
219         dump_backedge_information_flag = flag;
220 }
221
222 /* Dump the information of type field specified in ana/irtypeinfo.h.
223  * If the flag is set, the type name is output in [] in the node label,
224  * else it is output as info.
225  */
226 void set_opt_dump_analysed_type_info(int flag) {
227         opt_dump_analysed_type_info = flag;
228 }
229
230 void dump_pointer_values_to_info(int flag) {
231         opt_dump_pointer_values_to_info = flag;
232 }
233
234 void dump_ld_names(int flag) {
235         dump_ld_name = flag;
236 }
237
238 void dump_all_anchors(int flag) {
239         dump_anchors = flag;
240 }
241
242 /* -------------- some extended helper functions ----------------- */
243
244 /**
245  * returns the name of a mode or <ERROR> if mode is NOT a mode object.
246  * in the later case, sets bad
247  */
248 const char *get_mode_name_ex(ir_mode *mode, int *bad) {
249         if (is_mode(mode))
250                 return get_mode_name(mode);
251         *bad |= 1;
252         return ERROR_TXT;
253 }
254
255 /**
256  * returns the name of a type or <ERROR> if mode is NOT a mode object.
257  * in the later case, sets bad
258  */
259 const char *get_type_name_ex(ir_type *tp, int *bad) {
260         if (is_type(tp))
261                 return get_type_name(tp);
262         *bad |= 1;
263         return ERROR_TXT;
264 }
265
266 /**
267  * printf the VCG color to a file
268  */
269 static void print_vcg_color(FILE *F, dumper_colors color) {
270         static const char *color_names[32] = {
271                 "white",        "blue",      "red",        "green",
272                 "yellow",       "magenta",   "cyan",       "darkgray",
273                 "darkblue",     "darkred",   "darkgreen",  "darkyellow",
274                 "darkmagenta",  "darkcyan",  "gold",       "lightgray",
275                 "lightblue",    "lightred",  "lightgreen", "lightyellow",
276                 "lightmagenta", "lightcyan", "lilac",      "turquoise",
277                 "aquamarine",   "khaki",     "purple",     "yellowgreen",
278                 "pink",         "orange",    "orchid",     "black"
279         };
280
281         if (color != ird_color_default)
282                 fprintf(F, "color:%s", color_names[color]);
283 }
284
285 /**
286  * prints the edge from a type S to a type T with additional info fmt, ...
287  * to the file F
288  */
289 static void print_type_type_edge(FILE *F, ir_type *S, ir_type *T, const char *fmt, ...)
290 {
291         va_list ap;
292
293         va_start(ap, fmt);
294         fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
295         fprintf(F, " targetname: "); PRINT_TYPEID(T);
296         vfprintf(F, fmt, ap);
297         fprintf(F,"}\n");
298         va_end(ap);
299 }
300
301 /**
302  * prints the edge from a type T to an entity E with additional info fmt, ...
303  * to the file F
304  */
305 static void print_type_ent_edge(FILE *F, ir_type *T, ir_entity *E, const char *fmt, ...)
306 {
307         va_list ap;
308
309         va_start(ap, fmt);
310         fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
311         fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
312         vfprintf(F, fmt, ap);
313         fprintf(F, "}\n");
314         va_end(ap);
315 }
316
317 /**
318  * prints the edge from an entity E to an entity T with additional info fmt, ...
319  * to the file F
320  */
321 static void print_ent_ent_edge(FILE *F, ir_entity *E, ir_entity *T, int backedge, const char *fmt, ...)
322 {
323         va_list ap;
324
325         va_start(ap, fmt);
326         if (backedge)
327                 fprintf(F, "backedge: { sourcename: \"");
328         else
329                 fprintf(F, "edge: { sourcename: \"");
330         PRINT_ENTID(E);
331         fprintf(F, "\" targetname: \""); PRINT_ENTID(T);  fprintf(F, "\"");
332         vfprintf(F, fmt, ap);
333         fprintf(F, "}\n");
334         va_end(ap);
335 }
336
337 /**
338  * prints the edge from an entity E to a type T with additional info fmt, ...
339  * to the file F
340  */
341 static void print_ent_type_edge(FILE *F, ir_entity *E, ir_type *T, const char *fmt, ...)
342 {
343         va_list ap;
344
345         va_start(ap, fmt);
346         fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
347         fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
348         vfprintf(F, fmt, ap);
349         fprintf(F,"}\n");
350         va_end(ap);
351 }
352
353 /**
354  * prints the edge from a node N to a type T with additional info fmt, ...
355  * to the file F
356  */
357 static void print_node_type_edge(FILE *F, const ir_node *N, ir_type *T, const char *fmt, ...)
358 {
359         va_list ap;
360
361         va_start(ap, fmt);
362         fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
363         fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
364         vfprintf(F, fmt, ap);
365         fprintf(F,"}\n");
366         va_end(ap);
367 }
368
369 /**
370  * prints the edge from a node N to an entity E with additional info fmt, ...
371  * to the file F
372  */
373 static void print_node_ent_edge(FILE *F, const ir_node *N, ir_entity *E, const char *fmt, ...)
374 {
375         va_list ap;
376
377         va_start(ap, fmt);
378         fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
379         fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
380         fprintf(F, "\"");
381         vfprintf(F, fmt, ap);
382         fprintf(F,"}\n");
383         va_end(ap);
384 }
385
386 /**
387  * prints the edge from an entity E to a node N with additional info fmt, ...
388  * to the file F
389  */
390 static void print_ent_node_edge(FILE *F, ir_entity *E, const ir_node *N, const char *fmt, ...)
391 {
392         va_list ap;
393
394         va_start(ap, fmt);
395         fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
396         fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
397         vfprintf(F, fmt, ap);
398         fprintf(F,"}\n");
399         va_end(ap);
400 }
401
402 /**
403  * prints the edge from a type E to an enumeration item item with additional info fmt, ...
404  * to the file F
405  */
406 static void print_enum_item_edge(FILE *F, ir_type *E, int item, const char *fmt, ...)
407 {
408         va_list ap;
409
410         va_start(ap, fmt);
411         fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
412         fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
413         vfprintf(F, fmt, ap);
414         fprintf(F,"}\n");
415         va_end(ap);
416 }
417
418 /*-----------------------------------------------------------------*/
419 /* global and ahead declarations                                   */
420 /*-----------------------------------------------------------------*/
421
422 static void dump_whole_node(ir_node *n, void *env);
423 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
424
425 /*-----------------------------------------------------------------*/
426 /* Helper functions.                                                */
427 /*-----------------------------------------------------------------*/
428
429 /**
430  * This map is used as a private link attr to be able to call dumper
431  * anywhere without destroying link fields.
432  */
433 static pmap *irdump_link_map = NULL;
434
435 /** NOT A STANDARD LIBFIRM INIT METHOD
436  *
437  * We do not want to integrate dumping into libfirm, i.e., if the dumpers
438  * are off, we want to have as few interferences as possible.  Therefore the
439  * initialization is performed lazily and not called from within init_firm.
440  *
441  * Creates the link attribute map. */
442 static void init_irdump(void) {
443         /* We need a new, empty map. */
444         if (irdump_link_map) pmap_destroy(irdump_link_map);
445         irdump_link_map = pmap_create();
446         if (!dump_file_filter_id)
447                 dump_file_filter_id = new_id_from_str("");
448 }
449
450 /**
451  * Returns the private link field.
452  */
453 static void *ird_get_irn_link(ir_node *n) {
454         void *res = NULL;
455         if (!irdump_link_map) return NULL;
456
457         if (pmap_contains(irdump_link_map, (void *)n))
458                 res = pmap_get(irdump_link_map, (void *)n);
459         return res;
460 }
461
462 /**
463  * Sets the private link field.
464  */
465 static void ird_set_irn_link(ir_node *n, void *x) {
466         if (!irdump_link_map)
467                 init_irdump();
468         pmap_insert(irdump_link_map, (void *)n, x);
469 }
470
471 /**
472  * Gets the private link field of an irg.
473  */
474 static void *ird_get_irg_link(ir_graph *irg) {
475         void *res = NULL;
476         if (!irdump_link_map) return NULL;
477
478         if (pmap_contains(irdump_link_map, (void *)irg))
479                 res = pmap_get(irdump_link_map, (void *)irg);
480         return res;
481 }
482
483 /**
484  * Sets the private link field of an irg.
485  */
486 static void ird_set_irg_link(ir_graph *irg, void *x) {
487         if (!irdump_link_map) init_irdump();
488         pmap_insert(irdump_link_map, (void *)irg, x);
489 }
490
491 /**
492  * Walker, clears the private link field.
493  */
494 static void clear_link(ir_node * node, void * env) {
495         (void) env;
496         ird_set_irn_link(node, NULL);
497 }
498
499 /**
500  * If the entity has a ld_name, returns it if the dump_ld_name is set,
501  * else returns the name of the entity.
502  */
503 static const char *_get_ent_dump_name(ir_entity *ent, int dump_ld_name) {
504         if (!ent)
505                 return "<NULL entity>";
506         if (dump_ld_name) {
507                 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
508                 if (ent->ld_name) return get_id_str(ent->ld_name);
509         }
510         return get_id_str(ent->name);
511 }
512
513 /**
514  * If the entity has a ld_name, returns it if the option dump_ld_name is set,
515  * else returns the name of the entity.
516  */
517 const char *get_ent_dump_name(ir_entity *ent) {
518         return _get_ent_dump_name(ent, dump_ld_name);
519 }
520
521 /* Returns the name of an IRG. */
522 const char *get_irg_dump_name(ir_graph *irg) {
523         /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
524         return _get_ent_dump_name(get_irg_entity(irg), 1);
525 }
526
527 /**
528  * Returns non-zero if a node is in floating state.
529  */
530 static int node_floats(ir_node *n) {
531         return ((get_irn_pinned(n) == op_pin_state_floats) &&
532                 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
533 }
534
535 /**
536  *  Walker that visits the anchors
537  */
538 static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
539         if (dump_anchors) {
540                 irg_walk_anchors(irg, pre, post, env);
541         } else {
542                 irg_walk_graph(irg, pre, post, env);
543         }
544 }
545
546 /**
547  * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
548  */
549 static void collect_node(ir_node * node, void *env) {
550         (void) env;
551         if (is_Block(node)
552             || node_floats(node)
553             || get_irn_op(node) == op_Bad
554             || get_irn_op(node) == op_Unknown
555             || get_irn_op(node) == op_NoMem) {
556                 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
557                 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
558                 ARR_APP1(ir_node *, arr, node);
559                 ird_set_irg_link(get_irn_irg(node), arr);    /* arr is an l-value, APP_ARR might change it! */
560         } else {
561                 ir_node * block = get_nodes_block(node);
562
563                 if (is_Bad(block)) {
564                         /* this node is in a Bad block, so we must place it into the graph's list */
565                         ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
566                         if (!arr) arr = NEW_ARR_F(ir_node *, 0);
567                         ARR_APP1(ir_node *, arr, node);
568                         ird_set_irg_link(get_irn_irg(node), arr);    /* arr is an l-value, APP_ARR might change it! */
569                 } else {
570                         ird_set_irn_link(node, ird_get_irn_link(block));
571                         ird_set_irn_link(block, node);
572                 }
573         }
574 }
575
576 /** Construct lists to walk ir block-wise.
577  *
578  * Collects all blocks, nodes not op_pin_state_pinned,
579  * Bad, NoMem and Unknown into a flexible array in link field of
580  * irg they belong to.  Sets the irg link field to NULL in all
581  * graphs not visited.
582  * Free the list with DEL_ARR_F().
583  */
584 static ir_node **construct_block_lists(ir_graph *irg) {
585         int      i;
586         int      rem_view  = get_interprocedural_view();
587         int      walk_flag = using_visited(irg);
588         ir_graph *rem      = current_ir_graph;
589
590         current_ir_graph = irg;
591
592         if(walk_flag)
593                 clear_using_visited(current_ir_graph);
594
595         for (i = get_irp_n_irgs() - 1; i >= 0; --i)
596                 ird_set_irg_link(get_irp_irg(i), NULL);
597
598         ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
599
600         /* Collect also EndReg and EndExcept. We do not want to change the walker. */
601         set_interprocedural_view(0);
602
603         set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
604         irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
605         set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
606         irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
607
608         set_interprocedural_view(rem_view);
609
610         if(walk_flag)
611                 set_using_visited(current_ir_graph);
612
613         current_ir_graph = rem;
614         return ird_get_irg_link(irg);
615 }
616
617 typedef struct _list_tuple {
618         ir_node **blk_list;
619         ir_extblk **extbb_list;
620 } list_tuple;
621
622 /** Construct lists to walk IR extended block-wise.
623  * Free the lists in the tuple with DEL_ARR_F().
624  * Sets the irg link field to NULL in all
625  * graphs not visited.
626  */
627 static list_tuple *construct_extblock_lists(ir_graph *irg) {
628         ir_node **blk_list = construct_block_lists(irg);
629         int i;
630         ir_graph *rem = current_ir_graph;
631         list_tuple *lists = xmalloc(sizeof(*lists));
632
633         current_ir_graph = irg;
634
635         lists->blk_list   = NEW_ARR_F(ir_node *, 0);
636         lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
637
638         inc_irg_block_visited(irg);
639         for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
640                 ir_extblk *ext;
641
642                 if (is_Block(blk_list[i])) {
643                         ext = get_Block_extbb(blk_list[i]);
644
645                         if (extbb_not_visited(ext)) {
646                                 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
647                                 mark_extbb_visited(ext);
648                         }
649                 } else
650                         ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
651         }
652         DEL_ARR_F(blk_list);
653
654         current_ir_graph = rem;
655         ird_set_irg_link(irg, lists);
656         return lists;
657 }
658
659 /*-----------------------------------------------------------------*/
660 /* Routines to dump information about a single ir node.            */
661 /*-----------------------------------------------------------------*/
662
663 /*
664  * dump the name of a node n to the File F.
665  */
666 int dump_node_opcode(FILE *F, ir_node *n)
667 {
668         int bad = 0;
669         const ir_op_ops *ops = get_op_ops(get_irn_op(n));
670
671         /* call the dump_node operation if available */
672         if (ops->dump_node)
673                 return ops->dump_node(n, F, dump_node_opcode_txt);
674
675         /* implementation for default nodes */
676         switch (get_irn_opcode(n)) {
677
678         case iro_Const: {
679                 int res;
680                 char buf[1024];
681                 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
682                 assert(res < (int) sizeof(buf) && "buffer to small for tarval_snprintf");
683                 fprintf(F, buf);
684         } break;
685
686         case iro_SymConst: {
687                 switch (get_SymConst_kind(n)) {
688                 case symconst_addr_name:
689                         /* don't use get_SymConst_ptr_info as it mangles the name. */
690                         fprintf(F, "SymC %s", get_id_str(get_SymConst_name(n)));
691                         break;
692                 case symconst_addr_ent:
693                         fprintf(F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
694                         break;
695                 case symconst_ofs_ent:
696                         fprintf(F, "SymC %s offset", get_entity_name(get_SymConst_entity(n)));
697                         break;
698                 case symconst_type_tag:
699                         fprintf(F, "SymC %s tag", get_type_name_ex(get_SymConst_type(n), &bad));
700                         break;
701                 case symconst_type_size:
702                         fprintf(F, "SymC %s size", get_type_name_ex(get_SymConst_type(n), &bad));
703                         break;
704                 case symconst_type_align:
705                         fprintf(F, "SymC %s align", get_type_name_ex(get_SymConst_type(n), &bad));
706                         break;
707                 case symconst_enum_const:
708                         fprintf(F, "SymC %s enum", get_enumeration_name(get_SymConst_enum(n)));
709                         break;
710                 case symconst_label:
711                         fprintf(F, "SymC %lu label", get_SymConst_label(n));
712                         break;
713                 }
714         } break;
715
716         case iro_Filter: {
717                 if (!get_interprocedural_view())
718                         fprintf(F, "Proj'");
719                 else
720                         goto default_case;
721         } break;
722
723         case iro_Proj: {
724                 ir_node *pred = get_Proj_pred(n);
725
726                 if (get_irn_opcode(pred) == iro_Cond
727                         && get_Proj_proj(n) == get_Cond_defaultProj(pred)
728                         && get_irn_mode(get_Cond_selector(pred)) != mode_b)
729                         fprintf(F, "defProj");
730                 else
731                         goto default_case;
732         } break;
733         case iro_Start:
734         case iro_End:
735         case iro_EndExcept:
736         case iro_EndReg: {
737                 if (get_interprocedural_view()) {
738                         fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
739                         break;
740                 } else
741                         goto default_case;
742         }
743         case iro_CallBegin: {
744                 ir_node *addr = get_CallBegin_ptr(n);
745                 ir_entity *ent = NULL;
746                 if (get_irn_op(addr) == op_Sel)
747                         ent = get_Sel_entity(addr);
748                 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
749                         ent = get_SymConst_entity(addr);
750                 fprintf(F, "%s", get_irn_opname(n));
751                 if (ent) fprintf(F, " %s", get_entity_name(ent));
752                 break;
753         }
754         case iro_Load:
755                 if (get_Load_align(n) == align_non_aligned)
756                         fprintf(F, "ua");
757                 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
758                 break;
759         case iro_Store:
760                 if (get_Store_align(n) == align_non_aligned)
761                         fprintf(F, "ua");
762                 fprintf(F, "%s", get_irn_opname(n));
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 /** Print the vcg attributes for the edge from node from to it's to's input */
1432 static void 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, KEEP_ALIVE_CF_EDGE_ATTR);
1451                         else
1452                                 fprintf(F, KEEP_ALIVE_DF_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 dump_ir_data_edges(FILE *F, ir_node *n)  {
1475         int i;
1476         unsigned long visited = get_irn_visited(n);
1477
1478         if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1479                 return;
1480
1481         /* dump the dependency edges. */
1482         for (i = 0; i < get_irn_deps(n); ++i) {
1483                 ir_node *dep = get_irn_dep(n, i);
1484
1485                 if(dep) {
1486                         fprintf(F, "edge: {sourcename: \"");
1487                         PRINT_NODEID(n);
1488                         fprintf(F, "\" targetname: ");
1489                         if ((get_opt_dump_const_local()) && is_constlike_node(dep)) {
1490                                 PRINT_CONSTID(n, dep);
1491                         } else {
1492                                 fprintf(F, "\"");
1493                                 PRINT_NODEID(dep);
1494                                 fprintf(F, "\"");
1495                         }
1496                         fprintf(F, " label: \"%d\" ", i);
1497                         fprintf(F, " color: darkgreen}\n");
1498                 }
1499         }
1500
1501         for (i = 0; i < get_irn_arity(n); i++) {
1502                 ir_node * pred = get_irn_n(n, i);
1503                 assert(pred);
1504
1505                 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1506                         continue; /* pred not dumped */
1507
1508                 if (dump_backedge_information_flag && is_backedge(n, i))
1509                         fprintf(F, "backedge: {sourcename: \"");
1510                 else
1511                         fprintf(F, "edge: {sourcename: \"");
1512                 PRINT_NODEID(n);
1513                 fprintf(F, "\" targetname: ");
1514                 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1515                         PRINT_CONSTID(n, pred);
1516                 } else {
1517                         fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1518                 }
1519                 fprintf(F, " label: \"%d\" ", i);
1520                 print_edge_vcgattr(F, n, i);
1521                 fprintf(F, "}\n");
1522         }
1523 }
1524
1525 /** Dumps a node and its edges but not the block edge
1526  */
1527 static INLINE void
1528 dump_node_wo_blockedge(ir_node *n, void *env) {
1529         FILE *F = env;
1530         dump_node(F, n);
1531         dump_ir_data_edges(F, n);
1532 }
1533
1534 /** Dumps a node and its edges.
1535  */
1536 static void
1537 dump_whole_node(ir_node *n, void *env) {
1538         FILE *F = env;
1539         dump_node_wo_blockedge(n, env);
1540         if (!node_floats(n)) dump_ir_block_edge(F, n);
1541 }
1542
1543 static void
1544 dump_const_node(ir_node *n, void *env) {
1545         if (is_Block(n)) return;
1546         dump_node_wo_blockedge(n, env);
1547 }
1548
1549 /***********************************************************************/
1550 /* the following routines dump the nodes/irgs bracketed to graphs.     */
1551 /***********************************************************************/
1552
1553 /** Dumps a constant expression as entity initializer, array bound ...
1554  */
1555 static void dump_const_expression(FILE *F, ir_node *value) {
1556         ir_graph *rem = current_ir_graph;
1557         int rem_dump_const_local = dump_const_local;
1558         dump_const_local = 0;
1559         current_ir_graph = get_const_code_irg();
1560         irg_walk(value, dump_const_node, NULL, F);
1561         /* Decrease visited flag so that we walk with the same flag for the next
1562            expression.  This guarantees that we don't dump the same node twice,
1563            as for const expressions cse is performed to save memory. */
1564         set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1565         current_ir_graph = rem;
1566         dump_const_local = rem_dump_const_local;
1567 }
1568
1569 /** Dump a block as graph containing its nodes.
1570  *
1571  *  Expects to find nodes belonging to the block as list in its
1572  *  link field.
1573  *  Dumps the edges of all nodes including itself. */
1574 static void
1575 dump_whole_block(FILE *F, ir_node *block) {
1576         ir_node *node;
1577         dumper_colors color = ird_color_yellow;
1578
1579         assert(is_Block(block));
1580
1581         fprintf(F, "graph: { title: \"");
1582         PRINT_NODEID(block);
1583         fprintf(F, "\"  label: \"");
1584         dump_node_label(F, block);
1585 #if DO_HEAPANALYSIS
1586         if (get_opt_dump_abstvals())
1587                 fprintf(F, " seqno: %d", (int)get_Block_seqno(block));
1588 #endif
1589
1590         /* colorize blocks */
1591         if (! get_Block_matured(block))
1592                 color = ird_color_red;
1593         if (is_Block_dead(block))
1594                 color = ird_color_orange;
1595
1596         fprintf(F, "\" status:clustered ");
1597         print_vcg_color(F, color);
1598         fprintf(F, "\n");
1599
1600         /* yComp can show attributes for blocks, XVCG parses but ignores them */
1601         dump_node_info(F, block);
1602         print_dbg_info(F, get_irn_dbg_info(block));
1603
1604         /* dump the blocks edges */
1605         dump_ir_data_edges(F, block);
1606
1607         if (dump_block_edge_hook)
1608                 dump_block_edge_hook(F, block);
1609
1610         /* dump the nodes that go into the block */
1611         for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1612                 dump_node(F, node);
1613                 dump_ir_data_edges(F, node);
1614         }
1615
1616         /* Close the vcg information for the block */
1617         fprintf(F, "}\n");
1618         dump_const_node_local(F, block);
1619 #if DO_HEAPANALYSIS
1620         dump_irn_chi_term(F, block);
1621 #endif
1622         fprintf(F, "\n");
1623 }
1624
1625 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1626  *  The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1627 static void
1628 dump_block_graph(FILE *F, ir_graph *irg) {
1629         int i;
1630         ir_graph *rem = current_ir_graph;
1631         ir_node **arr = ird_get_irg_link(irg);
1632         current_ir_graph = irg;
1633
1634         for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1635                 ir_node * node = arr[i];
1636                 if (is_Block(node)) {
1637                 /* Dumps the block and all the nodes in the block, which are to
1638                         be found in Block->link. */
1639                         dump_whole_block(F, node);
1640                 } else {
1641                         /* Nodes that are not in a Block. */
1642                         dump_node(F, node);
1643                         if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1644                                 dump_const_block_local(F, node);
1645                         }
1646                         dump_ir_data_edges(F, node);
1647                 }
1648         }
1649
1650         if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1651                 dump_loop_nodes_into_graph(F, irg);
1652
1653         current_ir_graph = rem;
1654 }
1655
1656 /**
1657  * Dump the info for an irg.
1658  * Parsed by XVCG but not shown. use yComp.
1659  */
1660 static void dump_graph_info(FILE *F, ir_graph *irg) {
1661         fprintf(F, "info1: \"");
1662         dump_entity_to_file(F, get_irg_entity(irg), dump_verbosity_entattrs | dump_verbosity_entconsts);
1663         fprintf(F, "\"\n");
1664 }
1665
1666 /** Dumps an irg as a graph clustered by block nodes.
1667  *  If interprocedural view edges can point to nodes out of this graph.
1668  */
1669 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1670         ir_entity *ent = get_irg_entity(irg);
1671
1672         fprintf(F, "graph: { title: \"");
1673         PRINT_IRGID(irg);
1674         fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1675           get_ent_dump_name(ent));
1676
1677         dump_graph_info(F, irg);
1678         print_dbg_info(F, get_entity_dbg_info(ent));
1679
1680         dump_block_graph(F, irg);
1681
1682         /* Close the vcg information for the irg */
1683         fprintf(F, "}\n\n");
1684 }
1685
1686 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1687  *  The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1688 static void
1689 dump_extblock_graph(FILE *F, ir_graph *irg) {
1690         int i;
1691         ir_graph *rem = current_ir_graph;
1692         ir_extblk **arr = ird_get_irg_link(irg);
1693         current_ir_graph = irg;
1694
1695         for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1696                 ir_extblk *extbb = arr[i];
1697                 ir_node *leader = get_extbb_leader(extbb);
1698                 int j;
1699
1700                 fprintf(F, "graph: { title: \"");
1701                 PRINT_EXTBBID(leader);
1702                 fprintf(F, "\"  label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1703                         get_irn_node_nr(leader));
1704
1705                 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1706                         ir_node * node = extbb->blks[j];
1707                         if (is_Block(node)) {
1708                         /* Dumps the block and all the nodes in the block, which are to
1709                                 be found in Block->link. */
1710                                 dump_whole_block(F, node);
1711                         } else {
1712                                 /* Nodes that are not in a Block. */
1713                                 dump_node(F, node);
1714                                 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1715                                         dump_const_block_local(F, node);
1716                                 }
1717                                 dump_ir_data_edges(F, node);
1718                         }
1719                 }
1720                 fprintf(F, "}\n");
1721         }
1722
1723         if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1724                 dump_loop_nodes_into_graph(F, irg);
1725
1726         current_ir_graph = rem;
1727         free_extbb(irg);
1728 }
1729
1730
1731 /*******************************************************************/
1732 /* Basic type and entity nodes and edges.                          */
1733 /*******************************************************************/
1734
1735 /** dumps the edges between nodes and their type or entity attributes. */
1736 static void dump_node2type_edges(ir_node *n, void *env)
1737 {
1738         FILE *F = env;
1739         assert(n);
1740
1741         switch (get_irn_opcode(n)) {
1742         case iro_Const :
1743                 /* @@@ some consts have an entity */
1744                 break;
1745         case iro_SymConst:
1746                 if (SYMCONST_HAS_TYPE(get_SymConst_kind(n)))
1747                         print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1748                 break;
1749         case iro_Sel:
1750                 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1751                 break;
1752         case iro_Call:
1753                 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1754                 break;
1755         case iro_Alloc:
1756                 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1757                 break;
1758         case iro_Free:
1759                 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1760                 break;
1761         case iro_Cast:
1762                 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1763                 break;
1764         default:
1765                 break;
1766         }
1767 }
1768
1769 #if 0
1770 static int print_type_info(FILE *F, ir_type *tp) {
1771         int bad = 0;
1772
1773         if (get_type_state(tp) == layout_undefined) {
1774                 fprintf(F, "state: layout_undefined\n");
1775         } else {
1776                 fprintf(F, "state: layout_fixed,\n");
1777         }
1778         if (get_type_mode(tp))
1779                 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1780         fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1781
1782         return bad;
1783 }
1784
1785 static void print_typespecific_info(FILE *F, ir_type *tp) {
1786         switch (get_type_tpop_code(tp)) {
1787         case tpo_class:
1788                 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1789                 break;
1790         case tpo_struct:
1791                 break;
1792         case tpo_method:
1793                 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1794                 fprintf(F, "params: %d\n", get_method_n_params(tp));
1795                 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1796                 break;
1797         case tpo_union:
1798                 break;
1799         case tpo_array:
1800                 break;
1801         case tpo_enumeration:
1802                 break;
1803         case tpo_pointer:
1804                 break;
1805         case tpo_primitive:
1806                 break;
1807         default:
1808                 break;
1809         } /* switch type */
1810 }
1811 #endif
1812
1813 static void print_typespecific_vcgattr(FILE *F, ir_type *tp) {
1814         switch (get_type_tpop_code(tp)) {
1815         case tpo_class:
1816                 if (peculiarity_existent == get_class_peculiarity(tp))
1817                         fprintf(F, " " TYPE_CLASS_NODE_ATTR);
1818                 else
1819                         fprintf(F, " " TYPE_DESCRIPTION_NODE_ATTR);
1820                 break;
1821         case tpo_struct:
1822                 fprintf(F, " " TYPE_METH_NODE_ATTR);
1823                 break;
1824         case tpo_method:
1825                 break;
1826         case tpo_union:
1827                 break;
1828         case tpo_array:
1829                 break;
1830         case tpo_enumeration:
1831                 break;
1832         case tpo_pointer:
1833                 break;
1834         case tpo_primitive:
1835                 break;
1836         default:
1837                 break;
1838         } /* switch type */
1839 }
1840
1841
1842 int dump_type_node(FILE *F, ir_type *tp)
1843 {
1844         int bad = 0;
1845
1846         fprintf(F, "node: {title: ");
1847         PRINT_TYPEID(tp);
1848         fprintf(F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1849         fprintf(F, " info1: \"");
1850 #if 0
1851         bad |= print_type_info(F, tp);
1852         print_typespecific_info(F, tp);
1853 #else
1854         dump_type_to_file(F, tp, dump_verbosity_max);
1855 #endif
1856         fprintf(F, "\"\n");
1857         print_dbg_info(F, get_type_dbg_info(tp));
1858         print_typespecific_vcgattr(F, tp);
1859         fprintf(F, "}\n");
1860
1861         return bad;
1862 }
1863
1864
1865 void dump_entity_node(FILE *F, ir_entity *ent, int color)
1866 {
1867         fprintf(F, "node: {title: \"");
1868         PRINT_ENTID(ent); fprintf(F, "\"");
1869         fprintf(F, DEFAULT_TYPE_ATTRIBUTE);
1870         fprintf(F, "label: ");
1871         fprintf(F, "\"ent %s\" ", get_ent_dump_name(ent));
1872         if (color)
1873                 fprintf(F, "color:%d", color);
1874         else
1875                 fprintf(F, ENTITY_NODE_ATTR);
1876         fprintf(F, "\n info1: \"");
1877
1878         dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1879
1880         fprintf(F, "\"\n");
1881         print_dbg_info(F, get_entity_dbg_info(ent));
1882         fprintf(F, "}\n");
1883 }
1884
1885 static void dump_enum_item(FILE *F, ir_type *tp, int pos)
1886 {
1887         char buf[1024];
1888         ir_enum_const *ec = get_enumeration_const(tp, pos);
1889         ident         *id = get_enumeration_nameid(ec);
1890         tarval        *tv = get_enumeration_value(ec);
1891
1892         if (tv)
1893                 tarval_snprintf(buf, sizeof(buf), tv);
1894         else
1895                 strncpy(buf, "<not set>", sizeof(buf));
1896         fprintf(F, "node: {title: \"");
1897         PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1898         fprintf(F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1899         fprintf(F, "label: ");
1900         fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1901         fprintf(F, "\n info1: \"value: %s\"}\n", buf);
1902 }
1903
1904 /* dumps a type or entity and it's edges. */
1905 static void
1906 dump_type_info(type_or_ent *tore, void *env) {
1907         FILE *F = env;
1908         int i = 0;  /* to shutup gcc */
1909
1910         /* dump this type or entity */
1911
1912         switch (get_kind(tore)) {
1913         case k_entity: {
1914                 ir_entity *ent = (ir_entity *)tore;
1915                 ir_node *value;
1916                 /* The node */
1917                 dump_entity_node(F, ent, 0);
1918                 /* The Edges */
1919                 /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
1920                 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1921                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1922                 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1923                 if (is_Class_type(get_entity_owner(ent))) {
1924                         for(i = 0; i < get_entity_n_overwrites(ent); i++)
1925                                 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1926                 }
1927                 /* attached subgraphs */
1928                 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1929                         if (is_atomic_entity(ent)) {
1930                                 value = get_atomic_ent_value(ent);
1931                                 if (value) {
1932                                         print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1933                                         /* DDMN(value);  $$$ */
1934                                         dump_const_expression(F, value);
1935                                 }
1936                         }
1937                         if (is_compound_entity(ent)) {
1938                                 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1939                                         value = get_compound_ent_value(ent, i);
1940                                         if (value) {
1941                                                 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1942                                                 dump_const_expression(F, value);
1943                                                 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1944                                                 /*
1945                                                 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1946                                                 ENT_CORR_EDGE_ATTR  "}\n", GET_ENTID(ent),
1947                                                 get_compound_ent_value_member(ent, i), i);
1948                                                 */
1949                                         }
1950                                 }
1951                         }
1952                 }
1953                 break;
1954         }
1955         case k_type: {
1956                 ir_type *tp = (ir_type *)tore;
1957                 dump_type_node(F, tp);
1958                 /* and now the edges */
1959                 switch (get_type_tpop_code(tp)) {
1960                 case tpo_class:
1961                         for (i=0; i < get_class_n_supertypes(tp); i++)
1962                                 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1963                         for (i=0; i < get_class_n_members(tp); i++)
1964                                 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1965                         break;
1966                 case tpo_struct:
1967                         for (i=0; i < get_struct_n_members(tp); i++)
1968                                 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1969                         break;
1970                 case tpo_method:
1971                         for (i = 0; i < get_method_n_params(tp); i++)
1972                                 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1973                         for (i = 0; i < get_method_n_ress(tp); i++)
1974                                 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1975                         break;
1976                 case tpo_union:
1977                         for (i = 0; i < get_union_n_members(tp); i++)
1978                                 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1979                         break;
1980                 case tpo_array:
1981                         print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1982                         print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1983                         for (i = 0; i < get_array_n_dimensions(tp); i++) {
1984                                 ir_node *upper = get_array_upper_bound(tp, i);
1985                                 ir_node *lower = get_array_lower_bound(tp, i);
1986                                 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1987                                 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1988                                 dump_const_expression(F, upper);
1989                                 dump_const_expression(F, lower);
1990                         }
1991                         break;
1992                 case tpo_enumeration:
1993                         for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1994                                 dump_enum_item(F, tp, i);
1995                                 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1996                         }
1997                         break;
1998                 case tpo_pointer:
1999                         print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
2000                         break;
2001                 case tpo_primitive:
2002                         break;
2003                 default:
2004                         break;
2005                 } /* switch type */
2006                 break; /* case k_type */
2007         }
2008         default:
2009                 printf(" *** irdump,  dump_type_info(l.%i), faulty type.\n", __LINE__);
2010         } /* switch kind_or_entity */
2011 }
2012
2013 typedef struct _h_env {
2014         int dump_ent;
2015         FILE *f;
2016 } h_env_t;
2017
2018 /** For dumping class hierarchies.
2019  * Dumps a class type node and a superclass edge.
2020  * If env->dump_ent dumps entities of classes and overwrites edges.
2021  */
2022 static void
2023 dump_class_hierarchy_node(type_or_ent *tore, void *ctx) {
2024         h_env_t *env = ctx;
2025         FILE *F = env->f;
2026         int i = 0;  /* to shutup gcc */
2027
2028         /* dump this type or entity */
2029         switch (get_kind(tore)) {
2030         case k_entity: {
2031                 ir_entity *ent = (ir_entity *)tore;
2032                 if (get_entity_owner(ent) == get_glob_type()) break;
2033                 if (!is_Method_type(get_entity_type(ent))) break;  /* GL */
2034                 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
2035                         /* The node */
2036                         dump_entity_node(F, ent, 0);
2037                         /* The edges */
2038                         print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
2039                         for(i = 0; i < get_entity_n_overwrites(ent); i++)
2040                                 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
2041                 }
2042                 break;
2043         }
2044         case k_type: {
2045                 ir_type *tp = (ir_type *)tore;
2046                 if (tp == get_glob_type()) break;
2047                 switch (get_type_tpop_code(tp)) {
2048                 case tpo_class:
2049                         dump_type_node(F, tp);
2050                         /* and now the edges */
2051                         for (i=0; i < get_class_n_supertypes(tp); i++) {
2052                                 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
2053                         }
2054                         break;
2055                 default: break;
2056                 } /* switch type */
2057                 break; /* case k_type */
2058         }
2059         default:
2060                 printf(" *** irdump,  dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
2061         } /* switch kind_or_entity */
2062 }
2063
2064 /*******************************************************************/
2065 /* dump analysis information that is expressed in graph terms.     */
2066 /*******************************************************************/
2067
2068 /* dump out edges */
2069 static void
2070 dump_out_edge(ir_node *n, void *env) {
2071         FILE *F = env;
2072         int i;
2073         for (i = 0; i < get_irn_n_outs(n); i++) {
2074                 assert(get_irn_out(n, i));
2075                 fprintf(F, "edge: {sourcename: \"");
2076                 PRINT_NODEID(n);
2077                 fprintf(F, "\" targetname: \"");
2078                 PRINT_NODEID(get_irn_out(n, i));
2079                 fprintf(F, "\" color: red linestyle: dashed");
2080                 fprintf(F, "}\n");
2081         }
2082 }
2083
2084 static INLINE void
2085 dump_loop_label(FILE *F, ir_loop *loop) {
2086         fprintf(F, "loop %d, %d sons, %d nodes",
2087                 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
2088 }
2089
2090 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
2091         fprintf(F, " info1: \"");
2092         fprintf(F, " loop nr: %d", get_loop_loop_nr(loop));
2093 #ifdef DEBUG_libfirm   /* GL @@@ debug analyses */
2094         fprintf(F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
2095 #endif
2096         fprintf(F, "\"");
2097 }
2098
2099 static INLINE void
2100 dump_loop_node(FILE *F, ir_loop *loop) {
2101         fprintf(F, "node: {title: \"");
2102         PRINT_LOOPID(loop);
2103         fprintf(F, "\" label: \"");
2104         dump_loop_label(F, loop);
2105         fprintf(F, "\" ");
2106         dump_loop_info(F, loop);
2107         fprintf(F, "}\n");
2108 }
2109
2110 static INLINE void
2111 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
2112         assert(loop);
2113         fprintf(F, "edge: {sourcename: \"");
2114         PRINT_LOOPID(loop);
2115         fprintf(F, "\" targetname: \"");
2116         PRINT_NODEID(get_loop_node(loop, i));
2117         fprintf(F, "\" color: green");
2118         fprintf(F, "}\n");
2119 }
2120
2121 static INLINE void
2122 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
2123         assert(loop);
2124         fprintf(F, "edge: {sourcename: \"");
2125         PRINT_LOOPID(loop);
2126         fprintf(F, "\" targetname: \"");
2127         PRINT_LOOPID(get_loop_son(loop, i));
2128         fprintf(F, "\" color: darkgreen label: \"%d\"}\n",
2129                 get_loop_element_pos(loop, get_loop_son(loop, i)));
2130 }
2131
2132 static
2133 void dump_loops(FILE *F, ir_loop *loop) {
2134         int i;
2135         /* dump this loop node */
2136         dump_loop_node(F, loop);
2137
2138         /* dump edges to nodes in loop -- only if it is a real loop */
2139         if (get_loop_depth(loop) != 0) {
2140                 for (i = 0; i < get_loop_n_nodes(loop); i++) {
2141                         dump_loop_node_edge(F, loop, i);
2142                 }
2143         }
2144         for (i = 0; i < get_loop_n_sons(loop); i++) {
2145                 dump_loops(F, get_loop_son(loop, i));
2146                 dump_loop_son_edge(F, loop, i);
2147         }
2148 }
2149
2150 static INLINE
2151 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
2152         ir_graph *rem = current_ir_graph;
2153         current_ir_graph = irg;
2154
2155         if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
2156
2157         current_ir_graph = rem;
2158 }
2159
2160
2161 /**
2162  * dumps the VCG header
2163  */
2164 void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
2165         char *label;
2166
2167         if (edge_label) {
2168                 label = "yes";
2169         } else {
2170                 label = "no";
2171         }
2172
2173         if (!orientation) orientation = "bottom_to_top";
2174
2175         /* print header */
2176         fprintf(F,
2177                 "graph: { title: \"ir graph of %s\"\n"
2178                 "display_edge_labels: %s\n"
2179                 "layoutalgorithm: mindepth\n"
2180                 "manhattan_edges: yes\n"
2181                 "port_sharing: no\n"
2182                 "orientation: %s\n"
2183                 "classname 1:  \"intrablock Data\"\n"
2184                 "classname 2:  \"Block\"\n"
2185                 "classname 3:  \"Entity type\"\n"
2186                 "classname 4:  \"Entity owner\"\n"
2187                 "classname 5:  \"Method Param\"\n"
2188                 "classname 6:  \"Method Res\"\n"
2189                 "classname 7:  \"Super\"\n"
2190                 "classname 8:  \"Union\"\n"
2191                 "classname 9:  \"Points-to\"\n"
2192                 "classname 10: \"Array Element Type\"\n"
2193                 "classname 11: \"Overwrites\"\n"
2194                 "classname 12: \"Member\"\n"
2195                 "classname 13: \"Control Flow\"\n"
2196                 "classname 14: \"intrablock Memory\"\n"
2197                 "classname 15: \"Dominators\"\n"
2198                 "classname 16: \"interblock Data\"\n"
2199                 "classname 17: \"interblock Memory\"\n"
2200                 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2201                 "classname 19: \"Postdominators\"\n"
2202                 "classname 20: \"Keep Alive\"\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 }