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