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