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