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