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