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