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