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