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