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