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