automatically generate most getter/setter functions of firm 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 = 0;
91 /** An option to dump the node number */
92 static int dump_node_nr = 0;
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         ir_fprintf(F, " label: \"%s %+F\" info1: \"", get_type_tpop_name(tp), tp);
2066         dump_type_to_file(F, tp, dump_verbosity_max);
2067         fprintf(F, "\"\n");
2068         print_type_dbg_info(F, get_type_dbg_info(tp));
2069         print_typespecific_vcgattr(F, tp);
2070         fprintf(F, "}\n");
2071
2072         return bad;
2073 }
2074
2075
2076 static void dump_entity_node(FILE *F, ir_entity *ent)
2077 {
2078         fprintf(F, "node: {title: \"");
2079         PRINT_ENTID(ent); fprintf(F, "\"");
2080         fprintf(F, " label: ");
2081         fprintf(F, "\"%s\" ", get_ent_dump_name(ent));
2082
2083         print_vcg_color(F, ird_color_entity);
2084         fprintf(F, "\n info1: \"");
2085
2086         dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
2087
2088         fprintf(F, "\"\n");
2089         print_dbg_info(F, get_entity_dbg_info(ent));
2090         fprintf(F, "}\n");
2091 }
2092
2093 static void dump_enum_item(FILE *F, ir_type *tp, int pos)
2094 {
2095         char buf[1024];
2096         ir_enum_const *ec = get_enumeration_const(tp, pos);
2097         ident         *id = get_enumeration_const_nameid(ec);
2098         tarval        *tv = get_enumeration_value(ec);
2099
2100         if (tv)
2101                 tarval_snprintf(buf, sizeof(buf), tv);
2102         else
2103                 strncpy(buf, "<not set>", sizeof(buf));
2104         fprintf(F, "node: {title: \"");
2105         PRINT_ITEMID(tp, pos); fprintf(F, "\"");
2106         fprintf(F, " label: ");
2107         fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
2108         fprintf(F, "\n info1: \"value: %s\"}\n", buf);
2109 }
2110
2111 /**
2112  * Dumps a new style initializer.
2113  */
2114 static void dump_entity_initializer(FILE *F, const ir_entity *ent)
2115 {
2116         /* TODO */
2117         (void) F;
2118         (void) ent;
2119 }
2120
2121 /** Dumps a type or entity and it's edges. */
2122 static void dump_type_info(type_or_ent tore, void *env)
2123 {
2124         FILE *F = env;
2125         int i = 0;  /* to shutup gcc */
2126
2127         /* dump this type or entity */
2128
2129         switch (get_kind(tore.ent)) {
2130         case k_entity: {
2131                 ir_entity *ent = tore.ent;
2132                 ir_node *value;
2133                 /* The node */
2134                 dump_entity_node(F, ent);
2135                 /* The Edges */
2136                 /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
2137                 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
2138                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
2139                 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
2140                 if (is_Class_type(get_entity_owner(ent))) {
2141                         for (i = get_entity_n_overwrites(ent) - 1; i >= 0; --i)
2142                                 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, -1, ENT_OVERWRITES_EDGE_ATTR);
2143                 }
2144                 /* attached subgraphs */
2145                 if (const_entities) {
2146                         if (ent->initializer != NULL) {
2147                                 /* new style initializers */
2148                                 dump_entity_initializer(F, ent);
2149                         } else if (entity_has_compound_ent_values(ent)) {
2150                                 /* old style compound entity values */
2151                                 for (i = get_compound_ent_n_values(ent) - 1; i >= 0; --i) {
2152                                         value = get_compound_ent_value(ent, i);
2153                                         if (value) {
2154                                                 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
2155                                                 dump_const_expression(F, value);
2156                                                 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, -1, ENT_CORR_EDGE_ATTR, i);
2157                                                 /*
2158                                                 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
2159                                                 ENT_CORR_EDGE_ATTR  "}\n", GET_ENTID(ent),
2160                                                 get_compound_ent_value_member(ent, i), i);
2161                                                 */
2162                                         }
2163                                 }
2164                         }
2165                 }
2166                 break;
2167         }
2168         case k_type: {
2169                 ir_type *tp = tore.typ;
2170                 dump_type_node(F, tp);
2171                 /* and now the edges */
2172                 switch (get_type_tpop_code(tp)) {
2173                 case tpo_class:
2174                         for (i = get_class_n_supertypes(tp) - 1; i >= 0; --i)
2175                                 print_type_type_edge(F, tp, get_class_supertype(tp, i), TYPE_SUPER_EDGE_ATTR);
2176                         for (i = get_class_n_members(tp) - 1; i >= 0; --i)
2177                                 print_type_ent_edge(F, tp, get_class_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
2178                         break;
2179                 case tpo_struct:
2180                         for (i = get_struct_n_members(tp) - 1; i >= 0; --i)
2181                                 print_type_ent_edge(F, tp, get_struct_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
2182                         break;
2183                 case tpo_method:
2184                         for (i = get_method_n_params(tp) - 1; i >= 0; --i)
2185                                 print_type_type_edge(F, tp, get_method_param_type(tp, i), METH_PAR_EDGE_ATTR,i);
2186                         for (i = get_method_n_ress(tp) - 1; i >= 0; --i)
2187                                 print_type_type_edge(F, tp, get_method_res_type(tp, i), METH_RES_EDGE_ATTR,i);
2188                         break;
2189                 case tpo_union:
2190                         for (i = get_union_n_members(tp) - 1; i >= 0; --i)
2191                                 print_type_ent_edge(F, tp, get_union_member(tp, i), UNION_EDGE_ATTR);
2192                         break;
2193                 case tpo_array:
2194                         print_type_type_edge(F, tp, get_array_element_type(tp), ARR_ELT_TYPE_EDGE_ATTR);
2195                         print_type_ent_edge(F, tp, get_array_element_entity(tp), ARR_ENT_EDGE_ATTR);
2196                         for (i = get_array_n_dimensions(tp) - 1; i >= 0; --i) {
2197                                 ir_node *upper = get_array_upper_bound(tp, i);
2198                                 ir_node *lower = get_array_lower_bound(tp, i);
2199                                 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
2200                                 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
2201                                 dump_const_expression(F, upper);
2202                                 dump_const_expression(F, lower);
2203                         }
2204                         break;
2205                 case tpo_enumeration:
2206                         for (i = get_enumeration_n_enums(tp) - 1; i >= 0; --i) {
2207                                 dump_enum_item(F, tp, i);
2208                                 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
2209                         }
2210                         break;
2211                 case tpo_pointer:
2212                         print_type_type_edge(F, tp, get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
2213                         break;
2214                 case tpo_primitive:
2215                         break;
2216                 default:
2217                         break;
2218                 } /* switch type */
2219                 break; /* case k_type */
2220         }
2221         default:
2222                 printf(" *** irdump,  dump_type_info(l.%i), faulty type.\n", __LINE__);
2223         } /* switch kind_or_entity */
2224 }
2225
2226 typedef struct _h_env {
2227         int dump_ent;
2228         FILE *f;
2229 } h_env_t;
2230
2231 /** For dumping class hierarchies.
2232  * Dumps a class type node and a superclass edge.
2233  * If env->dump_ent dumps entities of classes and overwrites edges.
2234  */
2235 static void dump_class_hierarchy_node(type_or_ent tore, void *ctx)
2236 {
2237         h_env_t *env = ctx;
2238         FILE *F = env->f;
2239         int i = 0;  /* to shutup gcc */
2240
2241         /* dump this type or entity */
2242         switch (get_kind(tore.ent)) {
2243         case k_entity: {
2244                 ir_entity *ent = tore.ent;
2245                 if (get_entity_owner(ent) == get_glob_type()) break;
2246                 if (!is_Method_type(get_entity_type(ent)))
2247                         break;  /* GL */
2248                 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
2249                         /* The node */
2250                         dump_entity_node(F, ent);
2251                         /* The edges */
2252                         print_type_ent_edge(F, get_entity_owner(ent), ent, TYPE_MEMBER_EDGE_ATTR);
2253                         for (i = get_entity_n_overwrites(ent) - 1; i >= 0; --i)
2254                                 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, -1, ENT_OVERWRITES_EDGE_ATTR);
2255                 }
2256                 break;
2257         }
2258         case k_type: {
2259                 ir_type *tp = tore.typ;
2260                 if (tp == get_glob_type())
2261                         break;
2262                 switch (get_type_tpop_code(tp)) {
2263                 case tpo_class:
2264                         dump_type_node(F, tp);
2265                         /* and now the edges */
2266                         for (i = get_class_n_supertypes(tp) - 1; i >= 0; --i) {
2267                                 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
2268                         }
2269                         break;
2270                 default: break;
2271                 } /* switch type */
2272                 break; /* case k_type */
2273         }
2274         default:
2275                 printf(" *** irdump,  dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
2276         } /* switch kind_or_entity */
2277 }
2278
2279 /*******************************************************************/
2280 /* dump analysis information that is expressed in graph terms.     */
2281 /*******************************************************************/
2282
2283 /* dump out edges */
2284 static void dump_out_edge(ir_node *n, void *env)
2285 {
2286         FILE *F = env;
2287         int i;
2288         for (i = get_irn_n_outs(n) - 1; i >= 0; --i) {
2289                 ir_node *succ = get_irn_out(n, i);
2290                 assert(succ);
2291                 print_node_edge_kind(F, succ);
2292                 fprintf(F, "{sourcename: \"");
2293                 PRINT_NODEID(n);
2294                 fprintf(F, "\" targetname: \"");
2295                 PRINT_NODEID(succ);
2296                 fprintf(F, "\" color: red linestyle: dashed");
2297                 fprintf(F, "}\n");
2298         }
2299 }
2300
2301 static inline void dump_loop_label(FILE *F, ir_loop *loop)
2302 {
2303         fprintf(F, "loop %d, %d sons, %d nodes",
2304                 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
2305 }
2306
2307 static inline void dump_loop_info(FILE *F, ir_loop *loop)
2308 {
2309         fprintf(F, " info1: \"");
2310         fprintf(F, " loop nr: %d", get_loop_loop_nr(loop));
2311 #ifdef DEBUG_libfirm   /* GL @@@ debug analyses */
2312         fprintf(F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
2313 #endif
2314         fprintf(F, "\"");
2315 }
2316
2317 static inline void dump_loop_node(FILE *F, ir_loop *loop)
2318 {
2319         fprintf(F, "node: {title: \"");
2320         PRINT_LOOPID(loop);
2321         fprintf(F, "\" label: \"");
2322         dump_loop_label(F, loop);
2323         fprintf(F, "\" ");
2324         dump_loop_info(F, loop);
2325         fprintf(F, "}\n");
2326 }
2327
2328 static inline void dump_loop_node_edge(FILE *F, ir_loop *loop, int i)
2329 {
2330         assert(loop);
2331         fprintf(F, "edge: {sourcename: \"");
2332         PRINT_LOOPID(loop);
2333         fprintf(F, "\" targetname: \"");
2334         PRINT_NODEID(get_loop_node(loop, i));
2335         fprintf(F, "\" color: green");
2336         fprintf(F, "}\n");
2337 }
2338
2339 static inline void dump_loop_son_edge(FILE *F, ir_loop *loop, int i)
2340 {
2341         assert(loop);
2342         fprintf(F, "edge: {sourcename: \"");
2343         PRINT_LOOPID(loop);
2344         fprintf(F, "\" targetname: \"");
2345         PRINT_LOOPID(get_loop_son(loop, i));
2346         fprintf(F, "\" color: darkgreen label: \"%d\"}\n",
2347                 get_loop_element_pos(loop, get_loop_son(loop, i)));
2348 }
2349
2350 static void dump_loops(FILE *F, ir_loop *loop)
2351 {
2352         int i;
2353         /* dump this loop node */
2354         dump_loop_node(F, loop);
2355
2356         /* dump edges to nodes in loop -- only if it is a real loop */
2357         if (get_loop_depth(loop) != 0) {
2358                 for (i = get_loop_n_nodes(loop) - 1; i >= 0; --i) {
2359                         dump_loop_node_edge(F, loop, i);
2360                 }
2361         }
2362         for (i = get_loop_n_sons(loop) - 1; i >= 0; --i) {
2363                 dump_loops(F, get_loop_son(loop, i));
2364                 dump_loop_son_edge(F, loop, i);
2365         }
2366 }
2367
2368 static inline void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg)
2369 {
2370         ir_loop *loop = get_irg_loop(irg);
2371
2372         if (loop != NULL) {
2373                 ir_graph *rem = current_ir_graph;
2374                 current_ir_graph = irg;
2375
2376                 dump_loops(F, loop);
2377
2378                 current_ir_graph = rem;
2379         }
2380 }
2381
2382
2383 /**
2384  * dumps the VCG header
2385  */
2386 void dump_vcg_header(FILE *F, const char *name, const char *layout, const char *orientation)
2387 {
2388         int   i;
2389         char *label;
2390
2391         init_colors();
2392
2393         label = edge_label ? "yes" : "no";
2394         if (! layout)     layout = "Compilergraph";
2395         if (!orientation) orientation = "bottom_to_top";
2396
2397         /* print header */
2398         fprintf(F,
2399                 "graph: { title: \"ir graph of %s\"\n"
2400                 "display_edge_labels: %s\n"
2401                 "layoutalgorithm: mindepth //$ \"%s\"\n"
2402                 "manhattan_edges: yes\n"
2403                 "port_sharing: no\n"
2404                 "orientation: %s\n"
2405                 "classname 1:  \"intrablock Data\"\n"
2406                 "classname 2:  \"Block\"\n"
2407                 "classname 3:  \"Entity type\"\n"
2408                 "classname 4:  \"Entity owner\"\n"
2409                 "classname 5:  \"Method Param\"\n"
2410                 "classname 6:  \"Method Res\"\n"
2411                 "classname 7:  \"Super\"\n"
2412                 "classname 8:  \"Union\"\n"
2413                 "classname 9:  \"Points-to\"\n"
2414                 "classname 10: \"Array Element Type\"\n"
2415                 "classname 11: \"Overwrites\"\n"
2416                 "classname 12: \"Member\"\n"
2417                 "classname 13: \"Control Flow\"\n"
2418                 "classname 14: \"intrablock Memory\"\n"
2419                 "classname 15: \"Dominators\"\n"
2420                 "classname 16: \"interblock Data\"\n"
2421                 "classname 17: \"interblock Memory\"\n"
2422                 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2423                 "classname 19: \"Postdominators\"\n"
2424                 "classname 20: \"Keep Alive\"\n"
2425                 "classname 21: \"Out Edges\"\n"
2426                 "classname 22: \"Macro Block Edges\"\n"
2427                 //"classname 23: \"NoInput Nodes\"\n"
2428                 "infoname 1: \"Attribute\"\n"
2429                 "infoname 2: \"Verification errors\"\n"
2430                 "infoname 3: \"Debug info\"\n",
2431                 name, label, layout, orientation);
2432
2433         for (i = 0; i < ird_color_count; ++i) {
2434                 if (color_rgb[i] != NULL) {
2435                         fprintf(F, "colorentry %s: %s\n", color_names[i], color_rgb[i]);
2436                 }
2437         }
2438         fprintf(F, "\n");        /* a separator */
2439 }
2440
2441 /**
2442  * open a vcg file
2443  *
2444  * @param irg     The graph to be dumped
2445  * @param suffix1 first filename suffix
2446  * @param suffix2 second filename suffix
2447  */
2448 FILE *vcg_open(const ir_graph *irg, const char *suffix1, const char *suffix2)
2449 {
2450         FILE *F;
2451         const char *nm = get_irg_dump_name(irg);
2452         int len = strlen(nm), i, j;
2453         char *fname;  /* filename to put the vcg information in */
2454
2455         if (!suffix1) suffix1 = "";
2456         if (!suffix2) suffix2 = "";
2457
2458         /* open file for vcg graph */
2459         fname = XMALLOCN(char, len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2460
2461         /* strncpy (fname, nm, len); */     /* copy the filename */
2462         j = 0;
2463         for (i = 0; i < len; ++i) {  /* replace '/' in the name: escape by @. */
2464                 if (nm[i] == '/') {
2465                         fname[j] = '@'; j++; fname[j] = '1'; j++;
2466                 } else if (nm[i] == '@') {
2467                         fname[j] = '@'; j++; fname[j] = '2'; j++;
2468                 } else {
2469                         fname[j] = nm[i]; j++;
2470                 }
2471         }
2472         fname[j] = '\0';
2473         strcat(fname, suffix1);  /* append file suffix */
2474         strcat(fname, suffix2);  /* append file suffix */
2475         strcat(fname, ".vcg");   /* append the .vcg suffix */
2476
2477         /* vcg really expect only a <CR> at end of line, so
2478          * the "b"inary mode is what you mean (and even needed for Win32)
2479          */
2480         F = fopen(fname, "wb");  /* open file for writing */
2481         if (!F) {
2482                 perror(fname);
2483         }
2484         xfree(fname);
2485
2486         return F;
2487 }
2488
2489 /**
2490  * open a vcg file
2491  *
2492  * @param name    prefix file name
2493  * @param suffix  filename suffix
2494  */
2495 FILE *vcg_open_name(const char *name, const char *suffix)
2496 {
2497         FILE *F;
2498         char *fname;  /* filename to put the vcg information in */
2499         int i, j, len = strlen(name);
2500
2501         if (!suffix) suffix = "";
2502
2503         /** open file for vcg graph */
2504         fname = XMALLOCN(char, len * 2 + 5 + strlen(suffix));
2505         /* strcpy (fname, name);*/    /* copy the filename */
2506         j = 0;
2507         for (i = 0; i < len; ++i) {  /* replace '/' in the name: escape by @. */
2508                 if (name[i] == '/') {
2509                         fname[j] = '@'; j++; fname[j] = '1'; j++;
2510                 } else if (name[i] == '@') {
2511                         fname[j] = '@'; j++; fname[j] = '2'; j++;
2512                 } else {
2513                         fname[j] = name[i]; j++;
2514                 }
2515         }
2516         fname[j] = '\0';
2517         strcat(fname, suffix);
2518         strcat(fname, ".vcg");  /* append the .vcg suffix */
2519
2520         /* vcg really expect only a <CR> at end of line, so
2521          * the "b"inary mode is what you mean (and even needed for Win32)
2522          */
2523         F = fopen(fname, "wb");  /* open file for writing */
2524         if (!F) {
2525                 perror(fname);
2526         }
2527         xfree(fname);
2528
2529         return F;
2530 }
2531
2532 /**
2533  * Dumps the vcg file footer
2534  */
2535 void dump_vcg_footer(FILE *F)
2536 {
2537         fprintf(F, "}\n");
2538 }
2539
2540 /************************************************************************/
2541 /************************************************************************/
2542 /* Routines that dump all or parts of the firm representation to a file */
2543 /************************************************************************/
2544 /************************************************************************/
2545
2546 /************************************************************************/
2547 /* Dump ir graphs, different formats and additional information.        */
2548 /************************************************************************/
2549
2550 typedef void (*do_dump_graph_func) (ir_graph *irg, FILE *out);
2551
2552 static void do_dump(ir_graph *irg, const char *suffix, const char *suffix_ip,
2553                     const char *suffix_nonip, do_dump_graph_func dump_func)
2554 {
2555         FILE       *out;
2556         ir_graph   *rem;
2557         const char *suffix1;
2558
2559         if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2560                 return;
2561
2562         rem = current_ir_graph;
2563         current_ir_graph = irg;
2564         (void) suffix_ip;
2565 #ifdef INTERPROCEDURAL_VIEW
2566         if (get_interprocedural_view())
2567                 suffix1 = suffix_ip;
2568         else
2569 #endif
2570                 suffix1 = suffix_nonip;
2571         current_ir_graph = rem;
2572
2573         out = vcg_open(irg, suffix, suffix1);
2574         if (out != NULL) {
2575                 dump_func(irg, out);
2576                 fclose(out);
2577         }
2578 }
2579
2580 void dump_ir_graph_file(ir_graph *irg, FILE *out)
2581 {
2582         if (dump_backedge_information_flag
2583                         && get_irg_loopinfo_state(irg) != loopinfo_consistent) {
2584                 construct_backedges(irg);
2585         }
2586
2587         dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2588
2589         /* call the dump graph hook */
2590         if (dump_ir_graph_hook) {
2591                 if (dump_ir_graph_hook(out, irg)) {
2592                         return;
2593                 }
2594         }
2595
2596         /* walk over the graph */
2597         /* dump_whole_node must be called in post visiting predecessors */
2598         ird_walk_graph(irg, NULL, dump_whole_node, out);
2599
2600         /* dump the out edges in a separate walk */
2601         if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2602                 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, out);
2603         }
2604
2605         dump_vcg_footer(out);
2606 }
2607
2608 /** Routine to dump a graph, blocks as conventional nodes.  */
2609 void dump_ir_graph(ir_graph *irg, const char *suffix )
2610 {
2611         do_dump(irg, suffix, "-pure-ip", "-pure", dump_ir_graph_file);
2612 }
2613
2614 void dump_ir_block_graph_file(ir_graph *irg, FILE *out)
2615 {
2616         int i;
2617
2618         dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2619
2620         construct_block_lists(irg);
2621
2622         /*
2623          * If we are in the interprocedural view, we dump not
2624          * only the requested irg but also all irgs that can be reached
2625          * from irg.
2626          */
2627         for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2628                 ir_graph *g = get_irp_irg(i);
2629                 ir_node **arr = ird_get_irg_link(g);
2630                 if (arr) {
2631                         dump_graph_from_list(out, g);
2632                         DEL_ARR_F(arr);
2633                 }
2634         }
2635
2636         dump_vcg_footer(out);
2637 }
2638
2639 /* Dump a firm graph without explicit block nodes. */
2640 void dump_ir_block_graph(ir_graph *irg, const char *suffix)
2641 {
2642         do_dump(irg, suffix, "-ip", "", dump_ir_block_graph_file);
2643 }
2644
2645 void dump_ir_extblock_graph_file(ir_graph *irg, FILE *F)
2646 {
2647         int        i;
2648         ir_entity *ent = get_irg_entity(irg);
2649
2650         if (get_irg_extblk_state(irg) != extblk_valid)
2651                 compute_extbb(irg);
2652
2653         dump_vcg_header(F, get_irg_dump_name(irg), NULL, NULL);
2654
2655         construct_extblock_lists(irg);
2656
2657         fprintf(F, "graph: { title: \"");
2658         PRINT_IRGID(irg);
2659         fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2660                 get_ent_dump_name(ent));
2661
2662         dump_graph_info(F, irg);
2663         print_dbg_info(F, get_entity_dbg_info(ent));
2664
2665         for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2666                 ir_graph *irg     = get_irp_irg(i);
2667                 list_tuple *lists = ird_get_irg_link(irg);
2668
2669                 if (lists) {
2670                         /* dump the extended blocks first */
2671                         if (ARR_LEN(lists->extbb_list)) {
2672                                 ird_set_irg_link(irg, lists->extbb_list);
2673                                 dump_extblock_graph(F, irg);
2674                         }
2675
2676                         /* we may have blocks without extended blocks, bad for instance */
2677                         if (ARR_LEN(lists->blk_list)) {
2678                                 ird_set_irg_link(irg, lists->blk_list);
2679                                 dump_block_graph(F, irg);
2680                         }
2681
2682                         DEL_ARR_F(lists->extbb_list);
2683                         DEL_ARR_F(lists->blk_list);
2684                         xfree(lists);
2685                 }
2686         }
2687
2688         /* Close the vcg information for the irg */
2689         fprintf(F, "}\n\n");
2690
2691         dump_vcg_footer(F);
2692         free_extbb(irg);
2693 }
2694
2695 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2696 void dump_ir_extblock_graph(ir_graph *irg, const char *suffix)
2697 {
2698         do_dump(irg, suffix, "-ip", "", dump_ir_extblock_graph_file);
2699 }
2700
2701 void dump_ir_graph_w_types_file(ir_graph *irg, FILE *out)
2702 {
2703         ir_graph *rem = current_ir_graph;
2704         int       rem_dump_const_local;
2705
2706         rem                  = current_ir_graph;
2707         current_ir_graph     = irg;
2708         rem_dump_const_local = dump_const_local;
2709         /* dumping types does not work with local nodes */
2710         dump_const_local = 0;
2711
2712         dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2713
2714         /* dump common ir graph */
2715         irg_walk(get_irg_end(irg), NULL, dump_whole_node, out);
2716         /* dump type info */
2717         type_walk_irg(irg, dump_type_info, NULL, out);
2718         inc_irg_visited(get_const_code_irg());
2719         /* dump edges from graph to type info */
2720         irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, out);
2721
2722         dump_vcg_footer(out);
2723         dump_const_local = rem_dump_const_local;
2724         current_ir_graph = rem;
2725 }
2726
2727 /* dumps a graph with type information */
2728 void dump_ir_graph_w_types(ir_graph *irg, const char *suffix)
2729 {
2730         do_dump(irg, suffix, "-pure-wtypes-ip", "-pure-wtypes",
2731                 dump_ir_graph_w_types_file);
2732 }
2733
2734 void dump_ir_block_graph_w_types_file(ir_graph *irg, FILE *out)
2735 {
2736         int       i;
2737         int       rem_dump_const_local;
2738         ir_graph *rem = current_ir_graph;
2739
2740         rem_dump_const_local = dump_const_local;
2741         /* dumping types does not work with local nodes */
2742         dump_const_local = 0;
2743
2744         dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2745
2746         /* dump common blocked ir graph */
2747         construct_block_lists(irg);
2748
2749         for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2750                 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2751                 if (arr) {
2752                         dump_graph_from_list(out, get_irp_irg(i));
2753                         DEL_ARR_F(arr);
2754                 }
2755         }
2756
2757         /* dump type info */
2758         current_ir_graph = irg;
2759         type_walk_irg(irg, dump_type_info, NULL, out);
2760         inc_irg_visited(get_const_code_irg());
2761
2762         /* dump edges from graph to type info */
2763         irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, out);
2764
2765         dump_vcg_footer(out);
2766         dump_const_local = rem_dump_const_local;
2767         current_ir_graph = rem;
2768 }
2769
2770 void dump_ir_block_graph_w_types(ir_graph *irg, const char *suffix)
2771 {
2772         do_dump(irg, suffix, "-wtypes-ip", "-wtypes",
2773                 dump_ir_block_graph_w_types_file);
2774 }
2775
2776 /*---------------------------------------------------------------------*/
2777 /* The following routines dump a control flow graph.                   */
2778 /*---------------------------------------------------------------------*/
2779
2780 static void dump_block_to_cfg(ir_node *block, void *env)
2781 {
2782         FILE *F = env;
2783         int i, fl = 0;
2784         ir_node *pred;
2785
2786         if (is_Block(block)) {
2787                 /* This is a block. Dump a node for the block. */
2788                 fprintf(F, "node: {title: \""); PRINT_NODEID(block);
2789                 fprintf(F, "\" label: \"");
2790                 if (block == get_irg_start_block(get_irn_irg(block)))
2791                         fprintf(F, "Start ");
2792                 if (block == get_irg_end_block(get_irn_irg(block)))
2793                         fprintf(F, "End ");
2794
2795                 fprintf(F, "%s ", get_op_name(get_irn_op(block)));
2796                 PRINT_NODEID(block);
2797                 fprintf(F, "\" ");
2798                 fprintf(F, "info1:\"");
2799
2800                 /* the generic version. */
2801                 dump_irnode_to_file(F, block);
2802
2803                 /* Check whether we have bad predecessors to color the block. */
2804                 for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i)
2805                         if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2806                                 break;
2807
2808                 fprintf(F, "\"");  /* closing quote of info */
2809
2810                 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2811                         (block == get_irg_end_block(get_irn_irg(block)))     )
2812                         fprintf(F, " color:blue ");
2813                 else if (fl)
2814                         fprintf(F, " color:yellow ");
2815
2816                 fprintf(F, "}\n");
2817                 /* Dump the edges */
2818                 for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i)
2819                         if (!is_Bad(skip_Proj(get_Block_cfgpred(block, i)))) {
2820                                 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2821                                 fprintf(F, "edge: { sourcename: \"");
2822                                 PRINT_NODEID(block);
2823                                 fprintf(F, "\" targetname: \"");
2824                                 PRINT_NODEID(pred);
2825                                 fprintf(F, "\"}\n");
2826                         }
2827
2828                 /* Dump dominator/postdominator edge */
2829                 if (dump_dominator_information_flag) {
2830                         if (get_irg_dom_state(current_ir_graph) == dom_consistent && get_Block_idom(block)) {
2831                                 pred = get_Block_idom(block);
2832                                 fprintf(F, "edge: { sourcename: \"");
2833                                 PRINT_NODEID(block);
2834                                 fprintf(F, "\" targetname: \"");
2835                                 PRINT_NODEID(pred);
2836                                 fprintf(F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2837                         }
2838                         if (get_irg_postdom_state(current_ir_graph) == dom_consistent && get_Block_ipostdom(block)) {
2839                                 pred = get_Block_ipostdom(block);
2840                                 fprintf(F, "edge: { sourcename: \"");
2841                                 PRINT_NODEID(block);
2842                                 fprintf(F, "\" targetname: \"");
2843                                 PRINT_NODEID(pred);
2844                                 fprintf(F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2845                         }
2846                 }
2847         }
2848 }
2849
2850 void dump_cfg(ir_graph *irg, const char *suffix)
2851 {
2852         FILE *f;
2853         /* if a filter is set, dump only the irg's that match the filter */
2854         if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2855                 return;
2856
2857         f = vcg_open(irg, suffix, "-cfg");
2858         if (f != NULL) {
2859                 ir_graph *rem = current_ir_graph;
2860 #ifdef INTERPROCEDURAL_VIEW
2861                 int ipv = get_interprocedural_view();
2862 #endif
2863
2864                 current_ir_graph = irg;
2865                 dump_vcg_header(f, get_irg_dump_name(irg), NULL, NULL);
2866
2867 #ifdef INTERPROCEDURAL_VIEW
2868                 if (ipv) {
2869                         printf("Warning: dumping cfg not in interprocedural view!\n");
2870                         set_interprocedural_view(0);
2871                 }
2872 #endif
2873
2874                 /* walk over the blocks in the graph */
2875                 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2876                 dump_node(f, get_irg_bad(irg));
2877
2878 #ifdef INTERPROCEDURAL_VIEW
2879                 set_interprocedural_view(ipv);
2880 #endif
2881                 dump_vcg_footer(f);
2882                 fclose(f);
2883                 current_ir_graph = rem;
2884         }
2885 }
2886
2887
2888 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set)
2889 {
2890         if (pset_find_ptr(mark_set, n))
2891                 return;
2892
2893         pset_insert_ptr(mark_set, n);
2894
2895         if (depth > 0) {
2896                 int i, start = is_Block(n) ? 0 : -1;
2897                 dump_whole_node(n, F);
2898                 for (i = start; i < get_irn_arity(n); ++i)
2899                         descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2900         } else {
2901                 dump_node(F, n);
2902                 /* Don't dump edges to nodes further out.  These might be edges to
2903                    nodes we already dumped, if there is a shorter path to these. */
2904         }
2905 }
2906
2907 static int subgraph_counter = 0;
2908 void dump_subgraph(ir_node *root, int depth, const char *suffix)
2909 {
2910         FILE *F;
2911         char buf[32];
2912
2913         sprintf(buf, "-subg_%03d", subgraph_counter++);
2914         F = vcg_open(get_irn_irg(root), suffix, buf);
2915         if (F != NULL) {
2916                 pset *mark_set = pset_new_ptr(1);
2917                 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL, NULL);
2918                 descend_and_dump(F, root, depth, mark_set);
2919                 dump_vcg_footer(F);
2920                 fclose(F);
2921                 del_pset(mark_set);
2922         }
2923 }
2924
2925 void dump_callgraph(const char *suffix)
2926 {
2927         FILE *F = vcg_open_name("Callgraph", suffix);
2928
2929         if (F != NULL) {
2930                 int i, rem = edge_label;
2931                 //int colorize;
2932                 edge_label = 1;
2933                 dump_vcg_header(F, "Callgraph", "Hierarchiv", NULL);
2934
2935                 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2936                         ir_graph *irg = get_irp_irg(i);
2937                         ir_entity *ent = get_irg_entity(irg);
2938                         int j;
2939                         int n_callees = get_irg_n_callees(irg);
2940
2941                         dump_entity_node(F, ent);
2942                         for (j = 0; j < n_callees; ++j) {
2943                                 ir_entity *c = get_irg_entity(get_irg_callee(irg, j));
2944                                 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2945                                 int be = is_irg_callee_backedge(irg, j);
2946                                 char *attr;
2947                                 attr = (be) ?
2948                                         "label:\"recursion %d\"" :
2949                                 "label:\"calls %d\"";
2950                                 print_ent_ent_edge(F, ent, c, be, ird_color_entity, attr, get_irg_callee_loop_depth(irg, j));
2951                         }
2952                 }
2953
2954                 edge_label = rem;
2955                 dump_vcg_footer(F);
2956                 fclose(F);
2957         }
2958 }
2959
2960 #if 0
2961 /* Dump all irgs in interprocedural view to a single file. */
2962 void dump_all_cg_block_graph(const char *suffix)
2963 {
2964         FILE *f = vcg_open_name("All_graphs", suffix);
2965
2966         if (f != NULL) {
2967                 int i;
2968                 int rem_view = get_interprocedural_view();
2969
2970                 set_interprocedural_view(1);
2971                 dump_vcg_header(f, "All_graphs", NULL);
2972
2973                 /* collect nodes in all irgs reachable in call graph*/
2974                 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2975                         ird_set_irg_link(get_irp_irg(i), NULL);
2976
2977                 cg_walk(clear_link, collect_node, NULL);
2978
2979                 /* dump all graphs */
2980                 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2981                         current_ir_graph = get_irp_irg(i);
2982                         assert(ird_get_irg_link(current_ir_graph));
2983                         dump_graph_from_list(f, current_ir_graph);
2984                         DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2985                 }
2986
2987                 dump_vcg_footer(f);
2988                 fclose(f);
2989                 set_interprocedural_view(rem_view);
2990         }
2991 }
2992 #endif
2993
2994 /*---------------------------------------------------------------------*/
2995 /* the following routines dumps type information without any ir nodes. */
2996 /*---------------------------------------------------------------------*/
2997
2998 void dump_type_graph(ir_graph *irg, const char *suffix)
2999 {
3000         FILE *f;
3001
3002         /* if a filter is set, dump only the irg's that match the filter */
3003         if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
3004
3005         f = vcg_open(irg, suffix, "-type");
3006         if (f != NULL) {
3007                 ir_graph *rem = current_ir_graph;
3008                 current_ir_graph = irg;
3009
3010                 dump_vcg_header(f, get_irg_dump_name(irg), "Hierarchic", NULL);
3011
3012                 /* walk over the blocks in the graph */
3013                 type_walk_irg(irg, dump_type_info, NULL, f);
3014                 /* The walker for the const code can be called several times for the
3015                    same (sub) expression.  So that no nodes are dumped several times
3016                    we decrease the visited flag of the corresponding graph after each
3017                    walk.  So now increase it finally. */
3018                 inc_irg_visited(get_const_code_irg());
3019
3020                 dump_vcg_footer(f);
3021                 fclose(f);
3022                 current_ir_graph = rem;
3023         }
3024 }
3025
3026 void dump_all_types(const char *suffix)
3027 {
3028         FILE *f = vcg_open_name("All_types", suffix);
3029         if (f != NULL) {
3030                 dump_vcg_header(f, "All_types", "Hierarchic", NULL);
3031                 type_walk(dump_type_info, NULL, f);
3032                 inc_irg_visited(get_const_code_irg());
3033
3034                 dump_vcg_footer(f);
3035                 fclose(f);
3036         }
3037 }
3038
3039 void dump_class_hierarchy(int entities, const char *suffix)
3040 {
3041         FILE *f = vcg_open_name("class_hierarchy", suffix);
3042
3043         if (f != NULL) {
3044                 h_env_t env;
3045                 env.f        = f;
3046                 env.dump_ent = entities;
3047                 dump_vcg_header(f, "class_hierarchy", "Hierarchic", NULL);
3048                 type_walk(dump_class_hierarchy_node, NULL, &env);
3049
3050                 dump_vcg_footer(f);
3051                 fclose(f);
3052         }
3053 }
3054
3055 /*---------------------------------------------------------------------*/
3056 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
3057 /*  dump_ir_graph                                                      */
3058 /*  dump_ir_block_graph                                                */
3059 /*  dump_cfg                                                           */
3060 /*  dump_type_graph                                                    */
3061 /*  dump_ir_graph_w_types                                              */
3062 /*---------------------------------------------------------------------*/
3063
3064 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix)
3065 {
3066         int i;
3067         for (i = get_irp_n_irgs() - 1; i >= 0; --i)
3068                 dmp_grph(get_irp_irg(i), suffix);
3069 }
3070
3071 struct pass_t {
3072         ir_prog_pass_t  pass;
3073         dump_graph_func *dump_graph;
3074         char            suffix[1];
3075 };
3076
3077 /**
3078  * Wrapper around dump_all_ir_graphs().
3079  */
3080 static int dump_all_ir_graphs_wrapper(ir_prog *irp, void *context)
3081 {
3082         struct pass_t *pass = context;
3083
3084         (void)irp;
3085         dump_all_ir_graphs(pass->dump_graph, pass->suffix);
3086         return 0;
3087 }
3088
3089 ir_prog_pass_t *dump_all_ir_graph_pass(const char *name,
3090                                        dump_graph_func *dump_graph,
3091                                        const char *suffix)
3092 {
3093         size_t         len   = strlen(suffix);
3094         struct pass_t  *pass = xmalloc(sizeof(*pass) + len);
3095         ir_prog_pass_t *res  = def_prog_pass_constructor(
3096                 &pass->pass, name ? name : "dump_all_graphs", dump_all_ir_graphs_wrapper);
3097
3098         /* this pass does not change anything, so neither dump nor verify is needed. */
3099         res->dump_irprog   = ir_prog_no_dump;
3100         res->verify_irprog = ir_prog_no_verify;
3101
3102         pass->dump_graph = dump_graph;
3103         strcpy(pass->suffix, suffix);
3104
3105         return res;
3106 }
3107
3108 /*--------------------------------------------------------------------------------*
3109  * Dumps a stand alone loop graph with firm nodes which belong to one loop node   *
3110  * packed together in one subgraph/box                                            *
3111  *--------------------------------------------------------------------------------*/
3112
3113 static void dump_loops_standalone(FILE *F, ir_loop *loop)
3114 {
3115         int i = 0, loop_node_started = 0, son_number = 0, first = 0;
3116         loop_element le;
3117         ir_loop *son = NULL;
3118
3119         /* Dump a new loop node. */
3120         dump_loop_node(F, loop);
3121
3122         /* Dump the loop elements. */
3123         for (i = 0; i < get_loop_n_elements(loop); i++) {
3124                 le = get_loop_element(loop, i);
3125                 son = le.son;
3126                 if (get_kind(son) == k_ir_loop) {
3127
3128                         /* We are a loop son -> Recurse */
3129
3130                         if (loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
3131                                 fprintf(F, "\" }\n");
3132                                 fprintf(F, "edge: {sourcename: \"");
3133                                 PRINT_LOOPID(loop);
3134                                 fprintf(F, "\" targetname: \"");
3135                                 PRINT_LOOPID(loop);
3136                                 fprintf(F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
3137                                 loop_node_started = 0;
3138                         }
3139                         dump_loop_son_edge(F, loop, son_number++);
3140                         dump_loops_standalone(F, son);
3141                 } else if (get_kind(son) == k_ir_node) {
3142                         /* We are a loop node -> Collect firm nodes */
3143
3144                         ir_node *n = le.node;
3145                         int bad = 0;
3146
3147                         if (!loop_node_started) {
3148                                 /* Start a new node which contains all firm nodes of the current loop */
3149                                 fprintf(F, "node: { title: \"");
3150                                 PRINT_LOOPID(loop);
3151                                 fprintf(F, "-%d-nodes\" color: lightyellow label: \"", i);
3152                                 loop_node_started = 1;
3153                                 first = i;
3154                         } else
3155                                 fprintf(F, "\n");
3156
3157                         bad |= dump_node_label(F, n);
3158                         /* Causes indeterministic output: if (is_Block(n)) fprintf(F, "\t ->%d", (int)get_irn_link(n)); */
3159                         if (has_backedges(n)) fprintf(F, "\t loop head!");
3160                 } else { /* for callgraph loop tree */
3161                         ir_graph *n;
3162                         assert(get_kind(son) == k_ir_graph);
3163
3164                         /* We are a loop node -> Collect firm graphs */
3165                         n = le.irg;
3166                         if (!loop_node_started) {
3167                                 /* Start a new node which contains all firm nodes of the current loop */
3168                                 fprintf(F, "node: { title: \"");
3169                                 PRINT_LOOPID(loop);
3170                                 fprintf(F, "-%d-nodes\" color: lightyellow label: \"", i);
3171                                 loop_node_started = 1;
3172                                 first = i;
3173                         } else
3174                                 fprintf(F, "\n");
3175                         fprintf(F, " %s", get_irg_dump_name(n));
3176                         /* fprintf(F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
3177                 }
3178         }
3179
3180         if (loop_node_started) {
3181                 fprintf(F, "\" }\n");
3182                 fprintf(F, "edge: {sourcename: \"");
3183                 PRINT_LOOPID(loop);
3184                 fprintf(F, "\" targetname: \"");
3185                 PRINT_LOOPID(loop);
3186                 fprintf(F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
3187                 loop_node_started = 0;
3188         }
3189 }
3190
3191 void dump_loop_tree(ir_graph *irg, const char *suffix)
3192 {
3193         FILE *f;
3194
3195         /* if a filter is set, dump only the irg's that match the filter */
3196         if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
3197                 return;
3198
3199         f = vcg_open(irg, suffix, "-looptree");
3200         if (f != NULL) {
3201                 ir_graph *rem = current_ir_graph;
3202                 int el_rem = edge_label;
3203
3204                 current_ir_graph = irg;
3205                 edge_label = 1;
3206
3207                 dump_vcg_header(f, get_irg_dump_name(irg), "Tree", "top_to_bottom");
3208
3209                 if (get_irg_loop(irg))
3210                         dump_loops_standalone(f, get_irg_loop(irg));
3211
3212                 dump_vcg_footer(f);
3213                 fclose(f);
3214
3215                 edge_label = el_rem;
3216                 current_ir_graph = rem;
3217         }
3218 }
3219
3220 void dump_callgraph_loop_tree(const char *suffix)
3221 {
3222         FILE *F;
3223         F = vcg_open_name("Callgraph_looptree", suffix);
3224         dump_vcg_header(F, "callgraph looptree", "Tree", "top_to_bottom");
3225         dump_loops_standalone(F, irp->outermost_cg_loop);
3226         dump_vcg_footer(F);
3227         fclose(F);
3228 }
3229
3230
3231 /*----------------------------------------------------------------------------*/
3232 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes.*/
3233 /*----------------------------------------------------------------------------*/
3234
3235 static void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes)
3236 {
3237         int i, son_number = 0, node_number = 0;
3238
3239         if (dump_loop_information_flag) dump_loop_node(F, loop);
3240
3241         for (i = 0; i < get_loop_n_elements(loop); i++) {
3242                 loop_element le = get_loop_element(loop, i);
3243                 if (*(le.kind) == k_ir_loop) {
3244                         if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
3245                         /* Recur */
3246                         collect_nodeloop(F, le.son, loopnodes);
3247                 } else {
3248                         if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
3249                         eset_insert(loopnodes, le.node);
3250                 }
3251         }
3252 }
3253
3254 static void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes,
3255                                             eset *extnodes)
3256 {
3257         int i, j, start;
3258
3259         for (i = 0; i < get_loop_n_elements(loop); i++) {
3260                 loop_element le = get_loop_element(loop, i);
3261                 if (*(le.kind) == k_ir_loop) {
3262                         /* Recur */
3263                         collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
3264                 } else {
3265                         if (is_Block(le.node)) start = 0; else start = -1;
3266                         for (j = start; j < get_irn_arity(le.node); j++) {
3267                                 ir_node *pred = get_irn_n(le.node, j);
3268                                 if (!eset_contains(loopnodes, pred)) {
3269                                         eset_insert(extnodes, pred);
3270                                         if (!is_Block(pred)) {
3271                                                 pred = get_nodes_block(pred);
3272                                                 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
3273                                         }
3274                                 }
3275                         }
3276                 }
3277         }
3278 }
3279
3280 void dump_loop(ir_loop *l, const char *suffix)
3281 {
3282         FILE *F;
3283         char name[50];
3284
3285         snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
3286         F = vcg_open_name(name, suffix);
3287         if (F != NULL) {
3288                 eset *loopnodes = eset_create();
3289                 eset *extnodes = eset_create();
3290                 ir_node *n, *b;
3291
3292                 dump_vcg_header(F, name, NULL, NULL);
3293
3294                 /* collect all nodes to dump */
3295                 collect_nodeloop(F, l, loopnodes);
3296                 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
3297
3298                 /* build block lists */
3299                 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3300                         set_irn_link(n, NULL);
3301                 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3302                         set_irn_link(n, NULL);
3303                 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes)) {
3304                         if (!is_Block(n)) {
3305                                 b = get_nodes_block(n);
3306                                 set_irn_link(n, get_irn_link(b));
3307                                 set_irn_link(b, n);
3308                         }
3309                 }
3310                 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes)) {
3311                         if (!is_Block(n)) {
3312                                 b = get_nodes_block(n);
3313                                 set_irn_link(n, get_irn_link(b));
3314                                 set_irn_link(b, n);
3315                         }
3316                 }
3317
3318                 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes)) {
3319                         if (is_Block(b)) {
3320                                 fprintf(F, "graph: { title: \"");
3321                                 PRINT_NODEID(b);
3322                                 fprintf(F, "\"  label: \"");
3323                                 dump_node_opcode(F, b);
3324                                 fprintf(F, " %ld:%d", get_irn_node_nr(b), get_irn_idx(b));
3325                                 fprintf(F, "\" status:clustered color:yellow\n");
3326
3327                                 /* dump the blocks edges */
3328                                 dump_ir_data_edges(F, b);
3329
3330                                 /* dump the nodes that go into the block */
3331                                 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3332                                         if (eset_contains(extnodes, n))
3333                                                 overrule_nodecolor = ird_color_block_inout;
3334                                         dump_node(F, n);
3335                                         overrule_nodecolor = ird_color_default_node;
3336                                         if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
3337                                 }
3338
3339                                 /* Close the vcg information for the block */
3340                                 fprintf(F, "}\n");
3341                                 dump_const_node_local(F, b);
3342                                 fprintf(F, "\n");
3343                         }
3344                 }
3345                 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes)) {
3346                         if (is_Block(b)) {
3347                                 fprintf(F, "graph: { title: \"");
3348                                 PRINT_NODEID(b);
3349                                 fprintf(F, "\"  label: \"");
3350                                 dump_node_opcode(F, b);
3351                                 fprintf(F, " %ld:%d", get_irn_node_nr(b), get_irn_idx(b));
3352                                 fprintf(F, "\" status:clustered color:lightblue\n");
3353
3354                                 /* dump the nodes that go into the block */
3355                                 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3356                                         if (!eset_contains(loopnodes, n))
3357                                                 overrule_nodecolor = ird_color_block_inout;
3358                                         dump_node(F, n);
3359                                         overrule_nodecolor = ird_color_default_node;
3360                                         if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
3361                                 }
3362
3363                                 /* Close the vcg information for the block */
3364                                 fprintf(F, "}\n");
3365                                 dump_const_node_local(F, b);
3366                                 fprintf(F, "\n");
3367                         }
3368                 }
3369                 eset_destroy(loopnodes);
3370                 eset_destroy(extnodes);
3371
3372                 dump_vcg_footer(F);
3373                 fclose(F);
3374         }
3375 }