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