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