3cc3224dd64d695d1b811bd5a1bf8616f7497822
[libfirm] / ir / ir / irdump.c
1 /*
2  * Copyright (C) 1995-2011 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  *          Matthias Braun
25  * @version $Id$
26  */
27 #include "config.h"
28
29 #include <string.h>
30 #include <stdlib.h>
31 #include <stdarg.h>
32 #include <stdbool.h>
33 #include <errno.h>
34
35 #include "list.h"
36
37 #include "irnode_t.h"
38 #include "irgraph_t.h"
39 #include "irprog_t.h"
40 #include "entity_t.h"
41 #include "irop.h"
42
43 #include "irdump_t.h"
44 #include "irpass_t.h"
45
46 #include "irgwalk.h"
47 #include "tv_t.h"
48 #include "irouts.h"
49 #include "iredges.h"
50 #include "irdom.h"
51 #include "irloop_t.h"
52 #include "callgraph.h"
53 #include "irextbb_t.h"
54 #include "irhooks.h"
55 #include "dbginfo_t.h"
56 #include "irtools.h"
57 #include "irprintf.h"
58
59 #include "irverify.h"
60
61 #include "error.h"
62 #include "array.h"
63 #include "pmap.h"
64 #include "obst.h"
65 #include "eset.h"
66 #include "pset.h"
67 #include "util.h"
68
69 typedef struct pns_lookup {
70         long       nr;      /**< the proj number */
71         const char *name;   /**< the name of the Proj */
72 } pns_lookup_t;
73
74 typedef struct proj_lookup {
75         unsigned           code;      /**< the opcode of the Proj predecessor */
76         unsigned           num_data;  /**< number of data entries */
77         const pns_lookup_t *data;     /**< the data */
78 } proj_lookup_t;
79
80 #include "gen_irdump.c.inl"
81
82 /** Dump only irgs with names that start with this prefix. */
83 static ident *dump_file_filter_id = NULL;
84
85 static ir_dump_flags_t flags =
86         ir_dump_flag_blocks_as_subgraphs |
87         ir_dump_flag_keepalive_edges |
88         ir_dump_flag_ld_names |
89         ir_dump_flag_back_edges |
90         ir_dump_flag_consts_local |
91         ir_dump_flag_analysed_types |
92         ir_dump_flag_entities_in_hierarchy |
93         ir_dump_flag_number_label;
94
95 static ird_color_t overrule_nodecolor = ird_color_default_node;
96
97 /** The vcg node attribute hook. */
98 static dump_node_vcgattr_func dump_node_vcgattr_hook = NULL;
99 /** The vcg edge attribute hook. */
100 static dump_edge_vcgattr_func dump_edge_vcgattr_hook = NULL;
101 /** The vcg dump block edge hook */
102 static dump_node_edge_func dump_block_edge_hook = NULL;
103 /** The vcg dump node edge hook. */
104 static dump_node_edge_func dump_node_edge_hook = NULL;
105
106 void set_dump_node_edge_hook(dump_node_edge_func func)
107 {
108         dump_node_edge_hook = func;
109 }
110
111 dump_node_edge_func get_dump_node_edge_hook(void)
112 {
113         return dump_node_edge_hook;
114 }
115
116 void set_dump_block_edge_hook(dump_node_edge_func func)
117 {
118         dump_block_edge_hook = func;
119 }
120
121 dump_node_edge_func get_dump_block_edge_hook(void)
122 {
123         return dump_node_edge_hook;
124 }
125
126 void set_dump_node_vcgattr_hook(dump_node_vcgattr_func hook)
127 {
128         dump_node_vcgattr_hook = hook;
129 }
130
131 void set_dump_edge_vcgattr_hook(dump_edge_vcgattr_func hook)
132 {
133         dump_edge_vcgattr_hook = hook;
134 }
135
136 void ir_set_dump_flags(ir_dump_flags_t new_flags)
137 {
138         flags = new_flags;
139 }
140
141 void ir_add_dump_flags(ir_dump_flags_t new_flags)
142 {
143         flags |= new_flags;
144 }
145
146 void ir_remove_dump_flags(ir_dump_flags_t to_remove)
147 {
148         flags &= ~to_remove;
149 }
150
151 ir_dump_flags_t ir_get_dump_flags(void)
152 {
153         return flags;
154 }
155
156 /** Returns 0 if dump_out_edge_flag or dump_loop_information_flag
157  * are set, else returns dump_const_local_flag.
158  */
159 static bool get_opt_dump_const_local(void)
160 {
161         return (flags & ir_dump_flag_out_edges)
162                 || (flags & ir_dump_flag_loops)
163                 || (flags & ir_dump_flag_consts_local)
164                 || (flags & ir_dump_flag_iredges);
165 }
166
167 static char *dump_filter;
168
169 void ir_set_dump_filter(const char *new_filter)
170 {
171         xfree(dump_filter);
172         dump_filter = xstrdup(new_filter);
173 }
174
175 const char *ir_get_dump_filter(void)
176 {
177         return dump_filter;
178 }
179
180 int ir_should_dump(const char *name)
181 {
182         const char *f, *n;
183
184         if (dump_filter == NULL || dump_filter[0] == '\0')
185                 return 1;
186
187         for (n = name, f = dump_filter; *f != '\0' && *n != '\0';
188                         ++n, ++f) {
189                 if (*n != *f)
190                         return 0;
191         }
192         return 1;
193 }
194
195 /* -------------- some extended helper functions ----------------- */
196
197 const char *get_mode_name_ex(const ir_mode *mode, int *bad)
198 {
199         if (is_mode(mode))
200                 return get_mode_name(mode);
201         if (bad != NULL)
202                 *bad |= 1;
203         return "<ERROR>";
204 }
205
206 #define CUSTOM_COLOR_BASE    100
207 static const char *color_names[ird_color_count];
208 static const char *color_rgb[ird_color_count];
209 static struct obstack color_obst;
210
211 /** define a custom color. */
212 static void custom_color(int num, const char *rgb_def)
213 {
214         assert(num < ird_color_count);
215         obstack_printf(&color_obst, "%d", CUSTOM_COLOR_BASE + num);
216         obstack_1grow(&color_obst, '\0');
217
218         color_rgb[num]   = rgb_def;
219         color_names[num] = (const char*)obstack_finish(&color_obst);
220 }
221
222 /** Define a named color. */
223 static void named_color(int num, const char *name)
224 {
225         assert(num < ird_color_count);
226         color_rgb[num]   = NULL;
227         color_names[num] = name;
228 }
229
230 /** Initializes the used colors. */
231 static void init_colors(void)
232 {
233         static int initialized = 0;
234         if (initialized)
235                 return;
236
237         obstack_init(&color_obst);
238
239         custom_color(ird_color_prog_background,       "204 204 204");
240         custom_color(ird_color_block_background,      "255 255 0");
241         custom_color(ird_color_dead_block_background, "190 150 150");
242         named_color(ird_color_block_inout,            "lightblue");
243         named_color(ird_color_default_node,           "white");
244         custom_color(ird_color_memory,                "153 153 255");
245         custom_color(ird_color_controlflow,           "255 153 153");
246         custom_color(ird_color_const,                 "204 255 255");
247         custom_color(ird_color_proj,                  "255 255 153");
248         custom_color(ird_color_uses_memory,           "153 153 255");
249         custom_color(ird_color_phi,                   "105 255 105");
250         custom_color(ird_color_anchor,                "100 100 255");
251         named_color(ird_color_error,                  "red");
252         custom_color(ird_color_entity,                "204 204 255");
253
254         initialized = 1;
255 }
256
257 /**
258  * Prints the VCG color to a file.
259  */
260 static void print_vcg_color(FILE *out, ird_color_t color)
261 {
262         assert(color < ird_color_count);
263         fprintf(out, "color:%s", color_names[color]);
264 }
265
266 /**
267  * Prints the edge kind of a given IR node.
268  *
269  * Projs should be dumped near their predecessor, so they get "nearedge".
270  */
271 static void print_node_edge_kind(FILE *out, ir_node *node)
272 {
273         if (is_Proj(node)) {
274                 fprintf(out, "nearedge: ");
275         } else {
276                 fprintf(out, "edge: ");
277         }
278 }
279
280 /**
281  * Prints the edge from a type S to a type T with additional info fmt, ...
282  * to the file F.
283  */
284 static void print_type_type_edge(FILE *F, const ir_type *S, const ir_type *T, const char *fmt, ...)
285 {
286         va_list ap;
287
288         va_start(ap, fmt);
289         fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
290         fprintf(F, " targetname: "); PRINT_TYPEID(T);
291         ir_vfprintf(F, fmt, ap);
292         fprintf(F,"}\n");
293         va_end(ap);
294 }
295
296 /**
297  * Prints the edge from a type tp to an entity ent with additional info fmt, ...
298  * to the file F.
299  */
300 static void print_type_ent_edge(FILE *F, const ir_type *tp, const ir_entity *ent, const char *fmt, ...)
301 {
302         va_list ap;
303
304         va_start(ap, fmt);
305         fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
306         fprintf(F, " targetname: \""); PRINT_ENTID(ent); fprintf(F, "\"");
307         ir_vfprintf(F, fmt, ap);
308         fprintf(F, "}\n");
309         va_end(ap);
310 }
311
312 /**
313  * Prints the edge from an entity ent1 to an entity ent2 with additional info fmt, ...
314  * to the file F.
315  */
316 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, ...)
317 {
318         va_list ap;
319
320         va_start(ap, fmt);
321         if (backedge)
322                 fprintf(F, "backedge: { sourcename: \"");
323         else
324                 fprintf(F, "edge: { sourcename: \"");
325         PRINT_ENTID(ent1);
326         fprintf(F, "\" targetname: \""); PRINT_ENTID(ent2);  fprintf(F, "\"");
327         ir_vfprintf(F, fmt, ap);
328         fprintf(F, " ");
329         if (color != ird_color_none)
330                 print_vcg_color(F, color);
331         fprintf(F, "}\n");
332         va_end(ap);
333 }
334
335 /**
336  * Prints the edge from an entity ent to a type tp with additional info fmt, ...
337  * to the file F.
338  */
339 static void print_ent_type_edge(FILE *F, const ir_entity *ent, const ir_type *tp, const char *fmt, ...)
340 {
341         va_list ap;
342
343         va_start(ap, fmt);
344         fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
345         fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
346         ir_vfprintf(F, fmt, ap);
347         fprintf(F,"}\n");
348         va_end(ap);
349 }
350
351 /**
352  * Prints the edge from a node irn to a type tp with additional info fmt, ...
353  * to the file F.
354  */
355 static void print_node_type_edge(FILE *F, const ir_node *irn, ir_type *tp, const char *fmt, ...)
356 {
357         va_list ap;
358
359         va_start(ap, fmt);
360         fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
361         fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
362         ir_vfprintf(F, fmt, ap);
363         fprintf(F,"}\n");
364         va_end(ap);
365 }
366
367 /**
368  * Prints the edge from a node irn to an entity ent with additional info fmt, ...
369  * to the file F.
370  */
371 static void print_node_ent_edge(FILE *F, const ir_node *irn, const ir_entity *ent, const char *fmt, ...)
372 {
373         va_list ap;
374
375         va_start(ap, fmt);
376         fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
377         fprintf(F, "\" targetname: \""); PRINT_ENTID(ent);
378         fprintf(F, "\"");
379         ir_vfprintf(F, fmt, ap);
380         fprintf(F,"}\n");
381         va_end(ap);
382 }
383
384 /**
385  * Prints the edge from an entity ent to a node irn with additional info fmt, ...
386  * to the file F.
387  */
388 static void print_ent_node_edge(FILE *F, const ir_entity *ent, const ir_node *irn, const char *fmt, ...)
389 {
390         va_list ap;
391
392         va_start(ap, fmt);
393         fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
394         fprintf(F, "\" targetname: \""); PRINT_NODEID(irn); fprintf(F, "\"");
395         ir_vfprintf(F, fmt, ap);
396         fprintf(F,"}\n");
397         va_end(ap);
398 }
399
400 /**
401  * Prints the edge from a type tp to an enumeration item item with additional info fmt, ...
402  * to the file F.
403  */
404 static void print_enum_item_edge(FILE *F, const ir_type *tp, size_t item, const char *fmt, ...)
405 {
406         va_list ap;
407
408         va_start(ap, fmt);
409         fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
410         fprintf(F, " targetname: \""); PRINT_ITEMID(tp, item); fprintf(F, "\" ");
411         ir_vfprintf(F, fmt, ap);
412         fprintf(F,"}\n");
413         va_end(ap);
414 }
415
416 /*-----------------------------------------------------------------*/
417 /* global and ahead declarations                                   */
418 /*-----------------------------------------------------------------*/
419
420 static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
421
422 /*-----------------------------------------------------------------*/
423 /* Helper functions.                                                */
424 /*-----------------------------------------------------------------*/
425
426 /**
427  * This map is used as a private link attr to be able to call dumper
428  * anywhere without destroying link fields.
429  */
430 static pmap *irdump_link_map = NULL;
431
432 /** NOT A STANDARD LIBFIRM INIT METHOD
433  *
434  * We do not want to integrate dumping into libfirm, i.e., if the dumpers
435  * are off, we want to have as few interferences as possible.  Therefore the
436  * initialization is performed lazily and not called from within init_firm.
437  *
438  * Creates the link attribute map. */
439 static void init_irdump(void)
440 {
441         /* We need a new, empty map. */
442         if (irdump_link_map) pmap_destroy(irdump_link_map);
443         irdump_link_map = pmap_create();
444         if (!dump_file_filter_id)
445                 dump_file_filter_id = new_id_from_str("");
446 }
447
448 /**
449  * Returns the private link field.
450  */
451 static void *ird_get_irn_link(const ir_node *n)
452 {
453         void *res = NULL;
454         if (irdump_link_map == NULL)
455                 return NULL;
456
457         if (pmap_contains(irdump_link_map, n))
458                 res = pmap_get(irdump_link_map, n);
459         return res;
460 }
461
462 /**
463  * Sets the private link field.
464  */
465 static void ird_set_irn_link(const ir_node *n, void *x)
466 {
467         if (irdump_link_map == NULL)
468                 init_irdump();
469         pmap_insert(irdump_link_map, n, x);
470 }
471
472 /**
473  * Gets the private link field of an irg.
474  */
475 static void *ird_get_irg_link(const ir_graph *irg)
476 {
477         void *res = NULL;
478         if (irdump_link_map == NULL)
479                 return NULL;
480
481         if (pmap_contains(irdump_link_map, irg))
482                 res = pmap_get(irdump_link_map, irg);
483         return res;
484 }
485
486 /**
487  * Sets the private link field of an irg.
488  */
489 static void ird_set_irg_link(const ir_graph *irg, void *x)
490 {
491         if (irdump_link_map == NULL)
492                 init_irdump();
493         pmap_insert(irdump_link_map, irg, x);
494 }
495
496 /**
497  * Walker, clears the private link field.
498  */
499 static void clear_link(ir_node *node, void *env)
500 {
501         (void) env;
502         ird_set_irn_link(node, NULL);
503 }
504
505 /**
506  * If the entity has a ld_name, returns it if the dump_ld_name is set,
507  * else returns the name of the entity.
508  */
509 static const char *_get_ent_dump_name(const ir_entity *ent, bool dump_ld_name)
510 {
511         if (ent == NULL)
512                 return "<NULL entity>";
513         if (dump_ld_name) {
514                 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
515                 if (ent->ld_name != NULL)
516                         return get_id_str(ent->ld_name);
517         }
518         return get_id_str(ent->name);
519 }
520
521 const char *get_ent_dump_name(const ir_entity *ent)
522 {
523         return _get_ent_dump_name(ent, flags & ir_dump_flag_ld_names);
524 }
525
526 const char *get_irg_dump_name(const ir_graph *irg)
527 {
528         /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
529         return _get_ent_dump_name(get_irg_entity(irg), true);
530 }
531
532 /**
533  * Returns non-zero if a node is in floating state.
534  */
535 static int node_floats(const ir_node *n)
536 {
537         return ((get_irn_pinned(n) == op_pin_state_floats) &&
538                 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
539 }
540
541 /**
542  *  Walker that visits the anchors
543  */
544 static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env)
545 {
546         if ((flags & ir_dump_flag_all_anchors)
547                         || ((flags & ir_dump_flag_iredges) && edges_activated(irg))) {
548                 irg_walk_anchors(irg, pre, post, env);
549         } else {
550                 irg_walk_graph(irg, pre, post, env);
551         }
552 }
553
554 /**
555  * Walker, allocates an array for all blocks and puts their non-floating
556  * nodes into this array.
557  */
558 static void collect_node(ir_node *node, void *env)
559 {
560         (void) env;
561         if (is_Block(node)
562             || node_floats(node)
563             || (get_op_flags(get_irn_op(node)) & irop_flag_dump_noblock)) {
564                 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
565                 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
566                 ARR_APP1(ir_node *, arr, node);
567                 ird_set_irg_link(get_irn_irg(node), arr);    /* arr is an l-value, APP_ARR might change it! */
568         } else {
569                 ir_node * block = get_nodes_block(node);
570
571                 if (is_Bad(block)) {
572                         /* this node is in a Bad block, so we must place it into the graph's list */
573                         ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
574                         if (!arr) arr = NEW_ARR_F(ir_node *, 0);
575                         ARR_APP1(ir_node *, arr, node);
576                         ird_set_irg_link(get_irn_irg(node), arr);    /* arr is an l-value, APP_ARR might change it! */
577                 } else {
578                         ird_set_irn_link(node, ird_get_irn_link(block));
579                         ird_set_irn_link(block, node);
580                 }
581         }
582 }
583
584 /** Construct lists to walk ir block-wise.
585  *
586  * Collects all blocks, nodes not op_pin_state_pinned,
587  * Bad, NoMem and Unknown into a flexible array in link field of
588  * irg they belong to.  Sets the irg link field to NULL in all
589  * graphs not visited.
590  * Free the list with DEL_ARR_F().
591  */
592 static ir_node **construct_block_lists(ir_graph *irg)
593 {
594         size_t   i;
595         int      walk_flag = ir_resources_reserved(irg) & IR_RESOURCE_IRN_VISITED;
596         ir_graph *rem      = current_ir_graph;
597
598         current_ir_graph = irg;
599
600         if (walk_flag) {
601                 ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
602         }
603
604         for (i = get_irp_n_irgs(); i > 0;)
605                 ird_set_irg_link(get_irp_irg(--i), NULL);
606
607         ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
608
609         if (walk_flag) {
610                 ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
611         }
612
613         current_ir_graph = rem;
614         return (ir_node**)ird_get_irg_link(irg);
615 }
616
617 typedef struct list_tuple {
618         ir_node **blk_list;
619         ir_extblk **extbb_list;
620 } list_tuple;
621
622 /** Construct lists to walk IR extended block-wise.
623  * Free the lists in the tuple with DEL_ARR_F(). Sets the irg link field to
624  * NULL in all graphs not visited.
625  */
626 static list_tuple *construct_extblock_lists(ir_graph *irg)
627 {
628         ir_node **blk_list = construct_block_lists(irg);
629         size_t i, n;
630         ir_graph *rem = current_ir_graph;
631         list_tuple *lists = XMALLOC(list_tuple);
632
633         current_ir_graph = irg;
634
635         lists->blk_list   = NEW_ARR_F(ir_node *, 0);
636         lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
637
638         inc_irg_block_visited(irg);
639         for (i = 0, n = ARR_LEN(blk_list); i < n; ++i) {
640                 ir_extblk *ext;
641
642                 if (is_Block(blk_list[i])) {
643                         ext = get_Block_extbb(blk_list[i]);
644
645                         if (extbb_not_visited(ext)) {
646                                 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
647                                 mark_extbb_visited(ext);
648                         }
649                 } else
650                         ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
651         }
652         DEL_ARR_F(blk_list);
653
654         current_ir_graph = rem;
655         ird_set_irg_link(irg, lists);
656         return lists;
657 }
658
659 void dump_node_opcode(FILE *F, ir_node *n)
660 {
661         const ir_op_ops *ops = get_op_ops(get_irn_op(n));
662
663         /* call the dump_node operation if available */
664         if (ops->dump_node) {
665                 ops->dump_node(F, n, dump_node_opcode_txt);
666                 return;
667         }
668
669         /* implementation for default nodes */
670         switch (get_irn_opcode(n)) {
671         case iro_SymConst:
672                 switch (get_SymConst_kind(n)) {
673                 case symconst_addr_ent:
674                         fprintf(F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
675                         break;
676                 case symconst_ofs_ent:
677                         fprintf(F, "SymC %s offset", get_entity_name(get_SymConst_entity(n)));
678                         break;
679                 case symconst_type_tag:
680                         ir_fprintf(F, "SymC %+F tag", get_SymConst_type(n));
681                         break;
682                 case symconst_type_size:
683                         ir_fprintf(F, "SymC %+F size", get_SymConst_type(n));
684                         break;
685                 case symconst_type_align:
686                         ir_fprintf(F, "SymC %+F align", get_SymConst_type(n));
687                         break;
688                 case symconst_enum_const:
689                         fprintf(F, "SymC %s enum", get_enumeration_const_name(get_SymConst_enum(n)));
690                         break;
691                 }
692                 break;
693
694         case iro_Proj: {
695                 ir_node *pred = get_Proj_pred(n);
696
697                 if (get_irn_opcode(pred) == iro_Cond
698                         && get_Proj_proj(n) == get_Cond_default_proj(pred)
699                         && get_irn_mode(get_Cond_selector(pred)) != mode_b)
700                         fprintf(F, "defProj");
701                 else
702                         goto default_case;
703         } break;
704
705         case iro_Load:
706                 if (get_Load_unaligned(n) == align_non_aligned)
707                         fprintf(F, "ua");
708                 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), NULL));
709                 break;
710         case iro_Store:
711                 if (get_Store_unaligned(n) == align_non_aligned)
712                         fprintf(F, "ua");
713                 fprintf(F, "%s", get_irn_opname(n));
714                 break;
715         case iro_Block:
716                 if (n == get_irg_start_block(get_irn_irg(n)))
717                         fputs("Start ", F);
718                 if (n == get_irg_end_block(get_irn_irg(n)))
719                         fputs("End ", F);
720                 fprintf(F, "%s%s", get_irn_opname(n),
721                         (flags & ir_dump_flag_show_marks) ? (get_Block_mark(n) ? "*" : "") : "");
722                 break;
723         case iro_Conv:
724                 if (get_Conv_strict(n))
725                         fprintf(F, "strict");
726                 fprintf(F, "%s", get_irn_opname(n));
727                 break;
728         case iro_Div:
729                 fprintf(F, "%s", get_irn_opname(n));
730                 if (get_Div_no_remainder(n))
731                         fprintf(F, "RL");
732                 fprintf(F, "[%s]", get_mode_name_ex(get_Div_resmode(n), NULL));
733                 break;
734         case iro_Mod:
735                 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Mod_resmode(n), NULL));
736                 break;
737         case iro_Builtin:
738                 fprintf(F, "%s[%s]", get_irn_opname(n), get_builtin_kind_name(get_Builtin_kind(n)));
739                 break;
740
741         default:
742 default_case:
743                 fprintf(F, "%s", get_irn_opname(n));
744         }
745 }
746
747 /**
748  * Dump the mode of a node n to a file F.
749  * Ignore modes that are "always known".
750  */
751 static void dump_node_mode(FILE *F, ir_node *n)
752 {
753         const ir_op_ops *ops = get_op_ops(get_irn_op(n));
754         unsigned         iro;
755         ir_mode         *mode;
756
757         /* call the dump_node operation if available */
758         if (ops->dump_node) {
759                 ops->dump_node(F, n, dump_node_mode_txt);
760                 return;
761         }
762
763         /* default implementation */
764         iro = get_irn_opcode(n);
765         switch (iro) {
766         case iro_SymConst:
767         case iro_Sel:
768         case iro_End:
769         case iro_Return:
770         case iro_Free:
771         case iro_Sync:
772         case iro_Jmp:
773         case iro_NoMem:
774                 break;
775         default:
776                 mode = get_irn_mode(n);
777
778                 if (mode != NULL && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
779                         (mode != mode_T || iro == iro_Proj))
780                         fprintf(F, "%s", get_mode_name_ex(mode, NULL));
781         }
782 }
783
784 /**
785  * Dump the type of a node n to a file F if it's known.
786  */
787 static int dump_node_typeinfo(FILE *F, ir_node *n)
788 {
789         int bad = 0;
790
791         if (ir_get_dump_flags() & ir_dump_flag_analysed_types) {
792                 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent  ||
793                         get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
794                         ir_type *tp = get_irn_typeinfo_type(n);
795                         if (tp != firm_none_type) {
796                                 ir_fprintf(F, "[%+F]", tp);
797                         } else {
798                                 fprintf(F, "[] ");
799                         }
800                 }
801         }
802         return bad;
803 }
804
805 /**
806  * Dump additional node attributes of some nodes to a file F.
807  */
808 static void dump_node_nodeattr(FILE *F, ir_node *n)
809 {
810         ir_node *pred;
811         unsigned code;
812         long proj_nr;
813         const ir_op_ops *ops = get_op_ops(get_irn_op(n));
814
815         /* call the dump_node operation if available */
816         if (ops->dump_node) {
817                 ops->dump_node(F, n, dump_node_nodeattr_txt);
818                 return;
819         }
820
821         switch (get_irn_opcode(n)) {
822         case iro_Const:
823                 ir_fprintf(F, "%T ", get_Const_tarval(n));
824                 break;
825
826         case iro_Proj:
827                 pred    = get_Proj_pred(n);
828                 proj_nr = get_Proj_proj(n);
829                 code    = get_irn_opcode(pred);
830
831                 if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
832                         fprintf(F, "Arg %ld ", proj_nr);
833                 else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
834                         fprintf(F, "%ld ", proj_nr);
835                 else {
836                         unsigned i, j, f = 0;
837
838                         for (i = 0; i < ARRAY_SIZE(proj_lut); ++i) {
839                                 if (code == proj_lut[i].code) {
840                                         for (j = 0; j < proj_lut[i].num_data; ++j) {
841                                                 if (proj_nr == proj_lut[i].data[j].nr) {
842                                                         fprintf(F, "%s ", proj_lut[i].data[j].name);
843                                                         f = 1;
844                                                         break;
845                                                 }
846                                         }
847                                         break;
848                                 }
849                         }
850                         if (! f)
851                                 fprintf(F, "%ld ", proj_nr);
852                         if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
853                                 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
854                                         fprintf(F, "PRED ");
855                                 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
856                                         fprintf(F, "PRED ");
857                         }
858                 }
859                 break;
860         case iro_Sel:
861                 fprintf(F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
862                 break;
863         case iro_Cast:
864                 ir_fprintf(F, "(%+F)", get_Cast_type(n));
865                 break;
866         case iro_Cmp:
867                 fprintf(F, "%s ", get_relation_string(get_Cmp_relation(n)));
868                 break;
869         case iro_Confirm:
870                 fprintf(F, "%s ", get_relation_string(get_Confirm_relation(n)));
871                 break;
872         case iro_CopyB:
873                 ir_fprintf(F, "(%+F)", get_CopyB_type(n));
874                 break;
875
876         default:
877                 break;
878         }
879 }
880
881 static void dump_node_ana_vals(FILE *F, ir_node *n)
882 {
883         (void) F;
884         (void) n;
885         return;
886 }
887
888 void dump_node_label(FILE *F, ir_node *n)
889 {
890         dump_node_opcode(F, n);
891         fputs(" ", F);
892         dump_node_mode(F, n);
893         fprintf(F, " ");
894         dump_node_typeinfo(F, n);
895         dump_node_nodeattr(F, n);
896         if (flags & ir_dump_flag_number_label) {
897                 fprintf(F, "%ld", get_irn_node_nr(n));
898         }
899         if (flags & ir_dump_flag_idx_label) {
900                 fprintf(F, ":%u", get_irn_idx(n));
901         }
902 }
903
904 /**
905  * Dumps the attributes of a node n into the file F.
906  * Currently this is only the color of a node.
907  */
908 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
909 {
910         ir_mode *mode;
911         ir_node *n;
912
913         if (bad) {
914                 print_vcg_color(F, ird_color_error);
915                 return;
916         }
917
918         if (dump_node_vcgattr_hook != NULL) {
919                 dump_node_vcgattr_hook(F, node, local);
920                 return;
921         }
922
923         n = local ? local : node;
924
925         if (overrule_nodecolor != ird_color_default_node) {
926                 print_vcg_color(F, overrule_nodecolor);
927                 return;
928         }
929
930         mode = get_irn_mode(n);
931         if (mode == mode_M) {
932                 print_vcg_color(F, ird_color_memory);
933                 return;
934         }
935         if (mode == mode_X) {
936                 print_vcg_color(F, ird_color_controlflow);
937                 return;
938         }
939
940         switch (get_irn_opcode(n)) {
941         case iro_Start:
942         case iro_End:
943                 print_vcg_color(F, ird_color_anchor);
944                 break;
945         case iro_Bad:
946                 print_vcg_color(F, ird_color_error);
947                 break;
948         case iro_Block:
949                 print_vcg_color(F, ird_color_block_background);
950                 break;
951         case iro_Phi:
952                 print_vcg_color(F, ird_color_phi);
953                 break;
954         case iro_Pin:
955                 print_vcg_color(F, ird_color_memory);
956                 break;
957         case iro_SymConst:
958         case iro_Const:
959                 print_vcg_color(F, ird_color_const);
960                 break;
961         case iro_Proj:
962                 print_vcg_color(F, ird_color_proj);
963                 break;
964         default: {
965                 ir_op *op = get_irn_op(node);
966
967                 if (is_op_constlike(op)) {
968                         print_vcg_color(F, ird_color_const);
969                 } else if (is_op_uses_memory(op)) {
970                         print_vcg_color(F, ird_color_uses_memory);
971                 } else if (is_op_cfopcode(op) || is_op_forking(op)) {
972                         print_vcg_color(F, ird_color_controlflow);
973                 }
974         }
975         }
976 }
977
978 void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
979 {
980         hook_entry_t *info = XMALLOCZ(hook_entry_t);
981
982         info->hook._hook_node_info = cb;
983         info->context              = data;
984         register_hook(hook_node_info, info);
985
986         return info;
987 }
988
989 void dump_remove_node_info_callback(void *handle)
990 {
991         hook_entry_t *info = (hook_entry_t*)handle;
992         unregister_hook(hook_node_info, info);
993         xfree(info);
994 }
995
996 /**
997  * Dump the node information of a node n to a file F.
998  */
999 static void dump_node_info(FILE *F, ir_node *n)
1000 {
1001         const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1002
1003         fprintf(F, " info1: \"");
1004         dump_irnode_to_file(F, n);
1005         /* call the dump_node operation if available */
1006         if (ops->dump_node)
1007                 ops->dump_node(F, n, dump_node_info_txt);
1008
1009         /* allow additional info to be added */
1010         hook_node_info(F, n);
1011         fprintf(F, "\"\n");
1012 }
1013
1014 static int is_constlike_node(const ir_node *node)
1015 {
1016         const ir_op *op = get_irn_op(node);
1017         return is_op_constlike(op);
1018 }
1019
1020
1021 /** outputs the predecessors of n, that are constants, local.  I.e.,
1022    generates a copy of the constant predecessors for each node called with. */
1023 static void dump_const_node_local(FILE *F, ir_node *n)
1024 {
1025         int i;
1026         if (!get_opt_dump_const_local()) return;
1027
1028         /* Use visited flag to avoid outputting nodes twice.
1029         initialize it first. */
1030         for (i = 0; i < get_irn_arity(n); i++) {
1031                 ir_node *con = get_irn_n(n, i);
1032                 if (is_constlike_node(con)) {
1033                         set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1034                 }
1035         }
1036
1037         for (i = 0; i < get_irn_arity(n); i++) {
1038                 ir_node *con = get_irn_n(n, i);
1039                 if (is_constlike_node(con) && !irn_visited_else_mark(con)) {
1040                         /* Generate a new name for the node by appending the names of
1041                         n and const. */
1042                         fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1043                         fprintf(F, " label: \"");
1044                         dump_node_label(F, con);
1045                         fprintf(F, "\" ");
1046                         dump_node_info(F, con);
1047                         dump_node_vcgattr(F, n, con, 0);
1048                         fprintf(F, "}\n");
1049                 }
1050         }
1051 }
1052
1053 /** If the block of an edge is a const_like node, dump it local with an edge */
1054 static void dump_const_block_local(FILE *F, ir_node *n)
1055 {
1056         ir_node *blk;
1057
1058         if (!get_opt_dump_const_local()) return;
1059
1060         blk = get_nodes_block(n);
1061         if (is_constlike_node(blk)) {
1062                 /* Generate a new name for the node by appending the names of
1063                 n and blk. */
1064                 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1065                 fprintf(F, "\" label: \"");
1066                 dump_node_label(F, blk);
1067                 fprintf(F, "\" ");
1068                 dump_node_info(F, blk);
1069                 dump_node_vcgattr(F, n, blk, 0);
1070                 fprintf(F, "}\n");
1071
1072                 fprintf(F, "edge: { sourcename: \"");
1073                 PRINT_NODEID(n);
1074                 fprintf(F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1075
1076                 if (dump_edge_vcgattr_hook) {
1077                         fprintf(F, "\" ");
1078                         if (dump_edge_vcgattr_hook(F, n, -1)) {
1079                                 fprintf(F, "}\n");
1080                                 return;
1081                         } else {
1082                                 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1083                                 return;
1084                         }
1085                 }
1086
1087                 fprintf(F, "\" "   BLOCK_EDGE_ATTR "}\n");
1088         }
1089 }
1090
1091 /**
1092  * prints the error message of a node to a file F as info2.
1093  */
1094 static void print_node_error(FILE *F, const char *err_msg)
1095 {
1096         if (! err_msg)
1097                 return;
1098
1099         fprintf(F, " info2: \"%s\"", err_msg);
1100 }
1101
1102 /**
1103  * prints debug messages of a node to file F as info3.
1104  */
1105 static void print_dbg_info(FILE *F, dbg_info *dbg)
1106 {
1107         char buf[1024];
1108
1109         ir_dbg_info_snprint(buf, sizeof(buf), dbg);
1110         if (buf[0] != 0) {
1111                 fprintf(F, " info3: \"%s\"\n", buf);
1112         }
1113 }
1114
1115 static void print_type_dbg_info(FILE *F, type_dbg_info *dbg)
1116 {
1117         (void) F;
1118         (void) dbg;
1119         /* TODO */
1120 }
1121
1122 /**
1123  * Dump a node
1124  */
1125 static void dump_node(FILE *F, ir_node *n)
1126 {
1127         int bad = 0;
1128         const char *p;
1129
1130         if (get_opt_dump_const_local() && is_constlike_node(n))
1131                 return;
1132
1133         /* dump this node */
1134         fputs("node: {title: \"", F);
1135         PRINT_NODEID(n);
1136         fputs("\"", F);
1137
1138         fputs(" label: \"", F);
1139         bad = ! irn_verify_irg_dump(n, current_ir_graph, &p);
1140         dump_node_label(F, n);
1141         dump_node_ana_vals(F, n);
1142         //dump_node_ana_info(F, n);
1143         fputs("\" ", F);
1144
1145         if (get_op_flags(get_irn_op(n)) & irop_flag_dump_noinput) {
1146                 //fputs(" node_class:23", F);
1147         }
1148
1149         dump_node_info(F, n);
1150         print_node_error(F, p);
1151         print_dbg_info(F, get_irn_dbg_info(n));
1152         dump_node_vcgattr(F, n, NULL, bad);
1153         fputs("}\n", F);
1154         dump_const_node_local(F, n);
1155
1156         if (dump_node_edge_hook)
1157                 dump_node_edge_hook(F, n);
1158 }
1159
1160 /** dump the edge to the block this node belongs to */
1161 static void dump_ir_block_edge(FILE *F, ir_node *n)
1162 {
1163         if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1164         if (!is_Block(n)) {
1165                 ir_node *block = get_nodes_block(n);
1166
1167                 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1168                         dump_const_block_local(F, n);
1169                 } else {
1170                         fprintf(F, "edge: { sourcename: \"");
1171                         PRINT_NODEID(n);
1172                         fprintf(F, "\" targetname: ");
1173                         fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1174
1175                         if (dump_edge_vcgattr_hook) {
1176                                 fprintf(F, " ");
1177                                 if (dump_edge_vcgattr_hook(F, n, -1)) {
1178                                         fprintf(F, "}\n");
1179                                         return;
1180                                 } else {
1181                                         fprintf(F, " "  BLOCK_EDGE_ATTR "}\n");
1182                                         return;
1183                                 }
1184                         }
1185
1186                         fprintf(F, " "   BLOCK_EDGE_ATTR "}\n");
1187                 }
1188         }
1189 }
1190
1191 static void print_data_edge_vcgattr(FILE *F, ir_node *from, int to)
1192 {
1193         /*
1194          * do not use get_nodes_block() here, will fail
1195          * if the irg is not pinned.
1196          */
1197         if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1198                 fprintf(F, INTRA_DATA_EDGE_ATTR);
1199         else
1200                 fprintf(F, INTER_DATA_EDGE_ATTR);
1201 }
1202
1203 static void print_mem_edge_vcgattr(FILE *F, ir_node *from, int to)
1204 {
1205         /*
1206          * do not use get_nodes_block() here, will fail
1207          * if the irg is not pinned.
1208          */
1209         if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1210                 fprintf(F, INTRA_MEM_EDGE_ATTR);
1211         else
1212                 fprintf(F, INTER_MEM_EDGE_ATTR);
1213 }
1214
1215 /** Print the vcg attributes for the edge from node "from" to its "to"th input */
1216 static void print_edge_vcgattr(FILE *F, ir_node *from, int to)
1217 {
1218         assert(from);
1219
1220         if (dump_edge_vcgattr_hook)
1221                 if (dump_edge_vcgattr_hook(F, from, to))
1222                         return;
1223
1224         if ((flags & ir_dump_flag_back_edges) && is_backedge(from, to))
1225                 fprintf(F, BACK_EDGE_ATTR);
1226
1227         switch (get_irn_opcode(from)) {
1228         case iro_Block:
1229                 fprintf(F, CF_EDGE_ATTR);
1230                 break;
1231         case iro_Start:  break;
1232         case iro_End:
1233                 if (to >= 0) {
1234                         if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1235                                 fprintf(F, KEEP_ALIVE_CF_EDGE_ATTR);
1236                         else
1237                                 fprintf(F, KEEP_ALIVE_DF_EDGE_ATTR);
1238                 }
1239                 break;
1240         default:
1241                 if (is_Proj(from)) {
1242                         if (get_irn_mode(from) == mode_M)
1243                                 print_mem_edge_vcgattr(F, from, to);
1244                         else if (get_irn_mode(from) == mode_X)
1245                                 fprintf(F, CF_EDGE_ATTR);
1246                         else
1247                                 print_data_edge_vcgattr(F, from, to);
1248                 }
1249                 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1250                         print_mem_edge_vcgattr(F, from, to);
1251                 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1252                         fprintf(F, CF_EDGE_ATTR);
1253                 else
1254                         print_data_edge_vcgattr(F, from, to);
1255         }
1256 }
1257
1258 /** dump edges to our inputs */
1259 static void dump_ir_data_edges(FILE *F, ir_node *n)
1260 {
1261         int i, num;
1262
1263         if (!(flags & ir_dump_flag_keepalive_edges) && is_End(n)) {
1264                 /* the End node has only keep-alive edges */
1265                 return;
1266         }
1267
1268         /* dump the dependency edges. */
1269         num = get_irn_deps(n);
1270         for (i = 0; i < num; ++i) {
1271                 ir_node *dep = get_irn_dep(n, i);
1272
1273                 if (dep) {
1274                         print_node_edge_kind(F, n);
1275                         fprintf(F, "{sourcename: \"");
1276                         PRINT_NODEID(n);
1277                         fprintf(F, "\" targetname: ");
1278                         if ((get_opt_dump_const_local()) && is_constlike_node(dep)) {
1279                                 PRINT_CONSTID(n, dep);
1280                         } else {
1281                                 fprintf(F, "\"");
1282                                 PRINT_NODEID(dep);
1283                                 fprintf(F, "\"");
1284                         }
1285                         fprintf(F, " label: \"%d\" ", i);
1286                         fprintf(F, " color: darkgreen}\n");
1287                 }
1288         }
1289
1290         num = get_irn_arity(n);
1291         for (i = 0; i < num; i++) {
1292                 ir_node *pred = get_irn_n(n, i);
1293                 assert(pred);
1294
1295                 if ((flags & ir_dump_flag_back_edges) && is_backedge(n, i)) {
1296                         fprintf(F, "backedge: {sourcename: \"");
1297                 } else {
1298                         print_node_edge_kind(F, n);
1299                         fprintf(F, "{sourcename: \"");
1300                 }
1301                 PRINT_NODEID(n);
1302                 fprintf(F, "\" targetname: ");
1303                 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1304                         PRINT_CONSTID(n, pred);
1305                 } else {
1306                         fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1307                 }
1308                 fprintf(F, " label: \"%d\" ", i);
1309                 print_edge_vcgattr(F, n, i);
1310                 fprintf(F, "}\n");
1311         }
1312 }
1313
1314 /**
1315  * Dump the ir_edges
1316  */
1317 static void dump_ir_edges(ir_node *node, void *env)
1318 {
1319         int              i = 0;
1320         FILE            *F = (FILE*)env;
1321         const ir_edge_t *edge;
1322
1323         foreach_out_edge(node, edge) {
1324                 ir_node *succ = get_edge_src_irn(edge);
1325
1326                 print_node_edge_kind(F, succ);
1327                 fprintf(F, "{sourcename: \"");
1328                 PRINT_NODEID(node);
1329                 fprintf(F, "\" targetname: \"");
1330                 PRINT_NODEID(succ);
1331                 fprintf(F, "\"");
1332
1333                 fprintf(F, " label: \"%d\" ", i);
1334                 fprintf(F, OUT_EDGE_ATTR);
1335                 fprintf(F, "}\n");
1336                 ++i;
1337         }
1338 }
1339
1340
1341 /** Dumps a node and its edges but not the block edge  */
1342 static void dump_node_wo_blockedge(ir_node *n, void *env)
1343 {
1344         FILE *F = (FILE*)env;
1345         dump_node(F, n);
1346         dump_ir_data_edges(F, n);
1347 }
1348
1349 /** Dumps a node and its edges. */
1350 static void dump_node_with_edges(ir_node *n, void *env)
1351 {
1352         FILE *F = (FILE*)env;
1353         dump_node_wo_blockedge(n, env);
1354         if (!node_floats(n))
1355                 dump_ir_block_edge(F, n);
1356 }
1357
1358 /** Dumps a const-like node. */
1359 static void dump_const_node(ir_node *n, void *env)
1360 {
1361         if (is_Block(n)) return;
1362         dump_node_wo_blockedge(n, env);
1363 }
1364
1365 /***********************************************************************/
1366 /* the following routines dump the nodes/irgs bracketed to graphs.     */
1367 /***********************************************************************/
1368
1369 /** Dumps a constant expression as entity initializer, array bound ... */
1370 static void dump_const_expression(FILE *F, ir_node *value)
1371 {
1372         ir_graph *rem = current_ir_graph;
1373         ir_dump_flags_t old_flags = ir_get_dump_flags();
1374         ir_remove_dump_flags(ir_dump_flag_consts_local);
1375
1376         current_ir_graph = get_const_code_irg();
1377         irg_walk(value, dump_const_node, NULL, F);
1378         /* Decrease visited flag so that we walk with the same flag for the next
1379            expression.  This guarantees that we don't dump the same node twice,
1380            as for const expressions cse is performed to save memory. */
1381         set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1382
1383         ir_set_dump_flags(old_flags);
1384         current_ir_graph = rem;
1385 }
1386
1387 /** Dump a block as graph containing its nodes.
1388  *
1389  *  Expects to find nodes belonging to the block as list in its
1390  *  link field.
1391  *  Dumps the edges of all nodes including itself. */
1392 static void dump_whole_block(FILE *F, ir_node *block)
1393 {
1394         ir_node *node;
1395         ird_color_t color = ird_color_block_background;
1396
1397         assert(is_Block(block));
1398
1399         fprintf(F, "graph: { title: \"");
1400         PRINT_NODEID(block);
1401         fprintf(F, "\"  label: \"");
1402         dump_node_label(F, block);
1403
1404         /* colorize blocks */
1405         if (! get_Block_matured(block))
1406                 color = ird_color_block_background;
1407
1408         fprintf(F, "\" status:clustered ");
1409         print_vcg_color(F, color);
1410         fprintf(F, "\n");
1411
1412         /* yComp can show attributes for blocks, XVCG parses but ignores them */
1413         dump_node_info(F, block);
1414         print_dbg_info(F, get_irn_dbg_info(block));
1415
1416         /* dump the blocks edges */
1417         dump_ir_data_edges(F, block);
1418
1419         if (dump_block_edge_hook)
1420                 dump_block_edge_hook(F, block);
1421
1422         /* dump the nodes that go into the block */
1423         for (node = (ir_node*)ird_get_irn_link(block); node; node = (ir_node*)ird_get_irn_link(node)) {
1424                 dump_node(F, node);
1425                 dump_ir_data_edges(F, node);
1426         }
1427
1428         /* Close the vcg information for the block */
1429         fprintf(F, "}\n");
1430         dump_const_node_local(F, block);
1431         fprintf(F, "\n");
1432 }
1433
1434 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1435  *  The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1436 static void dump_block_graph(FILE *F, ir_graph *irg)
1437 {
1438         size_t i, n;
1439         ir_graph *rem = current_ir_graph;
1440         ir_node **arr = (ir_node**)ird_get_irg_link(irg);
1441         current_ir_graph = irg;
1442
1443         for (i = 0, n = ARR_LEN(arr); i < n; ++i) {
1444                 ir_node *node = arr[i];
1445                 if (is_Block(node)) {
1446                 /* Dumps the block and all the nodes in the block, which are to
1447                         be found in Block->link. */
1448                         dump_whole_block(F, node);
1449                 } else {
1450                         /* Nodes that are not in a Block. */
1451                         dump_node(F, node);
1452                         if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1453                                 dump_const_block_local(F, node);
1454                         }
1455                         dump_ir_data_edges(F, node);
1456                 }
1457                 if ((flags & ir_dump_flag_iredges) && edges_activated(irg))
1458                         dump_ir_edges(node, F);
1459         }
1460
1461         if ((flags & ir_dump_flag_loops)
1462              && is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO))
1463                 dump_loop_nodes_into_graph(F, irg);
1464
1465         current_ir_graph = rem;
1466 }
1467
1468 /**
1469  * Dump the info for an irg.
1470  * Parsed by XVCG but not shown. use yComp.
1471  */
1472 static void dump_graph_info(FILE *F, ir_graph *irg)
1473 {
1474         fprintf(F, "info1: \"");
1475         dump_entity_to_file(F, get_irg_entity(irg));
1476         fprintf(F, "\n");
1477
1478         /* dump graph state */
1479         fprintf(F, "state:");
1480         if (is_irg_state(irg, IR_GRAPH_STATE_ARCH_DEP))
1481                 fprintf(F, " arch_dep");
1482         if (is_irg_state(irg, IR_GRAPH_STATE_MODEB_LOWERED))
1483                 fprintf(F, " modeb_lowered");
1484         if (is_irg_state(irg, IR_GRAPH_STATE_NORMALISATION2))
1485                 fprintf(F, " normalisation2");
1486         if (is_irg_state(irg, IR_GRAPH_STATE_IMPLICIT_BITFIELD_MASKING))
1487                 fprintf(F, " implicit_bitfield_masking");
1488         if (is_irg_state(irg, IR_GRAPH_STATE_OPTIMIZE_UNREACHABLE_CODE))
1489                 fprintf(F, " optimize_unreachable_code");
1490         if (is_irg_state(irg, IR_GRAPH_STATE_NO_CRITICAL_EDGES))
1491                 fprintf(F, " no_critical_edges");
1492         if (is_irg_state(irg, IR_GRAPH_STATE_NO_BADS))
1493                 fprintf(F, " no_bads");
1494         if (is_irg_state(irg, IR_GRAPH_STATE_NO_UNREACHABLE_CODE))
1495                 fprintf(F, " no_unreachable_code");
1496         if (is_irg_state(irg, IR_GRAPH_STATE_ONE_RETURN))
1497                 fprintf(F, " one_return");
1498         if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_DOMINANCE))
1499                 fprintf(F, " consistent_dominance");
1500         if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE))
1501                 fprintf(F, " consistent_postdominance");
1502         if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUT_EDGES))
1503                 fprintf(F, " consistent_out_edges");
1504         if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS))
1505                 fprintf(F, " consistent_outs");
1506         if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO))
1507                 fprintf(F, " consistent_loopinfo");
1508         if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_ENTITY_USAGE))
1509                 fprintf(F, " consistent_entity_usage");
1510         if (is_irg_state(irg, IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS))
1511                 fprintf(F, " valid_exended_blocks");
1512         fprintf(F, "\"\n");
1513 }
1514
1515 /** Dumps an irg as a graph clustered by block nodes.
1516  *  If interprocedural view edges can point to nodes out of this graph.
1517  */
1518 static void dump_graph_from_list(FILE *F, ir_graph *irg)
1519 {
1520         ir_entity *ent = get_irg_entity(irg);
1521
1522         fprintf(F, "graph: { title: \"");
1523         PRINT_IRGID(irg);
1524         fprintf(F, "\" label: \"%s\" status:clustered color:%s \n",
1525           get_ent_dump_name(ent), color_names[ird_color_prog_background]);
1526
1527         dump_graph_info(F, irg);
1528         print_dbg_info(F, get_entity_dbg_info(ent));
1529
1530         dump_block_graph(F, irg);
1531
1532         /* Close the vcg information for the irg */
1533         fprintf(F, "}\n\n");
1534 }
1535
1536 /*******************************************************************/
1537 /* Basic type and entity nodes and edges.                          */
1538 /*******************************************************************/
1539
1540 /** dumps the edges between nodes and their type or entity attributes. */
1541 static void dump_node2type_edges(ir_node *n, void *env)
1542 {
1543         FILE *F = (FILE*)env;
1544         assert(n);
1545
1546         switch (get_irn_opcode(n)) {
1547         case iro_Const :
1548                 /* @@@ some consts have an entity */
1549                 break;
1550         case iro_SymConst:
1551                 if (SYMCONST_HAS_TYPE(get_SymConst_kind(n)))
1552                         print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1553                 break;
1554         case iro_Sel:
1555                 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1556                 break;
1557         case iro_Call:
1558                 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1559                 break;
1560         case iro_Alloc:
1561                 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1562                 break;
1563         case iro_Free:
1564                 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1565                 break;
1566         case iro_Cast:
1567                 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1568                 break;
1569         default:
1570                 break;
1571         }
1572 }
1573
1574 #if 0
1575 static int print_type_info(FILE *F, ir_type *tp)
1576 {
1577         int bad = 0;
1578
1579         if (get_type_state(tp) == layout_undefined) {
1580                 fprintf(F, "state: layout_undefined\n");
1581         } else {
1582                 fprintf(F, "state: layout_fixed,\n");
1583         }
1584         if (get_type_mode(tp))
1585                 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1586         fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1587
1588         return bad;
1589 }
1590
1591 static void print_typespecific_info(FILE *F, ir_type *tp)
1592 {
1593         switch (get_type_tpop_code(tp)) {
1594         case tpo_class:
1595                 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1596                 break;
1597         case tpo_struct:
1598                 break;
1599         case tpo_method:
1600                 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1601                 fprintf(F, "params: %d\n", get_method_n_params(tp));
1602                 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1603                 break;
1604         case tpo_union:
1605                 break;
1606         case tpo_array:
1607                 break;
1608         case tpo_enumeration:
1609                 break;
1610         case tpo_pointer:
1611                 break;
1612         case tpo_primitive:
1613                 break;
1614         default:
1615                 break;
1616         }
1617 }
1618 #endif
1619
1620 static void print_typespecific_vcgattr(FILE *F, ir_type *tp)
1621 {
1622         switch (get_type_tpop_code(tp)) {
1623         case tpo_class:
1624                 fprintf(F, " " TYPE_CLASS_NODE_ATTR);
1625                 break;
1626         case tpo_struct:
1627                 fprintf(F, " " TYPE_METH_NODE_ATTR);
1628                 break;
1629         case tpo_method:
1630                 break;
1631         case tpo_union:
1632                 break;
1633         case tpo_array:
1634                 break;
1635         case tpo_enumeration:
1636                 break;
1637         case tpo_pointer:
1638                 break;
1639         case tpo_primitive:
1640                 break;
1641         default:
1642                 break;
1643         }
1644 }
1645
1646 void dump_type_node(FILE *F, ir_type *tp)
1647 {
1648         fprintf(F, "node: {title: ");
1649         PRINT_TYPEID(tp);
1650         fprintf(F, " label: \"");
1651         if (tp->dbi != NULL) {
1652                 char buf[1024];
1653                 ir_print_type(buf, sizeof(buf), tp);
1654                 fprintf(F, "%s '%s'", get_type_tpop_name(tp), buf);
1655         } else {
1656                 ir_fprintf(F, "%+F", tp);
1657         }
1658         fputs("\" info1: \"", F);
1659         dump_type_to_file(F, tp);
1660         fprintf(F, "\"\n");
1661         print_type_dbg_info(F, get_type_dbg_info(tp));
1662         print_typespecific_vcgattr(F, tp);
1663         fprintf(F, "}\n");
1664 }
1665
1666 static void dump_entity_node(FILE *F, ir_entity *ent)
1667 {
1668         fprintf(F, "node: {title: \"");
1669         PRINT_ENTID(ent); fprintf(F, "\"");
1670         fprintf(F, " label: ");
1671         fprintf(F, "\"%s\" ", get_ent_dump_name(ent));
1672
1673         print_vcg_color(F, ird_color_entity);
1674         fprintf(F, "\n info1: \"");
1675
1676         dump_entity_to_file(F, ent);
1677
1678         fprintf(F, "\"\n");
1679         print_dbg_info(F, get_entity_dbg_info(ent));
1680         fprintf(F, "}\n");
1681 }
1682
1683 static void dump_enum_item(FILE *F, ir_type *tp, size_t pos)
1684 {
1685         char buf[1024];
1686         ir_enum_const *ec = get_enumeration_const(tp, pos);
1687         ident         *id = get_enumeration_const_nameid(ec);
1688         ir_tarval     *tv = get_enumeration_value(ec);
1689
1690         if (tv)
1691                 tarval_snprintf(buf, sizeof(buf), tv);
1692         else
1693                 strncpy(buf, "<not set>", sizeof(buf));
1694         fprintf(F, "node: {title: \"");
1695         PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1696         fprintf(F, " label: ");
1697         fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1698         fprintf(F, "\n info1: \"value: %s\"}\n", buf);
1699 }
1700
1701 /**
1702  * Dumps a new style initializer.
1703  */
1704 static void dump_entity_initializer(FILE *F, const ir_entity *ent)
1705 {
1706         /* TODO */
1707         (void) F;
1708         (void) ent;
1709 }
1710
1711 /**
1712  * type-walker: Dumps a type or entity and its edges.
1713  */
1714 static void dump_type_info(type_or_ent tore, void *env)
1715 {
1716         FILE *F = (FILE*)env;
1717         size_t i = 0;  /* to shutup gcc */
1718
1719         /* dump this type or entity */
1720
1721         switch (get_kind(tore.ent)) {
1722         case k_entity: {
1723                 ir_entity *ent = tore.ent;
1724                 ir_node *value;
1725                 /* The node */
1726                 dump_entity_node(F, ent);
1727                 /* The Edges */
1728                 /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
1729                 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1730                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1731                 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1732                 if (is_Class_type(get_entity_owner(ent))) {
1733                         for (i = get_entity_n_overwrites(ent); i > 0;)
1734                                 print_ent_ent_edge(F, ent, get_entity_overwrites(ent, --i), 0, ird_color_none, ENT_OVERWRITES_EDGE_ATTR);
1735                 }
1736                 /* attached subgraphs */
1737                 if (! (flags & ir_dump_flag_no_entity_values)) {
1738                         if (ent->initializer != NULL) {
1739                                 /* new style initializers */
1740                                 dump_entity_initializer(F, ent);
1741                         } else if (entity_has_compound_ent_values(ent)) {
1742                                 /* old style compound entity values */
1743                                 for (i = get_compound_ent_n_values(ent); i > 0;) {
1744                                         value = get_compound_ent_value(ent, --i);
1745                                         if (value) {
1746                                                 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1747                                                 dump_const_expression(F, value);
1748                                                 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ird_color_none, ENT_CORR_EDGE_ATTR, i);
1749                                                 /*
1750                                                 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1751                                                 ENT_CORR_EDGE_ATTR  "}\n", GET_ENTID(ent),
1752                                                 get_compound_ent_value_member(ent, i), i);
1753                                                 */
1754                                         }
1755                                 }
1756                         }
1757                 }
1758                 break;
1759         }
1760         case k_type: {
1761                 ir_type *tp = tore.typ;
1762                 dump_type_node(F, tp);
1763                 /* and now the edges */
1764                 switch (get_type_tpop_code(tp)) {
1765                 case tpo_class:
1766                         for (i = get_class_n_supertypes(tp); i > 0;) {
1767                                 --i;
1768                                 print_type_type_edge(F, tp, get_class_supertype(tp, i), TYPE_SUPER_EDGE_ATTR);
1769                         }
1770                         for (i = get_class_n_members(tp); i > 0;) {
1771                                 --i;
1772                                 print_type_ent_edge(F, tp, get_class_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
1773                         }
1774                         break;
1775                 case tpo_struct:
1776                         for (i = get_struct_n_members(tp); i > 0;) {
1777                                 --i;
1778                                 print_type_ent_edge(F, tp, get_struct_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
1779                         }
1780                         break;
1781                 case tpo_method:
1782                         for (i = get_method_n_params(tp); i > 0;) {
1783                                 --i;
1784                                 print_type_type_edge(F, tp, get_method_param_type(tp, i), METH_PAR_EDGE_ATTR,i);
1785                         }
1786                         for (i = get_method_n_ress(tp); i > 0;) {
1787                                  --i;
1788                                 print_type_type_edge(F, tp, get_method_res_type(tp, i), METH_RES_EDGE_ATTR,i);
1789                         }
1790                         break;
1791                 case tpo_union:
1792                         for (i = get_union_n_members(tp); i > 0;) {
1793                                  --i;
1794                                 print_type_ent_edge(F, tp, get_union_member(tp, i), UNION_EDGE_ATTR);
1795                         }
1796                         break;
1797                 case tpo_array:
1798                         print_type_type_edge(F, tp, get_array_element_type(tp), ARR_ELT_TYPE_EDGE_ATTR);
1799                         print_type_ent_edge(F, tp, get_array_element_entity(tp), ARR_ENT_EDGE_ATTR);
1800                         for (i = get_array_n_dimensions(tp); i > 0;) {
1801                                 ir_node *upper, *lower;
1802
1803                                  --i;
1804                                 upper = get_array_upper_bound(tp, i);
1805                                 lower = get_array_lower_bound(tp, i);
1806                                 print_node_type_edge(F, upper, tp, "label: \"upper %zu\"", get_array_order(tp, i));
1807                                 print_node_type_edge(F, lower, tp, "label: \"lower %zu\"", get_array_order(tp, i));
1808                                 dump_const_expression(F, upper);
1809                                 dump_const_expression(F, lower);
1810                         }
1811                         break;
1812                 case tpo_enumeration:
1813                         for (i = get_enumeration_n_enums(tp); i > 0;) {
1814                                  --i;
1815                                 dump_enum_item(F, tp, i);
1816                                 print_enum_item_edge(F, tp, i, "label: \"item %zu\"", i);
1817                         }
1818                         break;
1819                 case tpo_pointer:
1820                         print_type_type_edge(F, tp, get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1821                         break;
1822                 case tpo_primitive:
1823                         break;
1824                 default:
1825                         break;
1826                 }
1827                 break; /* case k_type */
1828         }
1829         default:
1830                 printf(" *** irdump,  dump_type_info(l.%i), faulty type.\n", __LINE__);
1831         }
1832 }
1833
1834 /** For dumping class hierarchies.
1835  * Dumps a class type node and a superclass edge.
1836  */
1837 static void dump_class_hierarchy_node(type_or_ent tore, void *ctx)
1838 {
1839         FILE *F = (FILE*)ctx;
1840         size_t i = 0;  /* to shutup gcc */
1841
1842         /* dump this type or entity */
1843         switch (get_kind(tore.ent)) {
1844         case k_entity: {
1845                 ir_entity *ent = tore.ent;
1846                 if (get_entity_owner(ent) == get_glob_type()) break;
1847                 if (!is_Method_type(get_entity_type(ent)))
1848                         break;  /* GL */
1849                 if (flags & ir_dump_flag_entities_in_hierarchy
1850                                 && is_Class_type(get_entity_owner(ent))) {
1851                         /* The node */
1852                         dump_entity_node(F, ent);
1853                         /* The edges */
1854                         print_type_ent_edge(F, get_entity_owner(ent), ent, TYPE_MEMBER_EDGE_ATTR);
1855                         for (i = get_entity_n_overwrites(ent); i > 0;) {
1856                                  --i;
1857                                 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ird_color_none, ENT_OVERWRITES_EDGE_ATTR);
1858                         }
1859                 }
1860                 break;
1861         }
1862         case k_type: {
1863                 ir_type *tp = tore.typ;
1864                 if (tp == get_glob_type())
1865                         break;
1866                 switch (get_type_tpop_code(tp)) {
1867                 case tpo_class:
1868                         dump_type_node(F, tp);
1869                         /* and now the edges */
1870                         for (i = get_class_n_supertypes(tp); i > 0;) {
1871                                  --i;
1872                                 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1873                         }
1874                         break;
1875                 default: break;
1876                 }
1877                 break; /* case k_type */
1878         }
1879         default:
1880                 printf(" *** irdump,  dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1881         }
1882 }
1883
1884 /*******************************************************************/
1885 /* dump analysis information that is expressed in graph terms.     */
1886 /*******************************************************************/
1887
1888 /* dump out edges */
1889 static void dump_out_edge(ir_node *n, void *env)
1890 {
1891         FILE *F = (FILE*)env;
1892         int i;
1893         for (i = get_irn_n_outs(n) - 1; i >= 0; --i) {
1894                 ir_node *succ = get_irn_out(n, i);
1895                 assert(succ);
1896                 print_node_edge_kind(F, succ);
1897                 fprintf(F, "{sourcename: \"");
1898                 PRINT_NODEID(n);
1899                 fprintf(F, "\" targetname: \"");
1900                 PRINT_NODEID(succ);
1901                 fprintf(F, "\" color: red linestyle: dashed");
1902                 fprintf(F, "}\n");
1903         }
1904 }
1905
1906 static void dump_loop_label(FILE *F, ir_loop *loop)
1907 {
1908         fprintf(F, "loop %u, %lu sons, %lu nodes",
1909                 get_loop_depth(loop), (unsigned long) get_loop_n_sons(loop),
1910                 (unsigned long) get_loop_n_nodes(loop));
1911 }
1912
1913 static void dump_loop_info(FILE *F, ir_loop *loop)
1914 {
1915         fprintf(F, " info1: \"");
1916         fprintf(F, " loop nr: %ld", get_loop_loop_nr(loop));
1917 #ifdef DEBUG_libfirm   /* GL @@@ debug analyses */
1918         fprintf(F, "\n The loop was analyzed %ld times.", (long int) PTR_TO_INT(get_loop_link(loop)));
1919 #endif
1920         fprintf(F, "\"");
1921 }
1922
1923 static void dump_loop_node(FILE *F, ir_loop *loop)
1924 {
1925         fprintf(F, "node: {title: \"");
1926         PRINT_LOOPID(loop);
1927         fprintf(F, "\" label: \"");
1928         dump_loop_label(F, loop);
1929         fprintf(F, "\" ");
1930         dump_loop_info(F, loop);
1931         fprintf(F, "}\n");
1932 }
1933
1934 static void dump_loop_node_edge(FILE *F, ir_loop *loop, size_t i)
1935 {
1936         assert(loop);
1937         fprintf(F, "edge: {sourcename: \"");
1938         PRINT_LOOPID(loop);
1939         fprintf(F, "\" targetname: \"");
1940         PRINT_NODEID(get_loop_node(loop, i));
1941         fprintf(F, "\" color: green");
1942         fprintf(F, "}\n");
1943 }
1944
1945 static void dump_loop_son_edge(FILE *F, ir_loop *loop, size_t i)
1946 {
1947         assert(loop);
1948         fprintf(F, "edge: {sourcename: \"");
1949         PRINT_LOOPID(loop);
1950         fprintf(F, "\" targetname: \"");
1951         PRINT_LOOPID(get_loop_son(loop, i));
1952         ir_fprintf(F, "\" color: darkgreen label: \"%zu\"}\n",
1953                 get_loop_element_pos(loop, get_loop_son(loop, i)));
1954 }
1955
1956 static void dump_loops(FILE *F, ir_loop *loop)
1957 {
1958         size_t i;
1959         /* dump this loop node */
1960         dump_loop_node(F, loop);
1961
1962         /* dump edges to nodes in loop -- only if it is a real loop */
1963         if (get_loop_depth(loop) != 0) {
1964                 for (i = get_loop_n_nodes(loop); i > 0;) {
1965                         --i;
1966                         dump_loop_node_edge(F, loop, i);
1967                 }
1968         }
1969         for (i = get_loop_n_sons(loop); i > 0;) {
1970                  --i;
1971                 dump_loops(F, get_loop_son(loop, i));
1972                 dump_loop_son_edge(F, loop, i);
1973         }
1974 }
1975
1976 static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg)
1977 {
1978         ir_loop *loop = get_irg_loop(irg);
1979
1980         if (loop != NULL) {
1981                 ir_graph *rem = current_ir_graph;
1982                 current_ir_graph = irg;
1983
1984                 dump_loops(F, loop);
1985
1986                 current_ir_graph = rem;
1987         }
1988 }
1989
1990
1991 /**
1992  * dumps the VCG header
1993  */
1994 void dump_vcg_header(FILE *F, const char *name, const char *layout, const char *orientation)
1995 {
1996         int   i;
1997         const char *label
1998                 = (flags & ir_dump_flag_disable_edge_labels) ? "no" : "yes";
1999
2000         init_colors();
2001
2002         if (! layout)     layout = "Compilergraph";
2003         if (!orientation) orientation = "bottom_to_top";
2004
2005         /* print header */
2006         fprintf(F,
2007                 "graph: { title: \"ir graph of %s\"\n"
2008                 "display_edge_labels: %s\n"
2009                 "layoutalgorithm: mindepth //$ \"%s\"\n"
2010                 "manhattan_edges: yes\n"
2011                 "port_sharing: no\n"
2012                 "orientation: %s\n"
2013                 "classname 1:  \"intrablock Data\"\n"
2014                 "classname 2:  \"Block\"\n"
2015                 "classname 3:  \"Entity type\"\n"
2016                 "classname 4:  \"Entity owner\"\n"
2017                 "classname 5:  \"Method Param\"\n"
2018                 "classname 6:  \"Method Res\"\n"
2019                 "classname 7:  \"Super\"\n"
2020                 "classname 8:  \"Union\"\n"
2021                 "classname 9:  \"Points-to\"\n"
2022                 "classname 10: \"Array Element Type\"\n"
2023                 "classname 11: \"Overwrites\"\n"
2024                 "classname 12: \"Member\"\n"
2025                 "classname 13: \"Control Flow\"\n"
2026                 "classname 14: \"intrablock Memory\"\n"
2027                 "classname 15: \"Dominators\"\n"
2028                 "classname 16: \"interblock Data\"\n"
2029                 "classname 17: \"interblock Memory\"\n"
2030                 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2031                 "classname 19: \"Postdominators\"\n"
2032                 "classname 20: \"Keep Alive\"\n"
2033                 "classname 21: \"Out Edges\"\n"
2034                 "classname 22: \"Macro Block Edges\"\n"
2035                 //"classname 23: \"NoInput Nodes\"\n"
2036                 "infoname 1: \"Attribute\"\n"
2037                 "infoname 2: \"Verification errors\"\n"
2038                 "infoname 3: \"Debug info\"\n",
2039                 name, label, layout, orientation);
2040
2041         for (i = 0; i < ird_color_count; ++i) {
2042                 if (color_rgb[i] != NULL) {
2043                         fprintf(F, "colorentry %s: %s\n", color_names[i], color_rgb[i]);
2044                 }
2045         }
2046         fprintf(F, "\n");
2047 }
2048
2049 /**
2050  * Dumps the vcg file footer
2051  */
2052 void dump_vcg_footer(FILE *F)
2053 {
2054         fprintf(F, "}\n");
2055 }
2056
2057
2058
2059 static void dump_blocks_as_subgraphs(FILE *out, ir_graph *irg)
2060 {
2061         size_t i;
2062
2063         construct_block_lists(irg);
2064
2065         /*
2066          * If we are in the interprocedural view, we dump not
2067          * only the requested irg but also all irgs that can be reached
2068          * from irg.
2069          */
2070         for (i = get_irp_n_irgs(); i > 0;) {
2071                 ir_graph *other_irg = get_irp_irg(--i);
2072                 ir_node **arr = (ir_node**)ird_get_irg_link(other_irg);
2073                 if (arr == NULL)
2074                         continue;
2075
2076                 dump_graph_from_list(out, other_irg);
2077                 DEL_ARR_F(arr);
2078         }
2079 }
2080
2081 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
2082  *  The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
2083 static void dump_extblock_graph(FILE *F, ir_graph *irg)
2084 {
2085         size_t i, arr_len;
2086         ir_graph *rem = current_ir_graph;
2087         ir_extblk **arr = (ir_extblk**)ird_get_irg_link(irg);
2088         current_ir_graph = irg;
2089
2090         for (i = 0, arr_len = ARR_LEN(arr); i < arr_len; ++i) {
2091                 ir_extblk *extbb = arr[i];
2092                 ir_node *leader = get_extbb_leader(extbb);
2093                 size_t j, n_blks;
2094
2095                 fprintf(F, "graph: { title: \"");
2096                 PRINT_EXTBBID(leader);
2097                 fprintf(F, "\"  label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
2098                         get_irn_node_nr(leader));
2099
2100                 for (j = 0, n_blks = ARR_LEN(extbb->blks); j < n_blks; ++j) {
2101                         ir_node *node = extbb->blks[j];
2102                         if (is_Block(node)) {
2103                         /* Dumps the block and all the nodes in the block, which are to
2104                                 be found in Block->link. */
2105                                 dump_whole_block(F, node);
2106                         } else {
2107                                 /* Nodes that are not in a Block. */
2108                                 dump_node(F, node);
2109                                 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
2110                                         dump_const_block_local(F, node);
2111                                 }
2112                                 dump_ir_data_edges(F, node);
2113                         }
2114                 }
2115                 fprintf(F, "}\n");
2116         }
2117
2118         if ((flags & ir_dump_flag_loops)
2119                         && (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO)))
2120                 dump_loop_nodes_into_graph(F, irg);
2121
2122         current_ir_graph = rem;
2123         free_extbb(irg);
2124 }
2125
2126 static void dump_blocks_extbb_grouped(FILE *F, ir_graph *irg)
2127 {
2128         size_t    i;
2129         ir_entity *ent = get_irg_entity(irg);
2130
2131         if (!is_irg_state(irg, IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS))
2132                 compute_extbb(irg);
2133
2134         construct_extblock_lists(irg);
2135
2136         fprintf(F, "graph: { title: \"");
2137         PRINT_IRGID(irg);
2138         fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2139                 get_ent_dump_name(ent));
2140
2141         dump_graph_info(F, irg);
2142         print_dbg_info(F, get_entity_dbg_info(ent));
2143
2144         for (i = get_irp_n_irgs(); i > 0;) {
2145                 ir_graph   *other_irg = get_irp_irg(--i);
2146                 list_tuple *lists     = (list_tuple*)ird_get_irg_link(other_irg);
2147
2148                 if (lists) {
2149                         /* dump the extended blocks first */
2150                         if (ARR_LEN(lists->extbb_list)) {
2151                                 ird_set_irg_link(other_irg, lists->extbb_list);
2152                                 dump_extblock_graph(F, other_irg);
2153                         }
2154
2155                         /* we may have blocks without extended blocks, bad for instance */
2156                         if (ARR_LEN(lists->blk_list)) {
2157                                 ird_set_irg_link(other_irg, lists->blk_list);
2158                                 dump_block_graph(F, other_irg);
2159                         }
2160
2161                         DEL_ARR_F(lists->extbb_list);
2162                         DEL_ARR_F(lists->blk_list);
2163                         xfree(lists);
2164                 }
2165         }
2166
2167         /* Close the vcg information for the irg */
2168         fprintf(F, "}\n\n");
2169
2170         free_extbb(irg);
2171 }
2172
2173 void dump_ir_graph_file(FILE *out, ir_graph *irg)
2174 {
2175         dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2176
2177         /* dump nodes */
2178         if (flags & ir_dump_flag_blocks_as_subgraphs) {
2179                 if (flags & ir_dump_flag_group_extbb) {
2180                         dump_blocks_extbb_grouped(out, irg);
2181                 } else {
2182                         dump_blocks_as_subgraphs(out, irg);
2183                 }
2184         } else {
2185                 /* dump_node_with_edges must be called in post visiting predecessors */
2186                 ird_walk_graph(irg, NULL, dump_node_with_edges, out);
2187         }
2188
2189         /* dump type info */
2190         if (flags & ir_dump_flag_with_typegraph) {
2191                 ir_graph *rem = current_ir_graph;
2192                 current_ir_graph = irg;
2193
2194                 type_walk_irg(irg, dump_type_info, NULL, out);
2195                 inc_irg_visited(get_const_code_irg());
2196                 /* dump edges from graph to type info */
2197                 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, out);
2198
2199                 current_ir_graph = rem;
2200         }
2201
2202         /* dump iredges out edges */
2203         if ((flags & ir_dump_flag_iredges) && edges_activated(current_ir_graph)) {
2204                 irg_walk_edges(get_irg_start_block(irg), dump_ir_edges, NULL, out);
2205         }
2206
2207         /* dump the out edges in a separate walk */
2208         if ((flags & ir_dump_flag_out_edges)
2209                         && (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS))) {
2210                 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, out);
2211         }
2212
2213         dump_vcg_footer(out);
2214 }
2215
2216 static void dump_block_to_cfg(ir_node *block, void *env)
2217 {
2218         FILE *F = (FILE*)env;
2219         int i;
2220
2221         if (is_Bad(block) && get_irn_mode(block) == mode_X) {
2222                 dump_node(F, block);
2223         }
2224
2225         if (is_Block(block)) {
2226                 /* This is a block. Dump a node for the block. */
2227                 fprintf(F, "node: {title: \""); PRINT_NODEID(block);
2228                 fprintf(F, "\" label: \"");
2229                 if (block == get_irg_start_block(get_irn_irg(block)))
2230                         fprintf(F, "Start ");
2231                 if (block == get_irg_end_block(get_irn_irg(block)))
2232                         fprintf(F, "End ");
2233
2234                 fprintf(F, "%s ", get_op_name(get_irn_op(block)));
2235                 PRINT_NODEID(block);
2236                 fprintf(F, "\" ");
2237                 fprintf(F, "info1:\"");
2238
2239                 /* the generic version. */
2240                 dump_irnode_to_file(F, block);
2241
2242                 fprintf(F, "\"");  /* closing quote of info */
2243
2244                 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2245                         (block == get_irg_end_block(get_irn_irg(block)))     )
2246                         fprintf(F, " color:blue ");
2247
2248                 fprintf(F, "}\n");
2249
2250                 /* Dump the edges */
2251                 for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
2252                         ir_node *pred = get_Block_cfgpred(block, i);
2253                         if (!is_Bad(pred))
2254                                 pred = get_nodes_block(pred);
2255                         fprintf(F, "edge: { sourcename: \"");
2256                         PRINT_NODEID(block);
2257                         fprintf(F, "\" targetname: \"");
2258                         PRINT_NODEID(pred);
2259                         fprintf(F, "\"}\n");
2260                 }
2261
2262                 /* Dump dominator/postdominator edge */
2263                 if (ir_get_dump_flags() & ir_dump_flag_dominance) {
2264                         if (is_irg_state(get_irn_irg(block), IR_GRAPH_STATE_CONSISTENT_DOMINANCE) && get_Block_idom(block)) {
2265                                 ir_node *pred = get_Block_idom(block);
2266                                 fprintf(F, "edge: { sourcename: \"");
2267                                 PRINT_NODEID(block);
2268                                 fprintf(F, "\" targetname: \"");
2269                                 PRINT_NODEID(pred);
2270                                 fprintf(F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2271                         }
2272                         if (is_irg_state(get_irn_irg(block), IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE) && get_Block_ipostdom(block)) {
2273                                 ir_node *pred = get_Block_ipostdom(block);
2274                                 fprintf(F, "edge: { sourcename: \"");
2275                                 PRINT_NODEID(block);
2276                                 fprintf(F, "\" targetname: \"");
2277                                 PRINT_NODEID(pred);
2278                                 fprintf(F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2279                         }
2280                 }
2281         }
2282 }
2283
2284 void dump_cfg(FILE *F, ir_graph *irg)
2285 {
2286         dump_vcg_header(F, get_irg_dump_name(irg), NULL, NULL);
2287
2288         /* walk over the blocks in the graph */
2289         irg_walk_graph(irg, dump_block_to_cfg, NULL, F);
2290
2291         dump_vcg_footer(F);
2292 }
2293
2294 void dump_callgraph(FILE *F)
2295 {
2296         size_t          i;
2297         ir_dump_flags_t old_flags = ir_get_dump_flags();
2298
2299         ir_remove_dump_flags(ir_dump_flag_disable_edge_labels);
2300         dump_vcg_header(F, "Callgraph", "Hierarchic", NULL);
2301
2302         for (i = get_irp_n_irgs(); i > 0;) {
2303                 ir_graph *irg = get_irp_irg(--i);
2304                 ir_entity *ent = get_irg_entity(irg);
2305                 size_t j, n_callees = get_irg_n_callees(irg);
2306
2307                 dump_entity_node(F, ent);
2308                 for (j = 0; j < n_callees; ++j) {
2309                         ir_entity  *c    = get_irg_entity(get_irg_callee(irg, j));
2310                         int         be   = is_irg_callee_backedge(irg, j);
2311                         const char *attr = be
2312                                 ? "label:\"recursion %zu\""
2313                                 : "label:\"calls %zu\"";
2314                         print_ent_ent_edge(F, ent, c, be, ird_color_entity, attr,
2315                                            get_irg_callee_loop_depth(irg, j));
2316                 }
2317         }
2318
2319         ir_set_dump_flags(old_flags);
2320         dump_vcg_footer(F);
2321 }
2322
2323 void dump_typegraph(FILE *out)
2324 {
2325         dump_vcg_header(out, "All_types", "Hierarchic", NULL);
2326         type_walk(dump_type_info, NULL, out);
2327         dump_vcg_footer(out);
2328 }
2329
2330 void dump_class_hierarchy(FILE *out)
2331 {
2332         dump_vcg_header(out, "class_hierarchy", "Hierarchic", NULL);
2333         type_walk(dump_class_hierarchy_node, NULL, out);
2334         dump_vcg_footer(out);
2335 }
2336
2337 static void dump_loops_standalone(FILE *F, ir_loop *loop)
2338 {
2339         size_t i;
2340         bool   loop_node_started = false;
2341         size_t first      = 0;
2342         size_t son_number = 0;
2343         loop_element le;
2344         ir_loop *son = NULL;
2345
2346         /* Dump a new loop node. */
2347         dump_loop_node(F, loop);
2348
2349         /* Dump the loop elements. */
2350         for (i = 0; i < get_loop_n_elements(loop); i++) {
2351                 le = get_loop_element(loop, i);
2352                 son = le.son;
2353                 if (get_kind(son) == k_ir_loop) {
2354
2355                         /* We are a loop son -> Recurse */
2356
2357                         if (loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2358                                 fprintf(F, "\" }\n");
2359                                 fprintf(F, "edge: {sourcename: \"");
2360                                 PRINT_LOOPID(loop);
2361                                 fprintf(F, "\" targetname: \"");
2362                                 PRINT_LOOPID(loop);
2363                                 fprintf(F, "-%lu-nodes\" label:\"%lu...%lu\"}\n",
2364                                                 (unsigned long) first,
2365                                                 (unsigned long) first,
2366                                         (unsigned long) i-1);
2367                                 loop_node_started = false;
2368                         }
2369                         dump_loop_son_edge(F, loop, son_number++);
2370                         dump_loops_standalone(F, son);
2371                 } else if (get_kind(son) == k_ir_node) {
2372                         /* We are a loop node -> Collect firm nodes */
2373
2374                         ir_node *n = le.node;
2375                         if (!loop_node_started) {
2376                                 /* Start a new node which contains all firm nodes of the current loop */
2377                                 fprintf(F, "node: { title: \"");
2378                                 PRINT_LOOPID(loop);
2379                                 fprintf(F, "-%lu-nodes\" color: lightyellow label: \"",
2380                                         (unsigned long)i);
2381                                 loop_node_started = true;
2382                                 first = i;
2383                         } else
2384                                 fprintf(F, "\n");
2385
2386                         dump_node_label(F, n);
2387                         /* Causes indeterministic output: if (is_Block(n)) fprintf(F, "\t ->%d", (int)get_irn_link(n)); */
2388                         if (has_backedges(n)) fprintf(F, "\t loop head!");
2389                 } else { /* for callgraph loop tree */
2390                         ir_graph *n;
2391                         assert(get_kind(son) == k_ir_graph);
2392
2393                         /* We are a loop node -> Collect firm graphs */
2394                         n = le.irg;
2395                         if (!loop_node_started) {
2396                                 /* Start a new node which contains all firm nodes of the current loop */
2397                                 fprintf(F, "node: { title: \"");
2398                                 PRINT_LOOPID(loop);
2399                                 fprintf(F, "-%lu-nodes\" color: lightyellow label: \"",
2400                                         (unsigned long)i);
2401                                 loop_node_started = true;
2402                                 first = i;
2403                         } else
2404                                 fprintf(F, "\n");
2405                         fprintf(F, " %s", get_irg_dump_name(n));
2406                         /* fprintf(F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2407                 }
2408         }
2409
2410         if (loop_node_started) {
2411                 fprintf(F, "\" }\n");
2412                 fprintf(F, "edge: {sourcename: \"");
2413                 PRINT_LOOPID(loop);
2414                 fprintf(F, "\" targetname: \"");
2415                 PRINT_LOOPID(loop);
2416                 fprintf(F, "-%lu-nodes\" label:\"%lu...%lu\"}\n",
2417                         (unsigned long) first,
2418                         (unsigned long) first,
2419                         (unsigned long) i-1);
2420                 loop_node_started = false;
2421         }
2422 }
2423
2424 void dump_loop_tree(FILE *out, ir_graph *irg)
2425 {
2426         ir_graph       *rem       = current_ir_graph;
2427         ir_dump_flags_t old_flags = ir_get_dump_flags();
2428
2429         current_ir_graph = irg;
2430         ir_remove_dump_flags(ir_dump_flag_disable_edge_labels);
2431
2432         dump_vcg_header(out, get_irg_dump_name(irg), "Tree", "top_to_bottom");
2433
2434         if (get_irg_loop(irg))
2435                 dump_loops_standalone(out, get_irg_loop(irg));
2436
2437         dump_vcg_footer(out);
2438
2439         ir_set_dump_flags(old_flags);
2440         current_ir_graph = rem;
2441 }
2442
2443 void dump_callgraph_loop_tree(FILE *out)
2444 {
2445         dump_vcg_header(out, "callgraph looptree", "Tree", "top_to_bottom");
2446         dump_loops_standalone(out, irp->outermost_cg_loop);
2447         dump_vcg_footer(out);
2448 }
2449
2450 static void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes)
2451 {
2452         size_t i;
2453         int    son_number = 0;
2454         int    node_number = 0;
2455
2456         if (flags & ir_dump_flag_loops)
2457                 dump_loop_node(F, loop);
2458
2459         for (i = 0; i < get_loop_n_elements(loop); i++) {
2460                 loop_element le = get_loop_element(loop, i);
2461                 if (*(le.kind) == k_ir_loop) {
2462                         if (flags & ir_dump_flag_loops)
2463                                 dump_loop_son_edge(F, loop, son_number++);
2464                         /* Recur */
2465                         collect_nodeloop(F, le.son, loopnodes);
2466                 } else {
2467                         if (flags & ir_dump_flag_loops)
2468                                 dump_loop_node_edge(F, loop, node_number++);
2469                         eset_insert(loopnodes, le.node);
2470                 }
2471         }
2472 }
2473
2474 static void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes,
2475                                             eset *extnodes)
2476 {
2477         size_t i;
2478         int j, start;
2479
2480         for (i = 0; i < get_loop_n_elements(loop); i++) {
2481                 loop_element le = get_loop_element(loop, i);
2482                 if (*(le.kind) == k_ir_loop) {
2483                         /* Recur */
2484                         collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2485                 } else {
2486                         if (is_Block(le.node)) start = 0; else start = -1;
2487                         for (j = start; j < get_irn_arity(le.node); j++) {
2488                                 ir_node *pred = get_irn_n(le.node, j);
2489                                 if (!eset_contains(loopnodes, pred)) {
2490                                         eset_insert(extnodes, pred);
2491                                         if (!is_Block(pred)) {
2492                                                 pred = get_nodes_block(pred);
2493                                                 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2494                                         }
2495                                 }
2496                         }
2497                 }
2498         }
2499 }
2500
2501 void dump_loop(FILE *F, ir_loop *l)
2502 {
2503         eset *loopnodes = eset_create();
2504         eset *extnodes = eset_create();
2505         ir_node *n, *b;
2506         char name[50];
2507
2508         snprintf(name, sizeof(name), "loop_%ld", get_loop_loop_nr(l));
2509         dump_vcg_header(F, name, NULL, NULL);
2510
2511         /* collect all nodes to dump */
2512         collect_nodeloop(F, l, loopnodes);
2513         collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2514
2515         /* build block lists */
2516         eset_foreach(loopnodes, ir_node*, n) {
2517                 set_irn_link(n, NULL);
2518         }
2519         eset_foreach(extnodes, ir_node*, n) {
2520                 set_irn_link(n, NULL);
2521         }
2522         eset_foreach(loopnodes, ir_node*, n) {
2523                 if (!is_Block(n)) {
2524                         b = get_nodes_block(n);
2525                         set_irn_link(n, get_irn_link(b));
2526                         set_irn_link(b, n);
2527                 }
2528         }
2529         eset_foreach(extnodes, ir_node*, n) {
2530                 if (!is_Block(n)) {
2531                         b = get_nodes_block(n);
2532                         set_irn_link(n, get_irn_link(b));
2533                         set_irn_link(b, n);
2534                 }
2535         }
2536
2537         eset_foreach(loopnodes, ir_node*, b) {
2538                 if (is_Block(b)) {
2539                         fprintf(F, "graph: { title: \"");
2540                         PRINT_NODEID(b);
2541                         fprintf(F, "\"  label: \"");
2542                         dump_node_opcode(F, b);
2543                         fprintf(F, " %ld:%u", get_irn_node_nr(b), get_irn_idx(b));
2544                         fprintf(F, "\" status:clustered color:yellow\n");
2545
2546                         /* dump the blocks edges */
2547                         dump_ir_data_edges(F, b);
2548
2549                         /* dump the nodes that go into the block */
2550                         for (n = (ir_node*)get_irn_link(b); n; n = (ir_node*)get_irn_link(n)) {
2551                                 if (eset_contains(extnodes, n))
2552                                         overrule_nodecolor = ird_color_block_inout;
2553                                 dump_node(F, n);
2554                                 overrule_nodecolor = ird_color_default_node;
2555                                 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2556                         }
2557
2558                         /* Close the vcg information for the block */
2559                         fprintf(F, "}\n");
2560                         dump_const_node_local(F, b);
2561                         fprintf(F, "\n");
2562                 }
2563         }
2564         eset_foreach(extnodes, ir_node*, b) {
2565                 if (is_Block(b)) {
2566                         fprintf(F, "graph: { title: \"");
2567                         PRINT_NODEID(b);
2568                         fprintf(F, "\"  label: \"");
2569                         dump_node_opcode(F, b);
2570                         fprintf(F, " %ld:%u", get_irn_node_nr(b), get_irn_idx(b));
2571                         fprintf(F, "\" status:clustered color:lightblue\n");
2572
2573                         /* dump the nodes that go into the block */
2574                         for (n = (ir_node*)get_irn_link(b); n; n = (ir_node*)get_irn_link(n)) {
2575                                 if (!eset_contains(loopnodes, n))
2576                                         overrule_nodecolor = ird_color_block_inout;
2577                                 dump_node(F, n);
2578                                 overrule_nodecolor = ird_color_default_node;
2579                                 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2580                         }
2581
2582                         /* Close the vcg information for the block */
2583                         fprintf(F, "}\n");
2584                         dump_const_node_local(F, b);
2585                         fprintf(F, "\n");
2586                 }
2587         }
2588         eset_destroy(loopnodes);
2589         eset_destroy(extnodes);
2590
2591         dump_vcg_footer(F);
2592 }
2593
2594 static bool   obstack_init;
2595 static struct obstack obst;
2596 static char  *dump_path;
2597
2598 void ir_set_dump_path(const char *path)
2599 {
2600         xfree(dump_path);
2601         dump_path = xstrdup(path);
2602 }
2603
2604 static void add_string_escaped(const char *string)
2605 {
2606         const char *p;
2607         for (p = string; *p != '\0'; ++p) {
2608                 char c = *p;
2609                 if (c == '/') {
2610                         obstack_1grow(&obst, '@');
2611                         obstack_1grow(&obst, '1');
2612                 } else if (c == '@') {
2613                         obstack_1grow(&obst, '@');
2614                         obstack_1grow(&obst, '2');
2615                 } else {
2616                         obstack_1grow(&obst, c);
2617                 }
2618         }
2619 }
2620
2621 static void add_dump_path(void)
2622 {
2623         if (!obstack_init) {
2624                 obstack_init(&obst);
2625                 obstack_init = true;
2626         }
2627
2628         if (dump_path != NULL) {
2629                 size_t len = strlen(dump_path);
2630                 obstack_grow(&obst, dump_path, len);
2631                 if (len > 0 && dump_path[len-1] != '/')
2632                         obstack_1grow(&obst, '/');
2633         }
2634 }
2635
2636 void dump_ir_graph_ext(ir_graph_dump_func func, ir_graph *graph,
2637                        const char *suffix)
2638 {
2639         const char *dump_name = get_irg_dump_name(graph);
2640         char       *file_name;
2641         FILE       *out;
2642
2643         if (!ir_should_dump(dump_name))
2644                 return;
2645
2646         add_dump_path();
2647
2648         add_string_escaped(dump_name);
2649         obstack_printf(&obst, "-%02u", graph->dump_nr++);
2650
2651         if (suffix != NULL) {
2652                 if (suffix[0] != '.')
2653                         obstack_1grow(&obst, '-');
2654                 add_string_escaped(suffix);
2655         }
2656         obstack_1grow(&obst, '\0');
2657
2658         file_name = (char*)obstack_finish(&obst);
2659         /* xvcg expects only <CR> so we need "b"inary mode (for win32) */
2660         out       = fopen(file_name, "wb");
2661         obstack_free(&obst, file_name);
2662
2663         if (out == NULL) {
2664                 fprintf(stderr, "Couldn't open '%s': %s\n", file_name, strerror(errno));
2665                 return;
2666         }
2667
2668         func(out, graph);
2669         fclose(out);
2670 }
2671
2672 void dump_ir_prog_ext(ir_prog_dump_func func, const char *suffix)
2673 {
2674         char *file_name;
2675         FILE *out;
2676
2677         add_dump_path();
2678
2679         obstack_printf(&obst, "%02u", irp->dump_nr++);
2680         if (suffix != NULL) {
2681                 if (suffix[0] != '.')
2682                         obstack_1grow(&obst, '-');
2683                 add_string_escaped(suffix);
2684         }
2685         obstack_1grow(&obst, '\0');
2686
2687         file_name = (char*)obstack_finish(&obst);
2688         out       = fopen(file_name, "wb");
2689         obstack_free(&obst, file_name);
2690
2691         if (out == NULL) {
2692                 fprintf(stderr, "Couldn't open '%s': %s\n", file_name, strerror(errno));
2693                 return;
2694         }
2695         func(out);
2696         fclose(out);
2697 }
2698
2699 void dump_ir_graph(ir_graph *graph, const char *suffix)
2700 {
2701         char buf[256];
2702
2703         snprintf(buf, sizeof(buf), "%s.vcg", suffix);
2704         dump_ir_graph_ext(dump_ir_graph_file, graph, buf);
2705 }
2706
2707 void dump_all_ir_graphs(const char *suffix)
2708 {
2709         size_t i, n_irgs = get_irp_n_irgs();
2710
2711         for (i = 0; i < n_irgs; ++i) {
2712                 ir_graph *irg = get_irp_irg(i);
2713                 dump_ir_graph(irg, suffix);
2714         }
2715 }
2716
2717 typedef struct pass_t {
2718         ir_prog_pass_t pass;
2719         char           suffix[1];
2720 } pass_t;
2721
2722 /**
2723  * Wrapper around dump_all_ir_graphs().
2724  */
2725 static int dump_all_ir_graphs_wrapper(ir_prog *irp, void *context)
2726 {
2727         pass_t *pass = (pass_t*)context;
2728
2729         (void)irp;
2730         dump_all_ir_graphs(pass->suffix);
2731         return 0;
2732 }
2733
2734 ir_prog_pass_t *dump_all_ir_graph_pass(const char *name, const char *suffix)
2735 {
2736         size_t  len  = strlen(suffix) + 1;
2737         pass_t *pass = XMALLOCF(pass_t, suffix, len);
2738         ir_prog_pass_t *res  = def_prog_pass_constructor(
2739                 &pass->pass, name ? name : "dump_all_graphs", dump_all_ir_graphs_wrapper);
2740
2741         /* this pass does not change anything, so neither dump nor verify is needed. */
2742         res->dump_irprog   = ir_prog_no_dump;
2743         res->verify_irprog = ir_prog_no_verify;
2744
2745         memcpy(pass->suffix, suffix, len);
2746
2747         return res;
2748 }