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