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