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