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