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