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