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