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