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