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