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