cleanup vrp
[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_Cmp:
912                 fprintf(F, "%s ", get_relation_string(get_Cmp_relation(n)));
913                 break;
914         case iro_Confirm:
915                 fprintf(F, "%s ", get_relation_string(get_Confirm_relation(n)));
916                 break;
917         case iro_CopyB:
918                 ir_fprintf(F, "(%+F)", get_CopyB_type(n));
919                 break;
920
921         default:
922                 break;
923         }
924 }
925
926 void dump_node_label(FILE *F, const ir_node *n)
927 {
928         dump_node_opcode(F, n);
929         fputs(" ", F);
930         dump_node_mode(F, n);
931         fprintf(F, " ");
932         dump_node_typeinfo(F, n);
933         dump_node_nodeattr(F, n);
934         if (flags & ir_dump_flag_number_label) {
935                 fprintf(F, "%ld", get_irn_node_nr(n));
936         }
937         if (flags & ir_dump_flag_idx_label) {
938                 fprintf(F, ":%u", get_irn_idx(n));
939         }
940 }
941
942 /**
943  * Dumps the attributes of a node n into the file F.
944  * Currently this is only the color of a node.
945  */
946 static void dump_node_vcgattr(FILE *F, const ir_node *node, const ir_node *local, bool bad)
947 {
948         ir_mode *mode;
949         const ir_node *n;
950
951         if (bad) {
952                 print_vcg_color(F, ird_color_error);
953                 return;
954         }
955
956         if (dump_node_vcgattr_hook != NULL) {
957                 dump_node_vcgattr_hook(F, node, local);
958                 return;
959         }
960
961         n = local ? local : node;
962
963         if (overrule_nodecolor != ird_color_default_node) {
964                 print_vcg_color(F, overrule_nodecolor);
965                 return;
966         }
967
968         mode = get_irn_mode(n);
969         if (mode == mode_M) {
970                 print_vcg_color(F, ird_color_memory);
971                 return;
972         }
973         if (mode == mode_X) {
974                 print_vcg_color(F, ird_color_controlflow);
975                 return;
976         }
977
978         switch (get_irn_opcode(n)) {
979         case iro_Start:
980         case iro_End:
981                 print_vcg_color(F, ird_color_anchor);
982                 break;
983         case iro_Bad:
984                 print_vcg_color(F, ird_color_error);
985                 break;
986         case iro_Block:
987                 print_vcg_color(F, ird_color_block_background);
988                 break;
989         case iro_Phi:
990                 print_vcg_color(F, ird_color_phi);
991                 break;
992         case iro_Pin:
993                 print_vcg_color(F, ird_color_memory);
994                 break;
995         case iro_SymConst:
996         case iro_Const:
997                 print_vcg_color(F, ird_color_const);
998                 break;
999         case iro_Proj:
1000                 print_vcg_color(F, ird_color_proj);
1001                 break;
1002         default: {
1003                 ir_op *op = get_irn_op(node);
1004
1005                 if (is_op_constlike(op)) {
1006                         print_vcg_color(F, ird_color_const);
1007                 } else if (is_op_uses_memory(op)) {
1008                         print_vcg_color(F, ird_color_uses_memory);
1009                 } else if (is_op_cfopcode(op) || is_op_forking(op)) {
1010                         print_vcg_color(F, ird_color_controlflow);
1011                 }
1012         }
1013         }
1014 }
1015
1016 void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
1017 {
1018         hook_entry_t *info = XMALLOCZ(hook_entry_t);
1019
1020         info->hook._hook_node_info = cb;
1021         info->context              = data;
1022         register_hook(hook_node_info, info);
1023
1024         return info;
1025 }
1026
1027 void dump_remove_node_info_callback(void *handle)
1028 {
1029         hook_entry_t *info = (hook_entry_t*)handle;
1030         unregister_hook(hook_node_info, info);
1031         xfree(info);
1032 }
1033
1034 /**
1035  * Dump the node information of a node n to a file F.
1036  */
1037 static void dump_node_info(FILE *F, const ir_node *n)
1038 {
1039         const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1040
1041         fprintf(F, " info1: \"");
1042         dump_irnode_to_file(F, n);
1043         /* call the dump_node operation if available */
1044         if (ops->dump_node)
1045                 ops->dump_node(F, n, dump_node_info_txt);
1046
1047         /* allow additional info to be added */
1048         hook_node_info(F, n);
1049         fprintf(F, "\"\n");
1050 }
1051
1052 static int is_constlike_node(const ir_node *node)
1053 {
1054         const ir_op *op = get_irn_op(node);
1055         return is_op_constlike(op);
1056 }
1057
1058 static void print_constid(FILE *F, const ir_node *user, const ir_node *node)
1059 {
1060         fprintf(F, "\"n%ldb%ld\"", get_irn_node_nr(user), get_irn_node_nr(node));
1061 }
1062
1063 static void print_constblkid(FILE *F, const ir_node *node, const ir_node *block)
1064 {
1065         fprintf(F, "\"n%ldb%ld\"", get_irn_node_nr(node), get_irn_node_nr(block));
1066 }
1067
1068
1069 /** outputs the predecessors of n, that are constants, local.  I.e.,
1070    generates a copy of the constant predecessors for each node called with. */
1071 static void dump_const_node_local(FILE *F, const ir_node *n)
1072 {
1073         ir_graph *irg = get_irn_irg(n);
1074         int i;
1075         if (!get_opt_dump_const_local()) return;
1076
1077         /* Use visited flag to avoid outputting nodes twice.
1078         initialize it first. */
1079         for (i = 0; i < get_irn_arity(n); i++) {
1080                 ir_node *con = get_irn_n(n, i);
1081                 if (is_constlike_node(con)) {
1082                         set_irn_visited(con, get_irg_visited(irg) - 1);
1083                 }
1084         }
1085
1086         for (i = 0; i < get_irn_arity(n); i++) {
1087                 ir_node *con = get_irn_n(n, i);
1088                 if (is_constlike_node(con) && !irn_visited_else_mark(con)) {
1089                         /* Generate a new name for the node by appending the names of
1090                         n and const. */
1091                         fprintf(F, "node: {title: ");
1092                         print_constid(F, n, con);
1093                         fprintf(F, " label: \"");
1094                         dump_node_label(F, con);
1095                         fprintf(F, "\" ");
1096                         dump_node_info(F, con);
1097                         dump_node_vcgattr(F, n, con, 0);
1098                         fprintf(F, "}\n");
1099                 }
1100         }
1101 }
1102
1103 /** If the block of an edge is a const_like node, dump it local with an edge */
1104 static void dump_const_block_local(FILE *F, const ir_node *n)
1105 {
1106         ir_node *blk;
1107
1108         if (!get_opt_dump_const_local()) return;
1109
1110         blk = get_nodes_block(n);
1111         if (is_constlike_node(blk)) {
1112                 /* Generate a new name for the node by appending the names of
1113                 n and blk. */
1114                 fprintf(F, "node: {title: ");
1115                 print_constblkid(F, n, blk);
1116                 fprintf(F, " label: \"");
1117                 dump_node_label(F, blk);
1118                 fprintf(F, "\" ");
1119                 dump_node_info(F, blk);
1120                 dump_node_vcgattr(F, n, blk, 0);
1121                 fprintf(F, "}\n");
1122
1123                 fprintf(F, "edge: { sourcename: ");
1124                 print_nodeid(F, n);
1125                 fprintf(F, " targetname: ");
1126                 print_constblkid(F, n, blk);
1127                 fprintf(F, " ");
1128
1129                 if (dump_edge_vcgattr_hook != NULL
1130                     && dump_edge_vcgattr_hook(F, n, -1)) {
1131                         fprintf(F, "}\n");
1132                         return;
1133                 }
1134
1135                 fprintf(F, BLOCK_EDGE_ATTR "}\n");
1136         }
1137 }
1138
1139 /**
1140  * prints the error message of a node to a file F as info2.
1141  */
1142 static void print_node_error(FILE *F, const char *err_msg)
1143 {
1144         if (! err_msg)
1145                 return;
1146
1147         fprintf(F, " info2: \"%s\"", err_msg);
1148 }
1149
1150 /**
1151  * prints debug messages of a node to file F as info3.
1152  */
1153 static void print_dbg_info(FILE *F, dbg_info *dbg)
1154 {
1155         char buf[1024];
1156
1157         ir_dbg_info_snprint(buf, sizeof(buf), dbg);
1158         if (buf[0] != 0) {
1159                 fprintf(F, " info3: \"%s\"\n", buf);
1160         }
1161 }
1162
1163 static void print_type_dbg_info(FILE *F, type_dbg_info *dbg)
1164 {
1165         (void) F;
1166         (void) dbg;
1167         /* TODO */
1168 }
1169
1170 /**
1171  * Dump a node
1172  */
1173 void dump_node(FILE *F, const ir_node *n)
1174 {
1175         int bad = 0;
1176         const char *p;
1177         ir_graph   *irg;
1178
1179         if (get_opt_dump_const_local() && is_constlike_node(n))
1180                 return;
1181
1182         /* dump this node */
1183         fputs("node: {title: ", F);
1184         print_nodeid(F, n);
1185
1186         fputs(" label: \"", F);
1187         irg = get_irn_irg(n);
1188         bad = ! irn_verify_irg_dump(n, irg, &p);
1189         dump_node_label(F, n);
1190         fputs("\" ", F);
1191
1192         dump_node_info(F, n);
1193         print_node_error(F, p);
1194         print_dbg_info(F, get_irn_dbg_info(n));
1195         dump_node_vcgattr(F, n, NULL, bad);
1196         fputs("}\n", F);
1197         dump_const_node_local(F, n);
1198
1199 }
1200
1201 /** dump the edge to the block this node belongs to */
1202 static void dump_ir_block_edge(FILE *F, const ir_node *n)
1203 {
1204         if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1205         if (!is_Block(n)) {
1206                 ir_node *block = get_nodes_block(n);
1207
1208                 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1209                         dump_const_block_local(F, n);
1210                 } else {
1211                         fprintf(F, "edge: { sourcename: ");
1212                         print_nodeid(F, n);
1213                         fprintf(F, " targetname: ");
1214                         print_nodeid(F, block);
1215                         fprintf(F, " ");
1216
1217                         if (dump_edge_vcgattr_hook && dump_edge_vcgattr_hook(F, n, -1)) {
1218                                 fprintf(F, "}\n");
1219                                 return;
1220                         }
1221
1222                         fprintf(F, BLOCK_EDGE_ATTR "}\n");
1223                 }
1224         }
1225 }
1226
1227 static void print_data_edge_vcgattr(FILE *F, const ir_node *from, int to)
1228 {
1229         /*
1230          * do not use get_nodes_block() here, will fail
1231          * if the irg is not pinned.
1232          */
1233         if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
1234                 fprintf(F, INTRA_DATA_EDGE_ATTR);
1235         else
1236                 fprintf(F, INTER_DATA_EDGE_ATTR);
1237 }
1238
1239 static void print_mem_edge_vcgattr(FILE *F, const ir_node *from, int to)
1240 {
1241         /*
1242          * do not use get_nodes_block() here, will fail
1243          * if the irg is not pinned.
1244          */
1245         if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
1246                 fprintf(F, INTRA_MEM_EDGE_ATTR);
1247         else
1248                 fprintf(F, INTER_MEM_EDGE_ATTR);
1249 }
1250
1251 /** Print the vcg attributes for the edge from node "from" to its "to"th input */
1252 static void print_edge_vcgattr(FILE *F, const ir_node *from, int to)
1253 {
1254         assert(from);
1255
1256         if (dump_edge_vcgattr_hook)
1257                 if (dump_edge_vcgattr_hook(F, from, to))
1258                         return;
1259
1260         if ((flags & ir_dump_flag_back_edges) && is_backedge(from, to))
1261                 fprintf(F, BACK_EDGE_ATTR);
1262
1263         switch (get_irn_opcode(from)) {
1264         case iro_Block:
1265                 fprintf(F, CF_EDGE_ATTR);
1266                 break;
1267         case iro_Start:  break;
1268         case iro_End:
1269                 if (to >= 0) {
1270                         if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1271                                 fprintf(F, KEEP_ALIVE_CF_EDGE_ATTR);
1272                         else
1273                                 fprintf(F, KEEP_ALIVE_DF_EDGE_ATTR);
1274                 }
1275                 break;
1276         default:
1277                 if (is_Proj(from)) {
1278                         if (get_irn_mode(from) == mode_M)
1279                                 print_mem_edge_vcgattr(F, from, to);
1280                         else if (get_irn_mode(from) == mode_X)
1281                                 fprintf(F, CF_EDGE_ATTR);
1282                         else
1283                                 print_data_edge_vcgattr(F, from, to);
1284                 }
1285                 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1286                         print_mem_edge_vcgattr(F, from, to);
1287                 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1288                         fprintf(F, CF_EDGE_ATTR);
1289                 else
1290                         print_data_edge_vcgattr(F, from, to);
1291         }
1292 }
1293
1294 /** dump edges to our inputs */
1295 static void dump_ir_data_edges(FILE *F, const ir_node *n)
1296 {
1297         int i, num;
1298
1299         if (dump_node_edge_hook)
1300                 dump_node_edge_hook(F, n);
1301
1302         if (!(flags & ir_dump_flag_keepalive_edges) && is_End(n)) {
1303                 /* the End node has only keep-alive edges */
1304                 return;
1305         }
1306
1307         /* dump the dependency edges. */
1308         num = get_irn_deps(n);
1309         for (i = 0; i < num; ++i) {
1310                 ir_node *dep = get_irn_dep(n, i);
1311
1312                 if (dep) {
1313                         print_node_edge_kind(F, n);
1314                         fprintf(F, "{sourcename: ");
1315                         print_nodeid(F, n);
1316                         fprintf(F, " targetname: ");
1317                         if ((get_opt_dump_const_local()) && is_constlike_node(dep)) {
1318                                 print_constid(F, n, dep);
1319                         } else {
1320                                 print_nodeid(F, dep);
1321                         }
1322                         fprintf(F, " label: \"%d\" ", i);
1323                         fprintf(F, " color: darkgreen}\n");
1324                 }
1325         }
1326
1327         num = get_irn_arity(n);
1328         for (i = 0; i < num; i++) {
1329                 ir_node *pred = get_irn_n(n, i);
1330                 assert(pred);
1331
1332                 if ((flags & ir_dump_flag_back_edges) && is_backedge(n, i)) {
1333                         fprintf(F, "backedge: {sourcename: ");
1334                 } else {
1335                         print_node_edge_kind(F, n);
1336                         fprintf(F, "{sourcename: ");
1337                 }
1338                 print_nodeid(F, n);
1339                 fprintf(F, " targetname: ");
1340                 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1341                         print_constid(F, n, pred);
1342                 } else {
1343                         print_nodeid(F, pred);
1344                 }
1345                 fprintf(F, " label: \"%d\" ", i);
1346                 print_edge_vcgattr(F, n, i);
1347                 fprintf(F, "}\n");
1348         }
1349 }
1350
1351 /**
1352  * Dump the ir_edges
1353  */
1354 static void dump_ir_edges(ir_node *node, void *env)
1355 {
1356         int   i = 0;
1357         FILE *F = (FILE*)env;
1358
1359         foreach_out_edge(node, edge) {
1360                 ir_node *succ = get_edge_src_irn(edge);
1361
1362                 print_node_edge_kind(F, succ);
1363                 fprintf(F, "{sourcename: ");
1364                 print_nodeid(F, node);
1365                 fprintf(F, " targetname: ");
1366                 print_nodeid(F, succ);
1367
1368                 fprintf(F, " label: \"%d\" ", i);
1369                 fprintf(F, OUT_EDGE_ATTR);
1370                 fprintf(F, "}\n");
1371                 ++i;
1372         }
1373 }
1374
1375
1376 /** Dumps a node and its edges but not the block edge  */
1377 static void dump_node_wo_blockedge(FILE *F, const ir_node *n)
1378 {
1379         dump_node(F, n);
1380         dump_ir_data_edges(F, n);
1381 }
1382
1383 /** Dumps a node and its edges. */
1384 static void dump_node_with_edges(ir_node *n, void *env)
1385 {
1386         FILE *F = (FILE*)env;
1387         dump_node_wo_blockedge(F, n);
1388         if (!node_floats(n))
1389                 dump_ir_block_edge(F, n);
1390 }
1391
1392 /** Dumps a const-like node. */
1393 static void dump_const_node(ir_node *n, void *env)
1394 {
1395         FILE *F = (FILE*)env;
1396         if (is_Block(n)) return;
1397         dump_node_wo_blockedge(F, n);
1398 }
1399
1400 /***********************************************************************/
1401 /* the following routines dump the nodes/irgs bracketed to graphs.     */
1402 /***********************************************************************/
1403
1404 /** Dumps a constant expression as entity initializer, array bound ... */
1405 static void dump_const_expression(FILE *F, ir_node *value)
1406 {
1407         ir_graph *irg = get_const_code_irg();
1408         ir_dump_flags_t old_flags = ir_get_dump_flags();
1409         ir_remove_dump_flags(ir_dump_flag_consts_local);
1410
1411         irg_walk(value, dump_const_node, NULL, F);
1412         /* Decrease visited flag so that we walk with the same flag for the next
1413            expression.  This guarantees that we don't dump the same node twice,
1414            as for const expressions cse is performed to save memory. */
1415         set_irg_visited(irg, get_irg_visited(irg) -1);
1416
1417         ir_set_dump_flags(old_flags);
1418 }
1419
1420 /** Dump a block as graph containing its nodes.
1421  *
1422  *  Expects to find nodes belonging to the block as list in its
1423  *  link field.
1424  *  Dumps the edges of all nodes including itself. */
1425 static void dump_whole_block(FILE *F, const ir_node *block)
1426 {
1427         ir_node *node;
1428
1429         assert(is_Block(block));
1430
1431         fprintf(F, "graph: { title: ");
1432         print_nodeid(F, block);
1433         fprintf(F, " label: \"");
1434         dump_node_label(F, block);
1435
1436         fprintf(F, "\" status:clustered ");
1437         /* colorize blocks */
1438         ird_color_t const color =
1439                 !get_Block_matured(block) ? ird_color_error :
1440                 ird_color_block_background;
1441         print_vcg_color(F, color);
1442         fprintf(F, "\n");
1443
1444         /* yComp can show attributes for blocks, XVCG parses but ignores them */
1445         dump_node_info(F, block);
1446         print_dbg_info(F, get_irn_dbg_info(block));
1447
1448         /* dump the blocks edges */
1449         dump_ir_data_edges(F, block);
1450
1451         if (dump_block_edge_hook)
1452                 dump_block_edge_hook(F, block);
1453
1454         /* dump the nodes that go into the block */
1455         for (node = (ir_node*)ird_get_irn_link(block); node; node = (ir_node*)ird_get_irn_link(node)) {
1456                 dump_node(F, node);
1457                 dump_ir_data_edges(F, node);
1458         }
1459
1460         /* Close the vcg information for the block */
1461         fprintf(F, "}\n");
1462         dump_const_node_local(F, block);
1463         fprintf(F, "\n");
1464 }
1465
1466 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1467  *  The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1468 static void dump_block_graph(FILE *F, ir_graph *irg)
1469 {
1470         size_t i, n;
1471         ir_node **arr = (ir_node**)ird_get_irg_link(irg);
1472
1473         for (i = 0, n = ARR_LEN(arr); i < n; ++i) {
1474                 ir_node *node = arr[i];
1475                 if (is_Block(node)) {
1476                 /* Dumps the block and all the nodes in the block, which are to
1477                         be found in Block->link. */
1478                         dump_whole_block(F, node);
1479                 } else {
1480                         /* Nodes that are not in a Block. */
1481                         dump_node(F, node);
1482                         if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1483                                 dump_const_block_local(F, node);
1484                         }
1485                         dump_ir_data_edges(F, node);
1486                 }
1487                 if ((flags & ir_dump_flag_iredges) && edges_activated(irg))
1488                         dump_ir_edges(node, F);
1489         }
1490
1491         if ((flags & ir_dump_flag_loops)
1492              && irg_has_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_LOOPINFO))
1493                 dump_loop_nodes_into_graph(F, irg);
1494 }
1495
1496 /**
1497  * Dump the info for an irg.
1498  * Parsed by XVCG but not shown. use yComp.
1499  */
1500 static void dump_graph_info(FILE *F, ir_graph *irg)
1501 {
1502         fprintf(F, "info1: \"");
1503         dump_entity_to_file(F, get_irg_entity(irg));
1504         fprintf(F, "\n");
1505
1506         /* dump graph state */
1507         fprintf(F, "constraints:");
1508         if (irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_ARCH_DEP))
1509                 fprintf(F, " arch_dep");
1510         if (irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_MODEB_LOWERED))
1511                 fprintf(F, " modeb_lowered");
1512         if (irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_NORMALISATION2))
1513                 fprintf(F, " normalisation2");
1514         if (irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_OPTIMIZE_UNREACHABLE_CODE))
1515                 fprintf(F, " optimize_unreachable_code");
1516         fprintf(F, "\n");
1517
1518         fprintf(F, "properties:");
1519         if (irg_has_properties(irg, IR_GRAPH_PROPERTY_NO_CRITICAL_EDGES))
1520                 fprintf(F, " no_critical_edges");
1521         if (irg_has_properties(irg, IR_GRAPH_PROPERTY_NO_BADS))
1522                 fprintf(F, " no_bads");
1523         if (irg_has_properties(irg, IR_GRAPH_PROPERTY_NO_UNREACHABLE_CODE))
1524                 fprintf(F, " no_unreachable_code");
1525         if (irg_has_properties(irg, IR_GRAPH_PROPERTY_ONE_RETURN))
1526                 fprintf(F, " one_return");
1527         if (irg_has_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE))
1528                 fprintf(F, " consistent_dominance");
1529         if (irg_has_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_POSTDOMINANCE))
1530                 fprintf(F, " consistent_postdominance");
1531         if (irg_has_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUT_EDGES))
1532                 fprintf(F, " consistent_out_edges");
1533         if (irg_has_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS))
1534                 fprintf(F, " consistent_outs");
1535         if (irg_has_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_LOOPINFO))
1536                 fprintf(F, " consistent_loopinfo");
1537         if (irg_has_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_ENTITY_USAGE))
1538                 fprintf(F, " consistent_entity_usage");
1539         fprintf(F, "\"\n");
1540 }
1541
1542 /** Dumps an irg as a graph clustered by block nodes.
1543  *  If interprocedural view edges can point to nodes out of this graph.
1544  */
1545 static void dump_graph_from_list(FILE *F, ir_graph *irg)
1546 {
1547         ir_entity *ent = get_irg_entity(irg);
1548
1549         fprintf(F, "graph: { title: ");
1550         print_irgid(F, irg);
1551         fprintf(F, " label: \"%s\" status:clustered color:%s\n",
1552           get_ent_dump_name(ent), color_names[ird_color_prog_background]);
1553
1554         dump_graph_info(F, irg);
1555         print_dbg_info(F, get_entity_dbg_info(ent));
1556
1557         dump_block_graph(F, irg);
1558
1559         /* Close the vcg information for the irg */
1560         fprintf(F, "}\n\n");
1561 }
1562
1563 /*******************************************************************/
1564 /* Basic type and entity nodes and edges.                          */
1565 /*******************************************************************/
1566
1567 /** dumps the edges between nodes and their type or entity attributes. */
1568 static void dump_node2type_edges(ir_node *n, void *env)
1569 {
1570         FILE *F = (FILE*)env;
1571         assert(n);
1572
1573         switch (get_irn_opcode(n)) {
1574         case iro_Const :
1575                 /* @@@ some consts have an entity */
1576                 break;
1577         case iro_SymConst:
1578                 if (SYMCONST_HAS_TYPE(get_SymConst_kind(n)))
1579                         print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1580                 break;
1581         case iro_Sel:
1582                 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1583                 break;
1584         case iro_Call:
1585                 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1586                 break;
1587         case iro_Alloc:
1588                 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1589                 break;
1590         case iro_Free:
1591                 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1592                 break;
1593         default:
1594                 break;
1595         }
1596 }
1597
1598 static void print_typespecific_vcgattr(FILE *F, ir_type *tp)
1599 {
1600         switch (get_type_tpop_code(tp)) {
1601         case tpo_class:
1602                 fprintf(F, " " TYPE_CLASS_NODE_ATTR);
1603                 break;
1604         case tpo_struct:
1605                 fprintf(F, " " TYPE_METH_NODE_ATTR);
1606                 break;
1607         case tpo_method:
1608                 break;
1609         case tpo_union:
1610                 break;
1611         case tpo_array:
1612                 break;
1613         case tpo_enumeration:
1614                 break;
1615         case tpo_pointer:
1616                 break;
1617         case tpo_primitive:
1618                 break;
1619         default:
1620                 break;
1621         }
1622 }
1623
1624 void dump_type_node(FILE *F, ir_type *tp)
1625 {
1626         fprintf(F, "node: {title: ");
1627         print_typeid(F, tp);
1628         fprintf(F, " label: \"");
1629         if (tp->dbi != NULL) {
1630                 char buf[1024];
1631                 ir_print_type(buf, sizeof(buf), tp);
1632                 fprintf(F, "%s '%s'", get_type_tpop_name(tp), buf);
1633         } else {
1634                 ir_fprintf(F, "%+F", tp);
1635         }
1636         fputs("\" info1: \"", F);
1637         dump_type_to_file(F, tp);
1638         fprintf(F, "\"\n");
1639         print_type_dbg_info(F, get_type_dbg_info(tp));
1640         print_typespecific_vcgattr(F, tp);
1641         fprintf(F, "}\n");
1642 }
1643
1644 static void dump_entity_node(FILE *F, ir_entity *ent)
1645 {
1646         fprintf(F, "node: {title: ");
1647         print_entityid(F, ent);
1648         fprintf(F, " label: ");
1649         fprintf(F, "\"%s\" ", get_ent_dump_name(ent));
1650
1651         print_vcg_color(F, ird_color_entity);
1652         fprintf(F, "\n info1: \"");
1653
1654         dump_entity_to_file(F, ent);
1655
1656         fprintf(F, "\"\n");
1657         print_dbg_info(F, get_entity_dbg_info(ent));
1658         fprintf(F, "}\n");
1659 }
1660
1661 static void dump_enum_item(FILE *F, ir_type *tp, size_t pos)
1662 {
1663         char buf[1024];
1664         ir_enum_const *ec = get_enumeration_const(tp, pos);
1665         ident         *id = get_enumeration_const_nameid(ec);
1666         ir_tarval     *tv = get_enumeration_value(ec);
1667
1668         if (tv)
1669                 tarval_snprintf(buf, sizeof(buf), tv);
1670         else
1671                 strncpy(buf, "<not set>", sizeof(buf));
1672         fprintf(F, "node: {title: ");
1673         print_itemid(F, tp, pos);
1674         fprintf(F, " label: ");
1675         fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1676         fprintf(F, "\n info1: \"value: %s\"}\n", buf);
1677 }
1678
1679 /**
1680  * Dumps a new style initializer.
1681  */
1682 static void dump_entity_initializer(FILE *F, const ir_entity *ent)
1683 {
1684         /* TODO */
1685         (void) F;
1686         (void) ent;
1687 }
1688
1689 /**
1690  * type-walker: Dumps a type or entity and its edges.
1691  */
1692 static void dump_type_info(type_or_ent tore, void *env)
1693 {
1694         FILE *F = (FILE*)env;
1695         size_t i = 0;  /* to shutup gcc */
1696
1697         /* dump this type or entity */
1698
1699         switch (get_kind(tore.ent)) {
1700         case k_entity: {
1701                 ir_entity *ent = tore.ent;
1702                 /* The node */
1703                 dump_entity_node(F, ent);
1704                 /* The Edges */
1705                 /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
1706                 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1707                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1708                 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1709                 if (is_Class_type(get_entity_owner(ent))) {
1710                         for (i = get_entity_n_overwrites(ent); i > 0;)
1711                                 print_ent_ent_edge(F, ent, get_entity_overwrites(ent, --i), 0, ird_color_none, ENT_OVERWRITES_EDGE_ATTR);
1712                 }
1713                 /* attached subgraphs */
1714                 if (! (flags & ir_dump_flag_no_entity_values)) {
1715                         if (ent->initializer != NULL) {
1716                                 /* new style initializers */
1717                                 dump_entity_initializer(F, ent);
1718                         }
1719                 }
1720                 break;
1721         }
1722         case k_type: {
1723                 ir_type *tp = tore.typ;
1724                 dump_type_node(F, tp);
1725                 /* and now the edges */
1726                 switch (get_type_tpop_code(tp)) {
1727                 case tpo_class:
1728                         for (i = get_class_n_supertypes(tp); i > 0;) {
1729                                 --i;
1730                                 print_type_type_edge(F, tp, get_class_supertype(tp, i), TYPE_SUPER_EDGE_ATTR);
1731                         }
1732                         for (i = get_class_n_members(tp); i > 0;) {
1733                                 --i;
1734                                 print_type_ent_edge(F, tp, get_class_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
1735                         }
1736                         break;
1737                 case tpo_struct:
1738                         for (i = get_struct_n_members(tp); i > 0;) {
1739                                 --i;
1740                                 print_type_ent_edge(F, tp, get_struct_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
1741                         }
1742                         break;
1743                 case tpo_method:
1744                         for (i = get_method_n_params(tp); i > 0;) {
1745                                 --i;
1746                                 print_type_type_edge(F, tp, get_method_param_type(tp, i), METH_PAR_EDGE_ATTR,i);
1747                         }
1748                         for (i = get_method_n_ress(tp); i > 0;) {
1749                                  --i;
1750                                 print_type_type_edge(F, tp, get_method_res_type(tp, i), METH_RES_EDGE_ATTR,i);
1751                         }
1752                         break;
1753                 case tpo_union:
1754                         for (i = get_union_n_members(tp); i > 0;) {
1755                                  --i;
1756                                 print_type_ent_edge(F, tp, get_union_member(tp, i), UNION_EDGE_ATTR);
1757                         }
1758                         break;
1759                 case tpo_array:
1760                         print_type_type_edge(F, tp, get_array_element_type(tp), ARR_ELT_TYPE_EDGE_ATTR);
1761                         print_type_ent_edge(F, tp, get_array_element_entity(tp), ARR_ENT_EDGE_ATTR);
1762                         for (i = get_array_n_dimensions(tp); i > 0;) {
1763                                 ir_node *upper, *lower;
1764
1765                                  --i;
1766                                 upper = get_array_upper_bound(tp, i);
1767                                 lower = get_array_lower_bound(tp, i);
1768                                 print_node_type_edge(F, upper, tp, "label: \"upper %zu\"", get_array_order(tp, i));
1769                                 print_node_type_edge(F, lower, tp, "label: \"lower %zu\"", get_array_order(tp, i));
1770                                 dump_const_expression(F, upper);
1771                                 dump_const_expression(F, lower);
1772                         }
1773                         break;
1774                 case tpo_enumeration:
1775                         for (i = get_enumeration_n_enums(tp); i > 0;) {
1776                                  --i;
1777                                 dump_enum_item(F, tp, i);
1778                                 print_enum_item_edge(F, tp, i, "label: \"item %zu\"", i);
1779                         }
1780                         break;
1781                 case tpo_pointer:
1782                         print_type_type_edge(F, tp, get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1783                         break;
1784                 case tpo_unknown:
1785                 case tpo_code:
1786                 case tpo_uninitialized:
1787                 case tpo_none:
1788                 case tpo_primitive:
1789                         break;
1790                 }
1791                 break; /* case k_type */
1792         }
1793         default:
1794                 printf(" *** irdump,  dump_type_info(l.%i), faulty type.\n", __LINE__);
1795         }
1796 }
1797
1798 /** For dumping class hierarchies.
1799  * Dumps a class type node and a superclass edge.
1800  */
1801 static void dump_class_hierarchy_node(type_or_ent tore, void *ctx)
1802 {
1803         FILE *F = (FILE*)ctx;
1804         size_t i = 0;  /* to shutup gcc */
1805
1806         /* dump this type or entity */
1807         switch (get_kind(tore.ent)) {
1808         case k_entity: {
1809                 ir_entity *ent = tore.ent;
1810                 if (get_entity_owner(ent) == get_glob_type()) break;
1811                 if (!is_Method_type(get_entity_type(ent)))
1812                         break;  /* GL */
1813                 if (flags & ir_dump_flag_entities_in_hierarchy
1814                                 && is_Class_type(get_entity_owner(ent))) {
1815                         /* The node */
1816                         dump_entity_node(F, ent);
1817                         /* The edges */
1818                         print_type_ent_edge(F, get_entity_owner(ent), ent, TYPE_MEMBER_EDGE_ATTR);
1819                         for (i = get_entity_n_overwrites(ent); i > 0;) {
1820                                  --i;
1821                                 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ird_color_none, ENT_OVERWRITES_EDGE_ATTR);
1822                         }
1823                 }
1824                 break;
1825         }
1826         case k_type: {
1827                 ir_type *tp = tore.typ;
1828                 if (tp == get_glob_type())
1829                         break;
1830                 switch (get_type_tpop_code(tp)) {
1831                 case tpo_class:
1832                         dump_type_node(F, tp);
1833                         /* and now the edges */
1834                         for (i = get_class_n_supertypes(tp); i > 0;) {
1835                                  --i;
1836                                 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1837                         }
1838                         break;
1839                 default: break;
1840                 }
1841                 break; /* case k_type */
1842         }
1843         default:
1844                 printf(" *** irdump,  dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1845         }
1846 }
1847
1848 /*******************************************************************/
1849 /* dump analysis information that is expressed in graph terms.     */
1850 /*******************************************************************/
1851
1852 /* dump out edges */
1853 static void dump_out_edge(ir_node *n, void *env)
1854 {
1855         FILE *F = (FILE*)env;
1856         int i;
1857         for (i = get_irn_n_outs(n) - 1; i >= 0; --i) {
1858                 ir_node *succ = get_irn_out(n, i);
1859                 assert(succ);
1860                 print_node_edge_kind(F, succ);
1861                 fprintf(F, "{sourcename: ");
1862                 print_nodeid(F, n);
1863                 fprintf(F, " targetname: ");
1864                 print_nodeid(F, succ);
1865                 fprintf(F, " color: red linestyle: dashed");
1866                 fprintf(F, "}\n");
1867         }
1868 }
1869
1870 static void dump_loop_label(FILE *F, const ir_loop *loop)
1871 {
1872         fprintf(F, "loop %u", get_loop_depth(loop));
1873 }
1874
1875 static void dump_loop_info(FILE *F, const ir_loop *loop)
1876 {
1877         fprintf(F, " info1: \"");
1878         fprintf(F, " loop nr: %ld", get_loop_loop_nr(loop));
1879 #ifdef DEBUG_libfirm
1880         fprintf(F, "\n The loop was analyzed %ld times.", (long int) PTR_TO_INT(get_loop_link(loop)));
1881 #endif
1882         fprintf(F, "\"");
1883 }
1884
1885 void print_loopid(FILE *F, const ir_loop *loop)
1886 {
1887         fprintf(F, "\"l%ld\"", get_loop_loop_nr(loop));
1888 }
1889
1890 static void dump_loop_node(FILE *F, const ir_loop *loop)
1891 {
1892         fprintf(F, "node: {title: ");
1893         print_loopid(F, loop);
1894         fprintf(F, " label: \"");
1895         dump_loop_label(F, loop);
1896         fprintf(F, "\" ");
1897         dump_loop_info(F, loop);
1898         fprintf(F, "}\n");
1899 }
1900
1901 static void dump_loop_node_edge(FILE *F, const ir_loop *loop, size_t i)
1902 {
1903         assert(loop);
1904         fprintf(F, "edge: {sourcename: ");
1905         print_loopid(F, loop);
1906         fprintf(F, " targetname: ");
1907         print_nodeid(F, get_loop_element(loop, i).node);
1908         fprintf(F, " color: green");
1909         fprintf(F, "}\n");
1910 }
1911
1912 static void dump_loop_son_edge(FILE *F, const ir_loop *loop, size_t i)
1913 {
1914         assert(loop);
1915         fprintf(F, "edge: {sourcename: ");
1916         print_loopid(F, loop);
1917         fprintf(F, " targetname: ");
1918         print_loopid(F, get_loop_element(loop, i).son);
1919         ir_fprintf(F, " color: darkgreen label: \"%zu\"}\n", i);
1920 }
1921
1922 static void dump_loops(FILE *F, const ir_loop *loop)
1923 {
1924         size_t i;
1925         size_t n_elements = get_loop_n_elements(loop);
1926         /* dump this loop node */
1927         dump_loop_node(F, loop);
1928
1929         /* dump edges to nodes in loop -- only if it is a real loop */
1930         if (get_loop_depth(loop) != 0) {
1931                 for (i = n_elements; i > 0;) {
1932                         loop_element element;
1933                         --i;
1934                         element = get_loop_element(loop, i);
1935                         if (*element.kind != k_ir_node)
1936                                 continue;
1937                         dump_loop_node_edge(F, loop, i);
1938                 }
1939         }
1940         for (i = n_elements; i > 0;) {
1941                 loop_element element;
1942                 --i;
1943                 element = get_loop_element(loop, i);
1944                 if (*element.kind != k_ir_loop)
1945                         continue;
1946                 dump_loops(F, element.son);
1947                 dump_loop_son_edge(F, loop, i);
1948         }
1949 }
1950
1951 static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg)
1952 {
1953         ir_loop *loop = get_irg_loop(irg);
1954         if (loop != NULL) {
1955                 dump_loops(F, loop);
1956         }
1957 }
1958
1959 void dump_vcg_header_colors(FILE *F)
1960 {
1961         int i;
1962         init_colors();
1963         for (i = 0; i < ird_color_count; ++i) {
1964                 if (color_rgb[i] != NULL) {
1965                         fprintf(F, "colorentry %s: %s\n", color_names[i], color_rgb[i]);
1966                 }
1967         }
1968 }
1969
1970 void dump_vcg_infonames(FILE *F)
1971 {
1972         fputs(
1973                 "infoname 1: \"Attribute\"\n"
1974                 "infoname 2: \"Verification errors\"\n"
1975                 "infoname 3: \"Debug info\"\n", F);
1976 }
1977
1978 /**
1979  * dumps the VCG header
1980  */
1981 void dump_vcg_header(FILE *F, const char *name, const char *layout, const char *orientation)
1982 {
1983         const char *label
1984                 = (flags & ir_dump_flag_disable_edge_labels) ? "no" : "yes";
1985
1986         if (! layout)     layout = "Compilergraph";
1987         if (!orientation) orientation = "bottom_to_top";
1988
1989         /* print header */
1990         fprintf(F,
1991                 "graph: { title: \"ir graph of %s\"\n"
1992                 "display_edge_labels: %s\n"
1993                 "layoutalgorithm: mindepth //$ \"%s\"\n"
1994                 "manhattan_edges: yes\n"
1995                 "port_sharing: no\n"
1996                 "orientation: %s\n"
1997                 "classname 1:  \"intrablock Data\"\n"
1998                 "classname 2:  \"Block\"\n"
1999                 "classname 3:  \"Entity type\"\n"
2000                 "classname 4:  \"Entity owner\"\n"
2001                 "classname 5:  \"Method Param\"\n"
2002                 "classname 6:  \"Method Res\"\n"
2003                 "classname 7:  \"Super\"\n"
2004                 "classname 8:  \"Union\"\n"
2005                 "classname 9:  \"Points-to\"\n"
2006                 "classname 10: \"Array Element Type\"\n"
2007                 "classname 11: \"Overwrites\"\n"
2008                 "classname 12: \"Member\"\n"
2009                 "classname 13: \"Control Flow\"\n"
2010                 "classname 14: \"intrablock Memory\"\n"
2011                 "classname 15: \"Dominators\"\n"
2012                 "classname 16: \"interblock Data\"\n"
2013                 "classname 17: \"interblock Memory\"\n"
2014                 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2015                 "classname 19: \"Postdominators\"\n"
2016                 "classname 20: \"Keep Alive\"\n"
2017                 "classname 21: \"Out Edges\"\n"
2018                 "classname 22: \"Macro Block Edges\"\n",
2019                 name, label, layout, orientation);
2020         dump_vcg_infonames(F);
2021         dump_vcg_header_colors(F);
2022         fprintf(F, "\n");
2023 }
2024
2025 /**
2026  * Dumps the vcg file footer
2027  */
2028 void dump_vcg_footer(FILE *F)
2029 {
2030         fprintf(F, "}\n");
2031 }
2032
2033
2034
2035 static void dump_blocks_as_subgraphs(FILE *out, ir_graph *irg)
2036 {
2037         size_t i;
2038
2039         construct_block_lists(irg);
2040
2041         /*
2042          * If we are in the interprocedural view, we dump not
2043          * only the requested irg but also all irgs that can be reached
2044          * from irg.
2045          */
2046         for (i = get_irp_n_irgs(); i > 0;) {
2047                 ir_graph *other_irg = get_irp_irg(--i);
2048                 ir_node **arr = (ir_node**)ird_get_irg_link(other_irg);
2049                 if (arr == NULL)
2050                         continue;
2051
2052                 dump_graph_from_list(out, other_irg);
2053                 DEL_ARR_F(arr);
2054         }
2055 }
2056
2057 void dump_ir_graph_file(FILE *out, ir_graph *irg)
2058 {
2059         dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2060
2061         /* dump nodes */
2062         if (flags & ir_dump_flag_blocks_as_subgraphs) {
2063                 dump_blocks_as_subgraphs(out, irg);
2064         } else {
2065                 /* dump_node_with_edges must be called in post visiting predecessors */
2066                 ird_walk_graph(irg, NULL, dump_node_with_edges, out);
2067         }
2068
2069         /* dump type info */
2070         if (flags & ir_dump_flag_with_typegraph) {
2071                 type_walk_irg(irg, dump_type_info, NULL, out);
2072                 inc_irg_visited(get_const_code_irg());
2073                 /* dump edges from graph to type info */
2074                 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, out);
2075         }
2076
2077         /* dump iredges out edges */
2078         if ((flags & ir_dump_flag_iredges) && edges_activated(irg)) {
2079                 irg_walk_edges(get_irg_start_block(irg), dump_ir_edges, NULL, out);
2080         }
2081
2082         /* dump the out edges in a separate walk */
2083         if ((flags & ir_dump_flag_out_edges)
2084                         && (irg_has_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS))) {
2085                 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, out);
2086         }
2087
2088         dump_vcg_footer(out);
2089 }
2090
2091 static void dump_block_to_cfg(ir_node *block, void *env)
2092 {
2093         FILE *F = (FILE*)env;
2094         int i;
2095
2096         if (is_Bad(block) && get_irn_mode(block) == mode_X) {
2097                 dump_node(F, block);
2098         }
2099
2100         if (is_Block(block)) {
2101                 /* This is a block. Dump a node for the block. */
2102                 fprintf(F, "node: {title: ");
2103                 print_nodeid(F, block);
2104                 fprintf(F, " label: \"");
2105                 if (block == get_irg_start_block(get_irn_irg(block)))
2106                         fprintf(F, "Start ");
2107                 if (block == get_irg_end_block(get_irn_irg(block)))
2108                         fprintf(F, "End ");
2109
2110                 fprintf(F, "%s ", get_op_name(get_irn_op(block)));
2111                 print_nodeid(F, block);
2112                 fprintf(F, "\" ");
2113                 fprintf(F, "info1:\"");
2114
2115                 /* the generic version. */
2116                 dump_irnode_to_file(F, block);
2117
2118                 fprintf(F, "\"");  /* closing quote of info */
2119
2120                 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2121                         (block == get_irg_end_block(get_irn_irg(block)))     )
2122                         fprintf(F, " color:blue ");
2123
2124                 fprintf(F, "}\n");
2125
2126                 /* Dump the edges */
2127                 for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
2128                         ir_node *pred = get_Block_cfgpred(block, i);
2129                         if (!is_Bad(pred))
2130                                 pred = get_nodes_block(pred);
2131                         fprintf(F, "edge: { sourcename: ");
2132                         print_nodeid(F, block);
2133                         fprintf(F, " targetname: ");
2134                         print_nodeid(F, pred);
2135                         fprintf(F, "\"}\n");
2136                 }
2137
2138                 /* Dump dominator/postdominator edge */
2139                 if (ir_get_dump_flags() & ir_dump_flag_dominance) {
2140                         if (irg_has_properties(get_irn_irg(block), IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE) && get_Block_idom(block)) {
2141                                 ir_node *pred = get_Block_idom(block);
2142                                 fprintf(F, "edge: { sourcename: ");
2143                                 print_nodeid(F, block);
2144                                 fprintf(F, " targetname: ");
2145                                 print_nodeid(F, pred);
2146                                 fprintf(F, " " DOMINATOR_EDGE_ATTR "}\n");
2147                         }
2148                         if (irg_has_properties(get_irn_irg(block), IR_GRAPH_PROPERTY_CONSISTENT_POSTDOMINANCE) && get_Block_ipostdom(block)) {
2149                                 ir_node *pred = get_Block_ipostdom(block);
2150                                 fprintf(F, "edge: { sourcename: ");
2151                                 print_nodeid(F, block);
2152                                 fprintf(F, " targetname: ");
2153                                 print_nodeid(F, pred);
2154                                 fprintf(F, " " POSTDOMINATOR_EDGE_ATTR "}\n");
2155                         }
2156                 }
2157         }
2158 }
2159
2160 void dump_cfg(FILE *F, ir_graph *irg)
2161 {
2162         dump_vcg_header(F, get_irg_dump_name(irg), NULL, NULL);
2163
2164         /* walk over the blocks in the graph */
2165         irg_walk_graph(irg, dump_block_to_cfg, NULL, F);
2166
2167         dump_vcg_footer(F);
2168 }
2169
2170 void dump_callgraph(FILE *F)
2171 {
2172         size_t          i;
2173         ir_dump_flags_t old_flags = ir_get_dump_flags();
2174
2175         ir_remove_dump_flags(ir_dump_flag_disable_edge_labels);
2176         dump_vcg_header(F, "Callgraph", "Hierarchic", NULL);
2177
2178         for (i = get_irp_n_irgs(); i > 0;) {
2179                 ir_graph *irg = get_irp_irg(--i);
2180                 ir_entity *ent = get_irg_entity(irg);
2181                 size_t j, n_callees = get_irg_n_callees(irg);
2182
2183                 dump_entity_node(F, ent);
2184                 for (j = 0; j < n_callees; ++j) {
2185                         ir_entity  *c    = get_irg_entity(get_irg_callee(irg, j));
2186                         int         be   = is_irg_callee_backedge(irg, j);
2187                         const char *attr = be
2188                                 ? "label:\"recursion %zu\""
2189                                 : "label:\"calls %zu\"";
2190                         print_ent_ent_edge(F, ent, c, be, ird_color_entity, attr,
2191                                            get_irg_callee_loop_depth(irg, j));
2192                 }
2193         }
2194
2195         ir_set_dump_flags(old_flags);
2196         dump_vcg_footer(F);
2197 }
2198
2199 void dump_typegraph(FILE *out)
2200 {
2201         dump_vcg_header(out, "All_types", NULL, NULL);
2202         type_walk(dump_type_info, NULL, out);
2203         dump_vcg_footer(out);
2204 }
2205
2206 void dump_class_hierarchy(FILE *out)
2207 {
2208         dump_vcg_header(out, "class_hierarchy", NULL, NULL);
2209         type_walk(dump_class_hierarchy_node, NULL, out);
2210         dump_vcg_footer(out);
2211 }
2212
2213 static void dump_loops_standalone(FILE *F, ir_loop *loop)
2214 {
2215         size_t i;
2216         bool   loop_node_started = false;
2217         size_t first      = 0;
2218         size_t son_number = 0;
2219         loop_element le;
2220         ir_loop *son = NULL;
2221
2222         /* Dump a new loop node. */
2223         dump_loop_node(F, loop);
2224
2225         /* Dump the loop elements. */
2226         for (i = 0; i < get_loop_n_elements(loop); i++) {
2227                 le = get_loop_element(loop, i);
2228                 son = le.son;
2229                 if (get_kind(son) == k_ir_loop) {
2230
2231                         /* We are a loop son -> Recurse */
2232
2233                         if (loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2234                                 fprintf(F, "\" }\n");
2235                                 fprintf(F, "edge: {sourcename: ");
2236                                 print_loopid(F, loop);
2237                                 fprintf(F, " targetname: \"l%ld-%lu-nodes\" label:\"%lu...%lu\"}\n",
2238                                         get_loop_loop_nr(loop),
2239                                                 (unsigned long) first,
2240                                                 (unsigned long) first,
2241                                         (unsigned long) i-1);
2242                                 loop_node_started = false;
2243                         }
2244                         dump_loop_son_edge(F, loop, son_number++);
2245                         dump_loops_standalone(F, son);
2246                 } else if (get_kind(son) == k_ir_node) {
2247                         /* We are a loop node -> Collect firm nodes */
2248
2249                         ir_node *n = le.node;
2250                         if (!loop_node_started) {
2251                                 /* Start a new node which contains all firm nodes of the current loop */
2252                                 fprintf(F, "node: { title: \"l%ld-%lu-nodes\" color: lightyellow label: \"",
2253                                         get_loop_loop_nr(loop),
2254                                         (unsigned long)i);
2255                                 loop_node_started = true;
2256                                 first = i;
2257                         } else
2258                                 fprintf(F, "\n");
2259
2260                         dump_node_label(F, n);
2261                         if (has_backedges(n)) fprintf(F, "\t loop head!");
2262                 } else { /* for callgraph loop tree */
2263                         ir_graph *n;
2264                         assert(get_kind(son) == k_ir_graph);
2265
2266                         /* We are a loop node -> Collect firm graphs */
2267                         n = le.irg;
2268                         if (!loop_node_started) {
2269                                 /* Start a new node which contains all firm nodes of the current loop */
2270                                 fprintf(F, "node: { title: \"l%ld-%lu-nodes\" color: lightyellow label: \"",
2271                                         get_loop_loop_nr(loop),
2272                                         (unsigned long)i);
2273                                 loop_node_started = true;
2274                                 first = i;
2275                         } else
2276                                 fprintf(F, "\n");
2277                         fprintf(F, " %s", get_irg_dump_name(n));
2278                         /* fprintf(F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2279                 }
2280         }
2281
2282         if (loop_node_started) {
2283                 fprintf(F, "\" }\n");
2284                 fprintf(F, "edge: {sourcename: \"");
2285                 print_loopid(F, loop);
2286                 fprintf(F, "\" targetname: \"l%ld-%lu-nodes\" label:\"%lu...%lu\"}\n",
2287                         get_loop_loop_nr(loop),
2288                         (unsigned long) first,
2289                         (unsigned long) first,
2290                         (unsigned long) i-1);
2291         }
2292 }
2293
2294 void dump_loop_tree(FILE *out, ir_graph *irg)
2295 {
2296         ir_dump_flags_t old_flags = ir_get_dump_flags();
2297
2298         ir_remove_dump_flags(ir_dump_flag_disable_edge_labels);
2299
2300         dump_vcg_header(out, get_irg_dump_name(irg), "Tree", "top_to_bottom");
2301
2302         if (get_irg_loop(irg))
2303                 dump_loops_standalone(out, get_irg_loop(irg));
2304
2305         dump_vcg_footer(out);
2306
2307         ir_set_dump_flags(old_flags);
2308 }
2309
2310 void dump_callgraph_loop_tree(FILE *out)
2311 {
2312         dump_vcg_header(out, "callgraph looptree", "Tree", "top_to_bottom");
2313         dump_loops_standalone(out, irp->outermost_cg_loop);
2314         dump_vcg_footer(out);
2315 }
2316
2317 static void collect_nodeloop(FILE *F, ir_loop *loop, pset *loopnodes)
2318 {
2319         size_t i;
2320         int    son_number = 0;
2321         int    node_number = 0;
2322
2323         if (flags & ir_dump_flag_loops)
2324                 dump_loop_node(F, loop);
2325
2326         for (i = 0; i < get_loop_n_elements(loop); i++) {
2327                 loop_element le = get_loop_element(loop, i);
2328                 if (*(le.kind) == k_ir_loop) {
2329                         if (flags & ir_dump_flag_loops)
2330                                 dump_loop_son_edge(F, loop, son_number++);
2331                         /* Recur */
2332                         collect_nodeloop(F, le.son, loopnodes);
2333                 } else {
2334                         if (flags & ir_dump_flag_loops)
2335                                 dump_loop_node_edge(F, loop, node_number++);
2336                         pset_insert_ptr(loopnodes, le.node);
2337                 }
2338         }
2339 }
2340
2341 static void collect_nodeloop_external_nodes(ir_loop *loop, pset *loopnodes,
2342                                             pset *extnodes)
2343 {
2344         size_t i;
2345         int j, start;
2346
2347         for (i = 0; i < get_loop_n_elements(loop); i++) {
2348                 loop_element le = get_loop_element(loop, i);
2349                 if (*(le.kind) == k_ir_loop) {
2350                         /* Recur */
2351                         collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2352                 } else {
2353                         if (is_Block(le.node)) start = 0; else start = -1;
2354                         for (j = start; j < get_irn_arity(le.node); j++) {
2355                                 ir_node *pred = get_irn_n(le.node, j);
2356                                 if (!pset_find_ptr(loopnodes, pred)) {
2357                                         pset_insert_ptr(extnodes, pred);
2358                                         if (!is_Block(pred)) {
2359                                                 pred = get_nodes_block(pred);
2360                                                 if (!pset_find_ptr(loopnodes, pred))
2361                                                         pset_insert_ptr(extnodes, pred);
2362                                         }
2363                                 }
2364                         }
2365                 }
2366         }
2367 }
2368
2369 void dump_loop(FILE *F, ir_loop *l)
2370 {
2371         pset *loopnodes = pset_new_ptr_default();
2372         pset *extnodes  = pset_new_ptr_default();
2373         char name[50];
2374
2375         snprintf(name, sizeof(name), "loop_%ld", get_loop_loop_nr(l));
2376         dump_vcg_header(F, name, NULL, NULL);
2377
2378         /* collect all nodes to dump */
2379         collect_nodeloop(F, l, loopnodes);
2380         collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2381
2382         /* build block lists */
2383         foreach_pset(loopnodes, ir_node, n) {
2384                 set_irn_link(n, NULL);
2385         }
2386         foreach_pset(extnodes, ir_node, n) {
2387                 set_irn_link(n, NULL);
2388         }
2389         foreach_pset(loopnodes, ir_node, n) {
2390                 if (!is_Block(n)) {
2391                         ir_node *const b = get_nodes_block(n);
2392                         set_irn_link(n, get_irn_link(b));
2393                         set_irn_link(b, n);
2394                 }
2395         }
2396         foreach_pset(extnodes, ir_node, n) {
2397                 if (!is_Block(n)) {
2398                         ir_node *const b = get_nodes_block(n);
2399                         set_irn_link(n, get_irn_link(b));
2400                         set_irn_link(b, n);
2401                 }
2402         }
2403
2404         foreach_pset(loopnodes, ir_node, b) {
2405                 if (is_Block(b)) {
2406                         fprintf(F, "graph: { title: ");
2407                         print_nodeid(F, b);
2408                         fprintf(F, "  label: \"");
2409                         dump_node_opcode(F, b);
2410                         fprintf(F, " %ld:%u", get_irn_node_nr(b), get_irn_idx(b));
2411                         fprintf(F, "\" status:clustered color:yellow\n");
2412
2413                         /* dump the blocks edges */
2414                         dump_ir_data_edges(F, b);
2415
2416                         /* dump the nodes that go into the block */
2417                         for (ir_node *n = (ir_node*)get_irn_link(b); n; n = (ir_node*)get_irn_link(n)) {
2418                                 if (pset_find_ptr(extnodes, n))
2419                                         overrule_nodecolor = ird_color_block_inout;
2420                                 dump_node(F, n);
2421                                 overrule_nodecolor = ird_color_default_node;
2422                                 if (!pset_find_ptr(extnodes, n)) dump_ir_data_edges(F, n);
2423                         }
2424
2425                         /* Close the vcg information for the block */
2426                         fprintf(F, "}\n");
2427                         dump_const_node_local(F, b);
2428                         fprintf(F, "\n");
2429                 }
2430         }
2431         foreach_pset(extnodes, ir_node, b) {
2432                 if (is_Block(b)) {
2433                         fprintf(F, "graph: { title: ");
2434                         print_nodeid(F, b);
2435                         fprintf(F, " label: \"");
2436                         dump_node_opcode(F, b);
2437                         fprintf(F, " %ld:%u", get_irn_node_nr(b), get_irn_idx(b));
2438                         fprintf(F, "\" status:clustered color:lightblue\n");
2439
2440                         /* dump the nodes that go into the block */
2441                         for (ir_node *n = (ir_node*)get_irn_link(b); n; n = (ir_node*)get_irn_link(n)) {
2442                                 if (!pset_find_ptr(loopnodes, n))
2443                                         overrule_nodecolor = ird_color_block_inout;
2444                                 dump_node(F, n);
2445                                 overrule_nodecolor = ird_color_default_node;
2446                                 if (pset_find_ptr(loopnodes, n)) dump_ir_data_edges(F, n);
2447                         }
2448
2449                         /* Close the vcg information for the block */
2450                         fprintf(F, "}\n");
2451                         dump_const_node_local(F, b);
2452                         fprintf(F, "\n");
2453                 }
2454         }
2455         del_pset(loopnodes);
2456         del_pset(extnodes);
2457
2458         dump_vcg_footer(F);
2459 }
2460
2461 static bool   obstack_init;
2462 static struct obstack obst;
2463 static char  *dump_path;
2464
2465 void ir_set_dump_path(const char *path)
2466 {
2467         xfree(dump_path);
2468         dump_path = xstrdup(path);
2469 }
2470
2471 static void add_string_escaped(const char *string)
2472 {
2473         const char *p;
2474         for (p = string; *p != '\0'; ++p) {
2475                 char c = *p;
2476                 if (c == '/') {
2477                         obstack_1grow(&obst, '@');
2478                         obstack_1grow(&obst, '1');
2479                 } else if (c == '@') {
2480                         obstack_1grow(&obst, '@');
2481                         obstack_1grow(&obst, '2');
2482                 } else {
2483                         obstack_1grow(&obst, c);
2484                 }
2485         }
2486 }
2487
2488 static void add_dump_path(void)
2489 {
2490         if (!obstack_init) {
2491                 obstack_init(&obst);
2492                 obstack_init = true;
2493         }
2494
2495         if (dump_path != NULL) {
2496                 size_t len = strlen(dump_path);
2497                 obstack_grow(&obst, dump_path, len);
2498                 if (len > 0 && dump_path[len-1] != '/')
2499                         obstack_1grow(&obst, '/');
2500         }
2501 }
2502
2503 void dump_ir_graph_ext(ir_graph_dump_func func, ir_graph *graph,
2504                        const char *suffix)
2505 {
2506         const char *dump_name = get_irg_dump_name(graph);
2507         char       *file_name;
2508         FILE       *out;
2509
2510         if (!ir_should_dump(dump_name))
2511                 return;
2512
2513         add_dump_path();
2514
2515         add_string_escaped(dump_name);
2516         obstack_printf(&obst, "-%02u", graph->dump_nr++);
2517
2518         if (suffix != NULL) {
2519                 if (suffix[0] != '.')
2520                         obstack_1grow(&obst, '-');
2521                 add_string_escaped(suffix);
2522         }
2523         obstack_1grow(&obst, '\0');
2524
2525         file_name = (char*)obstack_finish(&obst);
2526         /* xvcg expects only <LF> so we need "b"inary mode (for win32) */
2527         out       = fopen(file_name, "wb");
2528         obstack_free(&obst, file_name);
2529
2530         if (out == NULL) {
2531                 fprintf(stderr, "Couldn't open '%s': %s\n", file_name, strerror(errno));
2532                 return;
2533         }
2534
2535         func(out, graph);
2536         fclose(out);
2537 }
2538
2539 void dump_ir_prog_ext(ir_prog_dump_func func, const char *suffix)
2540 {
2541         char *file_name;
2542         FILE *out;
2543
2544         add_dump_path();
2545
2546         obstack_printf(&obst, "%02u", irp->dump_nr++);
2547         if (suffix != NULL) {
2548                 if (suffix[0] != '.')
2549                         obstack_1grow(&obst, '-');
2550                 add_string_escaped(suffix);
2551         }
2552         obstack_1grow(&obst, '\0');
2553
2554         file_name = (char*)obstack_finish(&obst);
2555         out       = fopen(file_name, "wb");
2556         obstack_free(&obst, file_name);
2557
2558         if (out == NULL) {
2559                 fprintf(stderr, "Couldn't open '%s': %s\n", file_name, strerror(errno));
2560                 return;
2561         }
2562         func(out);
2563         fclose(out);
2564 }
2565
2566 void dump_ir_graph(ir_graph *graph, const char *suffix)
2567 {
2568         char buf[256];
2569
2570         snprintf(buf, sizeof(buf), "%s.vcg", suffix);
2571         dump_ir_graph_ext(dump_ir_graph_file, graph, buf);
2572 }
2573
2574 void dump_all_ir_graphs(const char *suffix)
2575 {
2576         size_t i, n_irgs = get_irp_n_irgs();
2577
2578         for (i = 0; i < n_irgs; ++i) {
2579                 ir_graph *irg = get_irp_irg(i);
2580                 dump_ir_graph(irg, suffix);
2581         }
2582 }
2583
2584 typedef struct pass_t {
2585         ir_prog_pass_t pass;
2586         char           suffix[1];
2587 } pass_t;
2588
2589 /**
2590  * Wrapper around dump_all_ir_graphs().
2591  */
2592 static int dump_all_ir_graphs_wrapper(ir_prog *irp, void *context)
2593 {
2594         pass_t *pass = (pass_t*)context;
2595
2596         (void)irp;
2597         dump_all_ir_graphs(pass->suffix);
2598         return 0;
2599 }
2600
2601 ir_prog_pass_t *dump_all_ir_graph_pass(const char *name, const char *suffix)
2602 {
2603         size_t  len  = strlen(suffix) + 1;
2604         pass_t *pass = XMALLOCF(pass_t, suffix, len);
2605         ir_prog_pass_t *res  = def_prog_pass_constructor(
2606                 &pass->pass, name ? name : "dump_all_graphs", dump_all_ir_graphs_wrapper);
2607
2608         /* this pass does not change anything, so neither dump nor verify is needed. */
2609         res->dump_irprog   = ir_prog_no_dump;
2610         res->verify_irprog = ir_prog_no_verify;
2611
2612         memcpy(pass->suffix, suffix, len);
2613
2614         return res;
2615 }