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