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