Added additional dominator information dumping
[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-2003 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 "irnode_t.h"
27 #include "irgraph_t.h"
28 #include "irprog_t.h"
29 #include "entity_t.h"
30 #include "irop_t.h"
31
32 #include "irdump_t.h"
33
34 #include "irgwalk.h"
35 #include "typewalk.h"
36 #include "tv_t.h"
37 #include "type_or_entity.h"
38 #include "irouts.h"
39 #include "irdom.h"
40 #include "irloop.h"
41 #include "callgraph.h"
42
43 #include "irvrfy.h"
44
45 #include "panic.h"
46 #include "array.h"
47 #include "pmap.h"
48 #include "eset.h"
49 #include "pset.h"
50
51 #if DO_HEAPANALYSIS
52 extern void dump_irn_chi_term(FILE *FL, ir_node *n);
53 extern void dump_irn_state(FILE *FL, ir_node *n);
54 extern int  get_opt_dump_abstvals(void);
55 typedef unsigned long SeqNo;
56 extern SeqNo get_Block_seqno(ir_node *n);
57 #endif
58
59 /* basis for a color range for vcg */
60 static int n_colors   = 0;
61 static int base_color = 0;
62
63 #define ERROR_TXT       "<ERROR>"
64
65 /**
66  * returns the name of a mode or <ERROR> if mode is NOT a mode object.
67  * in the later case, sets bad
68  */
69 const char *get_mode_name_ex(ir_mode *mode, int *bad)
70 {
71   if (is_mode(mode))
72     return get_mode_name(mode);
73   *bad |= 1;
74   return ERROR_TXT;
75 }
76
77 /**
78  * returns the name of a type or <ERROR> if mode is NOT a mode object.
79  * in the later case, sets bad
80  */
81 const char *get_type_name_ex(type *tp, int *bad)
82 {
83   if (is_type(tp))
84     return get_type_name(tp);
85   *bad |= 1;
86   return ERROR_TXT;
87 }
88
89 /**
90  * prints the edge from a type S to a type T with additional info fmt, ...
91  * to the file F
92  */
93 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
94 {
95   va_list ap;
96
97   va_start(ap, fmt);
98   fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
99   fprintf(F, " targetname: "); PRINT_TYPEID(T);
100   vfprintf(F, fmt, ap);
101   fprintf(F,"}\n");
102   va_end(ap);
103 }
104
105 /**
106  * prints the edge from a type T to an entity E with additional info fmt, ...
107  * to the file F
108  */
109 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
110 {
111   va_list ap;
112
113   va_start(ap, fmt);
114   fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
115   fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
116   vfprintf(F, fmt, ap);
117   fprintf(F, "}\n");
118   va_end(ap);
119 }
120
121 /**
122  * prints the edge from an entity E to an entity T with additional info fmt, ...
123  * to the file F
124  */
125 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
126 {
127   va_list ap;
128
129   va_start(ap, fmt);
130   if (backedge)
131     fprintf(F, "backedge: { sourcename: \"");
132    else
133     fprintf(F, "edge: { sourcename: \"");
134   PRINT_ENTID(E);
135   fprintf(F, "\" targetname: \""); PRINT_ENTID(T);  fprintf(F, "\"");
136   vfprintf(F, fmt, ap);
137   fprintf(F, "}\n");
138   va_end(ap);
139 }
140
141 /**
142  * prints the edge from an entity E to a type T with additional info fmt, ...
143  * to the file F
144  */
145 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
146 {
147   va_list ap;
148
149   va_start(ap, fmt);
150   fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
151   fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
152   vfprintf(F, fmt, ap);
153   fprintf(F,"}\n");
154   va_end(ap);
155 }
156
157 /**
158  * prints the edge from a node N to a type T with additional info fmt, ...
159  * to the file F
160  */
161 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
162 {
163   va_list ap;
164
165   va_start(ap, fmt);
166   fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
167   fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
168   vfprintf(F, fmt, ap);
169   fprintf(F,"}\n");
170   va_end(ap);
171 }
172
173 /**
174  * prints the edge from a node N to an entity E with additional info fmt, ...
175  * to the file F
176  */
177 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
178 {
179   va_list ap;
180
181   va_start(ap, fmt);
182   fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
183   fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
184   fprintf(F, "\"");
185   vfprintf(F, fmt, ap);
186   fprintf(F,"}\n");
187   va_end(ap);
188 }
189
190 /**
191  * prints the edge from an entity E to a node N with additional info fmt, ...
192  * to the file F
193  */
194 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
195 {
196   va_list ap;
197
198   va_start(ap, fmt);
199   fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
200   fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
201   vfprintf(F, fmt, ap);
202   fprintf(F,"}\n");
203   va_end(ap);
204 }
205
206 /**
207  * prints the edge from a type E to an enumeration item item with additional info fmt, ...
208  * to the file F
209  */
210 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
211 {
212   va_list ap;
213
214   va_start(ap, fmt);
215   fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
216   fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
217   vfprintf(F, fmt, ap);
218   fprintf(F,"}\n");
219   va_end(ap);
220 }
221
222 /*-----------------------------------------------------------------*/
223 /* global and ahead declarations                                   */
224 /*-----------------------------------------------------------------*/
225
226 static void dump_whole_node(ir_node *n, void *env);
227 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
228
229 /*-----------------------------------------------------------------*/
230 /* Helper functions.                                                */
231 /*-----------------------------------------------------------------*/
232
233 /**
234  * This map is used as a private link attr to be able to call dumper
235  * anywhere without destroying link fields.
236  */
237 static pmap *irdump_link_map = NULL;
238
239 /** Creates the link attribut map. */
240 static void init_irdump(void) {
241   /* We need a new, empty map. */
242   if (irdump_link_map) pmap_destroy(irdump_link_map);
243   irdump_link_map = pmap_create();
244 }
245
246 /**
247  * Returns the private link field.
248  */
249 static void *ird_get_irn_link(ir_node *n) {
250   void *res = NULL;
251   if (!irdump_link_map) return NULL;
252
253   if (pmap_contains(irdump_link_map, (void *)n))
254     res = pmap_get(irdump_link_map, (void *)n);
255   return res;
256 }
257
258 /**
259  * Sets the private link field.
260  */
261 static void ird_set_irn_link(ir_node *n, void *x) {
262   if (!irdump_link_map) init_irdump();
263   pmap_insert(irdump_link_map, (void *)n, x);
264 }
265
266 /**
267  * Gets the private link field of an irg.
268  */
269 static void *ird_get_irg_link(ir_graph *irg) {
270   void *res = NULL;
271   if (!irdump_link_map) return NULL;
272
273   if (pmap_contains(irdump_link_map, (void *)irg))
274     res = pmap_get(irdump_link_map, (void *)irg);
275   return res;
276 }
277
278 /**
279  * Sets the private link field of an irg.
280  */
281 static void ird_set_irg_link(ir_graph *irg, void *x) {
282   if (!irdump_link_map) init_irdump();
283   pmap_insert(irdump_link_map, (void *)irg, x);
284 }
285
286 /**
287  * Walker, clears tzhe private link field
288  */
289 static void clear_link(ir_node * node, void * env) {
290   ird_set_irn_link(node, NULL);
291 }
292
293 /**
294  * If the entity has a ld_name, returns it, else returns the name of the entity.
295  */
296 const char *get_ent_dump_name(entity *ent) {
297   if (!ent)
298     return "<NULL entity>";
299   /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
300   if (ent->ld_name) return get_id_str(ent->ld_name);
301   return get_id_str(ent->name);
302 }
303
304 /* Returns the name of an IRG. */
305 const char *get_irg_dump_name(ir_graph *irg) {
306   /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
307   entity *ent = get_irg_entity(irg);
308   return get_ent_dump_name(ent);
309 }
310
311 /**
312  * Returns non-zero if a node is in floating state.
313  */
314 static int node_floats(ir_node *n) {
315   return ((get_irn_pinned(n) == op_pin_state_floats) &&
316       (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
317 }
318
319 /**
320  * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
321  */
322 static void collect_node(ir_node * node, void *env) {
323   if (is_Block(node)
324       || node_floats(node)
325       || get_irn_op(node) == op_Bad
326       || get_irn_op(node) == op_Unknown
327       || get_irn_op(node) == op_NoMem) {
328     ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
329     if (!arr) arr = NEW_ARR_F(ir_node *, 0);
330     ARR_APP1(ir_node *, arr, node);
331     ird_set_irg_link(get_irn_irg(node), arr);    /* arr is an l-value, APP_ARR might change it! */
332   } else {
333     ir_node * block = get_nodes_block(node);
334
335     if (is_Bad(block)) {
336       /* this node is in a Bad block, so we must place it into the graph's list */
337       ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
338       if (!arr) arr = NEW_ARR_F(ir_node *, 0);
339       ARR_APP1(ir_node *, arr, node);
340       ird_set_irg_link(get_irn_irg(node), arr);    /* arr is an l-value, APP_ARR might change it! */
341     }
342     else {
343       ird_set_irn_link(node, ird_get_irn_link(block));
344       ird_set_irn_link(block, node);
345     }
346   }
347 }
348
349 /** Construct lists to walk ir block-wise.
350  *
351  * Collects all blocks, nodes not op_pin_state_pinned,
352  * Bad, NoMem and Unknown into a flexible array in link field of
353  * irg they belong to.  Sets the irg link field to NULL in all
354  * graphs not visited.
355  * Free the list with DEL_ARR_F().
356  */
357 static ir_node ** construct_block_lists(ir_graph *irg) {
358   int i, rem_view = get_interprocedural_view();
359   ir_graph *rem = current_ir_graph;
360   current_ir_graph = irg;
361
362   for (i = 0; i < get_irp_n_irgs(); i++)
363     ird_set_irg_link(get_irp_irg(i), NULL);
364
365   irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
366
367   /* Collect also EndReg and EndExcept. We do not want to change the walker. */
368   set_interprocedural_view(false);
369
370   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
371   irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
372   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
373   irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
374
375   set_interprocedural_view(rem_view);
376
377   current_ir_graph = rem;
378   return ird_get_irg_link(irg);
379 }
380
381 /*******************************************************************/
382 /* flags to steer output                                           */
383 /*******************************************************************/
384
385 /** Dump only irgs with names start with this string */
386 const char *dump_file_filter = "";
387
388 /** A compiler option to turn off edge labels */
389 static int edge_label = 1;
390 /** A compiler option to turn off dumping values of constant entities */
391 static int const_entities = 1;
392 /** A compiler option to dump the keep alive edges */
393 static int dump_keepalive = 0;
394 /** Compiler options to dump analysis information in dump_ir_graph */
395 int dump_out_edge_flag = 0;
396 int dump_dominator_information_flag = 0;
397 int dump_loop_information_flag = 0;
398 int dump_backedge_information_flag = 1;
399 int dump_const_local = 0;
400 bool opt_dump_analysed_type_info = 1;
401 bool opt_dump_pointer_values_to_info = 0;  /* default off: for test compares!! */
402
403 static const char *overrule_nodecolor = NULL;
404
405 /** The vcg attribute hook. */
406 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
407
408 /* set the hook */
409 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook)
410 {
411   dump_node_vcgattr_hook = hook;
412 }
413
414 INLINE bool get_opt_dump_const_local(void) {
415   if (!dump_out_edge_flag && !dump_loop_information_flag)
416     return dump_const_local;
417   else
418     return false;
419 }
420
421 void only_dump_method_with_name(ident *name) {
422   dump_file_filter = get_id_str(name);
423 }
424
425
426 /* To turn off display of edge labels.  Edge labels offen cause xvcg to
427    abort with a segmentation fault. */
428 void turn_off_edge_labels(void) {
429   edge_label = 0;
430 }
431
432 void dump_consts_local(bool b) {
433   dump_const_local = b;
434 }
435
436 void dump_constant_entity_values(bool b) {
437   const_entities = b;
438 }
439
440 void dump_keepalive_edges(bool b) {
441   dump_keepalive = b;
442 }
443
444 bool get_opt_dump_keepalive_edges(void) {
445   return dump_keepalive;
446 }
447
448 void dump_out_edges(bool b) {
449   dump_out_edge_flag = b;
450 }
451
452 void dump_dominator_information(bool b) {
453   dump_dominator_information_flag = b;
454 }
455
456 void dump_loop_information(bool b) {
457   dump_loop_information_flag = b;
458 }
459
460 void dump_backedge_information(bool b) {
461   dump_backedge_information_flag = b;
462 }
463
464 /* Dump the information of type field specified in ana/irtypeinfo.h.
465  * If the flag is set, the type name is output in [] in the node label,
466  * else it is output as info.
467  */
468 void dump_analysed_type_info(bool b) {
469   opt_dump_analysed_type_info = b;
470 }
471
472 void dump_pointer_values_to_info(bool b) {
473   opt_dump_pointer_values_to_info = b;
474 }
475
476 /*-----------------------------------------------------------------*/
477 /* Routines to dump information about a single ir node.            */
478 /*-----------------------------------------------------------------*/
479
480 /*
481  * dump the name of a node n to the File F.
482  */
483 int
484 dump_node_opcode(FILE *F, ir_node *n)
485 {
486   int bad = 0;
487
488   switch(get_irn_opcode(n)) {
489
490   case iro_Const: {
491     int res;
492     char buf[1024];
493     res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
494     assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
495     fprintf(F, buf);
496   } break;
497
498   case iro_SymConst: {
499     if (get_SymConst_kind(n) == symconst_addr_name) {
500       /* don't use get_SymConst_ptr_info as it mangles the name. */
501       fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
502     } else if (get_SymConst_kind(n) == symconst_addr_ent) {
503       assert(get_SymConst_entity(n));
504       assert(is_entity(get_SymConst_entity(n)));
505       fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
506     } else {
507       assert(get_kind(get_SymConst_type(n)) == k_type);
508       assert(get_type_ident(get_SymConst_type(n)));
509       fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
510       if (get_SymConst_kind(n) == symconst_type_tag)
511         fprintf (F, "tag");
512       else
513         fprintf (F, "size");
514     }
515   } break;
516
517   case iro_Filter: {
518     if (!get_interprocedural_view())
519       fprintf(F, "Proj'");
520     else
521       goto default_case;
522   } break;
523
524   case iro_Proj: {
525     ir_node *pred = get_Proj_pred(n);
526
527     if (get_irn_opcode(pred) == iro_Cond
528         && get_Proj_proj(n) == get_Cond_defaultProj(pred)
529         && get_irn_mode(get_Cond_selector(pred)) != mode_b)
530       fprintf (F, "defProj");
531 /*
532  *   else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
533  *     fprintf (F, "Arg");
534  */
535     else
536       goto default_case;
537   } break;
538   case iro_Start:
539   case iro_End:
540   case iro_EndExcept:
541   case iro_EndReg: {
542     if (get_interprocedural_view()) {
543       fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
544       break;
545     } else
546       goto default_case;
547   }
548   case iro_CallBegin: {
549     ir_node *addr = get_CallBegin_ptr(n);
550     entity *ent = NULL;
551     if (get_irn_op(addr) == op_Sel)
552       ent = get_Sel_entity(addr);
553     else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
554       ent = get_SymConst_entity(addr);
555     fprintf (F, "%s", get_irn_opname(n));
556     if (ent) fprintf (F, " %s", get_entity_name(ent));
557     break;
558   }
559   case iro_Load:
560     fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
561     break;
562
563 default_case:
564   default: {
565     fprintf (F, "%s", get_irn_opname(n));
566   }
567
568   }  /* end switch */
569   return bad;
570 }
571
572 /**
573  * Dump the mode of a node n to a file F.
574  * Ignore modes that are "always known".
575  */
576 static INLINE int
577 dump_node_mode(FILE *F, ir_node *n)
578 {
579   int bad = 0;
580   opcode iro = get_irn_opcode(n);
581
582   switch (iro) {
583     case iro_SymConst:
584     case iro_Sel:
585     case iro_End:
586     case iro_Return:
587     case iro_Free:
588     case iro_Sync:
589     case iro_Jmp:
590     case iro_NoMem:
591       break;
592     default: {
593       ir_mode *mode = get_irn_mode(n);
594
595       if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
596           (mode != mode_T || iro == iro_Proj))
597         fprintf(F, "%s", get_mode_name_ex(mode, &bad));
598     }
599   }
600
601   return bad;
602 }
603
604 /**
605  * Dump the tpe of a node n to a file F if it's known.
606  */
607 static int dump_node_typeinfo(FILE *F, ir_node *n) {
608   int bad = 0;
609
610   if (opt_dump_analysed_type_info) {
611     if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent  ||
612         get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
613       type *tp = get_irn_typeinfo_type(n);
614       if (tp != firm_none_type)
615         fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
616       else
617         fprintf(F, " []");
618     }
619   }
620   return bad;
621 }
622
623 /**
624  * Dump addinional node attributes of some nodes to a file F.
625  */
626 static INLINE int
627 dump_node_nodeattr(FILE *F, ir_node *n)
628 {
629   int bad = 0;
630
631   switch (get_irn_opcode(n)) {
632   case iro_Start:
633     if (false && get_interprocedural_view()) {
634       fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
635     }
636     break;
637   case iro_Proj:
638     if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
639       fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
640     } else {
641       fprintf (F, "%ld", get_Proj_proj(n));
642     }
643     break;
644   case iro_Filter:
645     fprintf (F, "%ld", get_Filter_proj(n));
646     break;
647   case iro_Sel:
648     fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
649     break;
650   case iro_Cast:
651     fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
652     break;
653   case iro_Confirm:
654     fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
655     break;
656
657   default:
658     ;
659   } /* end switch */
660
661   return bad;
662 }
663
664 /**
665  * dumps the attributes of a node n into the file F.
666  * Currently this is only the color of a node.
667  */
668 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
669 {
670   ir_node *n;
671
672   if (bad) {
673     fprintf(F, "color: red");
674     return;
675   }
676
677   if (dump_node_vcgattr_hook)
678     if (dump_node_vcgattr_hook(F, node, local))
679       return;
680
681   n = local ? local : node;
682
683   switch (get_irn_opcode(n)) {
684   case iro_Start:
685   case iro_EndReg:
686     /* fall through */
687   case iro_EndExcept:
688     /* fall through */
689   case iro_End:
690     fprintf (F, "color: blue");
691     break;
692   case iro_Block:
693     if (is_Block_dead(n))
694       fprintf (F, "color: lightred");
695     else
696       fprintf (F, "color: lightyellow");
697     break;
698   case iro_Phi:
699     fprintf (F, "color: green");
700     break;
701   case iro_Const:
702   case iro_Proj:
703   case iro_Filter:
704   case iro_Tuple:
705     fprintf (F, "color: yellow");
706     break;
707   default:
708     PRINT_DEFAULT_NODE_ATTR;
709   }
710
711   if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
712 }
713
714
715 /**
716  * Dump the node information of a node n to a file F.
717  */
718 static INLINE int dump_node_info(FILE *F, ir_node *n)
719 { int bad = 0;
720   fprintf (F, " info1: \"");
721   bad = dump_irnode_to_file(F, n);
722   fprintf(F, "\"\n");
723   return bad;
724 }
725
726 /**
727  * checks wheater a node is "constant-like", ie can be treated "block-less"
728  */
729 static INLINE
730 bool is_constlike_node(ir_node *n) {
731   ir_op *op = get_irn_op(n);
732   return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
733 }
734
735
736 /** outputs the predecessors of n, that are constants, local.  I.e.,
737    generates a copy of the constant predecessors for each node called with. */
738 static void dump_const_node_local(FILE *F, ir_node *n) {
739   int i;
740   if (!get_opt_dump_const_local()) return;
741
742   /* Use visited flag to avoid outputting nodes twice.
743      initialize it first. */
744   for (i = 0; i < get_irn_arity(n); i++) {
745     ir_node *con = get_irn_n(n, i);
746     if (is_constlike_node(con)) {
747       set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
748     }
749   }
750
751   for (i = 0; i < get_irn_arity(n); i++) {
752     ir_node *con = get_irn_n(n, i);
753     if (is_constlike_node(con) && irn_not_visited(con)) {
754       int bad = 0;
755
756       mark_irn_visited(con);
757       /* Generate a new name for the node by appending the names of
758          n and const. */
759       fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
760       fprintf(F, " label: \"");
761       bad |= dump_node_opcode(F, con);
762       bad |= dump_node_mode(F, con);
763       bad |= dump_node_typeinfo(F, con);
764       fprintf (F, " ");
765       bad |= dump_node_nodeattr(F, con);
766       fprintf(F, " %ld", get_irn_node_nr(con));
767       fprintf(F, "\" ");
768       bad |= dump_node_info(F, con);
769       dump_node_vcgattr(F, n, con, bad);
770       fprintf(F, "}\n");
771     }
772   }
773 }
774
775 /** If the block of an edge is a const_like node, dump it local with an edge */
776 static void dump_const_block_local(FILE *F, ir_node *n) {
777   ir_node *blk;
778
779   if (!get_opt_dump_const_local()) return;
780
781   blk = get_nodes_block(n);
782   if (is_constlike_node(blk)) {
783     int bad = 0;
784
785     /* Generate a new name for the node by appending the names of
786        n and blk. */
787     fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
788     fprintf(F, "\" label: \"");
789     bad |= dump_node_opcode(F, blk);
790     bad |= dump_node_mode(F, blk);
791     bad |= dump_node_typeinfo(F, blk);
792     fprintf (F, " ");
793     bad |= dump_node_nodeattr(F, blk);
794     fprintf(F, " %ld", get_irn_node_nr(blk));
795     fprintf(F, "\" ");
796     bad |= dump_node_info(F, blk);
797     dump_node_vcgattr(F, n, blk, bad);
798     fprintf(F, "}\n");
799
800     fprintf (F, "edge: { sourcename: \"");
801     PRINT_NODEID(n);
802     fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
803     fprintf (F, "\" "   BLOCK_EDGE_ATTR "}\n");
804   }
805 }
806
807 /**
808  * prints the error message of a node to a file F as info2.
809  */
810 static void INLINE print_node_error(FILE *F, const char *err_msg)
811 {
812   if (! err_msg)
813     return;
814
815   fprintf (F, " info2: \"%s\"", err_msg);
816 }
817
818 /**
819  * Dump a node
820  */
821 static void dump_node(FILE *F, ir_node *n)
822 {
823   int bad = 0;
824   const char *p;
825
826   if (get_opt_dump_const_local() && is_constlike_node(n))
827     return;
828
829   /* dump this node */
830   fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
831
832   bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
833   bad |= dump_node_opcode(F, n);
834   bad |= dump_node_mode(F, n);
835   bad |= dump_node_typeinfo(F, n);
836   fprintf(F, " ");
837   bad |= dump_node_nodeattr(F, n);
838   fprintf(F, " %ld", get_irn_node_nr(n));
839   fprintf(F, "\" ");
840   bad |= dump_node_info(F, n);
841   print_node_error(F, p);
842   dump_node_vcgattr(F, n, NULL, bad);
843   fprintf(F, "}\n");
844   dump_const_node_local(F, n);
845 #if DO_HEAPANALYSIS
846   dump_irn_chi_term(F, n);
847   dump_irn_state(F, n);
848 #endif
849 }
850
851 /** dump the edge to the block this node belongs to */
852 static void
853 dump_ir_block_edge(FILE *F, ir_node *n)  {
854   if (get_opt_dump_const_local() && is_constlike_node(n)) return;
855   if (is_no_Block(n)) {
856     ir_node *block = get_nodes_block(n);
857
858     if (get_opt_dump_const_local() && is_constlike_node(block)) {
859       dump_const_block_local(F, n);
860     }
861     else {
862       fprintf (F, "edge: { sourcename: \"");
863       PRINT_NODEID(n);
864       fprintf (F, "\" targetname: ");
865       fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
866       fprintf (F, " "   BLOCK_EDGE_ATTR "}\n");
867     }
868   }
869 }
870
871 static void
872 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
873   if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
874     fprintf (F, INTRA_DATA_EDGE_ATTR);
875   else
876     fprintf (F, INTER_DATA_EDGE_ATTR);
877 }
878
879 static void
880 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
881   if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
882     fprintf (F, INTRA_MEM_EDGE_ATTR);
883   else
884     fprintf (F, INTER_MEM_EDGE_ATTR);
885 }
886
887 static void
888 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
889   assert(from);
890
891   if (dump_backedge_information_flag && is_backedge(from, to))
892     fprintf (F, BACK_EDGE_ATTR);
893
894   switch (get_irn_opcode(from)) {
895   case iro_Block:
896     fprintf (F, CF_EDGE_ATTR);
897     break;
898   case iro_Start:   break;
899   case iro_End:
900     if (to >= 0) {
901       if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
902     fprintf (F, CF_EDGE_ATTR);
903       if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
904     fprintf (F, INTER_MEM_EDGE_ATTR);
905     }
906     break;
907   case iro_EndReg:
908   case iro_EndExcept:
909   case iro_Jmp:
910   case iro_Break:
911   case iro_Cond:
912     print_data_edge_vcgattr(F, from, to);
913     break;
914   case iro_Return:
915   case iro_Raise:
916     if (to == 0)
917       print_mem_edge_vcgattr(F, from, to);
918     else
919       print_data_edge_vcgattr(F, from, to);
920     break;
921   case iro_Const:
922   case iro_SymConst:
923     print_data_edge_vcgattr(F, from, to);
924     break;
925   case iro_Sel:
926   case iro_Call:
927     if (to == 0)
928       print_mem_edge_vcgattr(F, from, to);
929     else
930       print_data_edge_vcgattr(F, from, to);
931     break;
932   case iro_CallBegin:
933   case iro_Add:
934   case iro_Sub:
935   case iro_Minus:
936   case iro_Mul:
937     print_data_edge_vcgattr(F, from, to);
938     break;
939   case iro_Quot:
940   case iro_DivMod:
941   case iro_Div:
942   case iro_Mod:
943     if (to == 0)
944       print_mem_edge_vcgattr(F, from, to);
945     else
946       print_data_edge_vcgattr(F, from, to);
947     break;
948   case iro_Abs:
949   case iro_And:
950   case iro_Or:
951   case iro_Eor:
952   case iro_Shl:
953   case iro_Shr:
954   case iro_Shrs:
955   case iro_Rot:
956   case iro_Cmp:
957   case iro_Conv:
958       print_data_edge_vcgattr(F, from, to);
959     break;
960   case iro_Phi:
961     if (get_irn_modecode(from) == irm_M)
962       fprintf (F, INTER_MEM_EDGE_ATTR);
963     else
964       print_data_edge_vcgattr(F, from, to);
965     break;
966   case iro_Load:
967   case iro_Store:
968   case iro_Alloc:
969   case iro_Free:
970     if (to == 0)
971       print_mem_edge_vcgattr(F, from, to);
972     else
973       print_data_edge_vcgattr(F, from, to);
974     break;
975   case iro_Sync:
976     print_mem_edge_vcgattr(F, from, to);
977     break;
978   case iro_Tuple:  break;
979   case iro_Proj:
980   case iro_Filter:
981     switch (get_irn_modecode(from)) {
982     case irm_X:
983       fprintf (F, CF_EDGE_ATTR);
984       break;
985     case irm_M:
986       fprintf (F, INTER_MEM_EDGE_ATTR);
987       break;
988     default:
989       print_data_edge_vcgattr(F, from, to);
990       break;
991     }
992     break;
993   case iro_Bad:     break;
994   case iro_Unknown: break;
995   case iro_Id:
996     switch (get_irn_modecode(from)) {
997     case irm_M:
998       fprintf (F, INTRA_MEM_EDGE_ATTR);
999       break;
1000     case irm_X:
1001       fprintf (F, CF_EDGE_ATTR);
1002       break;
1003     default:
1004       print_data_edge_vcgattr(F, from, to);
1005       break;
1006     } break;
1007   default:
1008     ;
1009   }
1010 }
1011
1012 /* dump edges to our inputs */
1013 static void
1014 dump_ir_data_edges(FILE *F, ir_node *n)  {
1015   int i;
1016   unsigned long visited = get_irn_visited(n);
1017
1018   if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1019     return;
1020
1021   for (i = 0; i < get_irn_arity(n); i++) {
1022     ir_node * pred = get_irn_n(n, i);
1023     assert(pred);
1024
1025     if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1026       continue; /* pred not dumped */
1027
1028     if (dump_backedge_information_flag && is_backedge(n, i))
1029       fprintf (F, "backedge: {sourcename: \"");
1030     else
1031       fprintf (F, "edge: {sourcename: \"");
1032     PRINT_NODEID(n);
1033     fprintf (F, "\" targetname: ");
1034     if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1035       PRINT_CONSTID(n, pred);
1036     } else {
1037       fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1038     }
1039     fprintf (F, " label: \"%d\" ", i);
1040     print_edge_vcgattr(F, n, i);
1041     fprintf (F, "}\n");
1042   }
1043 }
1044
1045 /** Dumps a node and its edges but not the block edge
1046  */
1047 static INLINE void
1048 dump_node_wo_blockedge (ir_node *n, void *env) {
1049   FILE *F = env;
1050   dump_node(F, n);
1051   dump_ir_data_edges(F, n);
1052 }
1053
1054 /** Dumps a node and its edges.
1055  */
1056 static void
1057 dump_whole_node (ir_node *n, void *env) {
1058   FILE *F = env;
1059   dump_node_wo_blockedge(n, env);
1060   if (!node_floats(n)) dump_ir_block_edge(F, n);
1061 }
1062
1063 static void
1064 dump_const_node(ir_node *n, void *env) {
1065   if (is_Block(n)) return;
1066   dump_node_wo_blockedge(n, env);
1067 }
1068
1069 /***********************************************************************/
1070 /* the following routines dump the nodes/irgs bracketed to graphs.     */
1071 /***********************************************************************/
1072
1073 /** Dumps a constant expression as entity initializer, array bound ...
1074  */
1075 static void dump_const_expression(FILE *F, ir_node *value) {
1076   ir_graph *rem = current_ir_graph;
1077   int rem_dump_const_local = dump_const_local;
1078   dump_const_local = 0;
1079   current_ir_graph = get_const_code_irg();
1080   irg_walk(value, dump_const_node, NULL, F);
1081   /* Decrease visited flag so that we walk with the same flag for the next
1082      expresssion.  This guarantees that we don't dump the same node twice,
1083      as for const expressions cse is performed to save memory. */
1084   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1085   current_ir_graph = rem;
1086   dump_const_local = rem_dump_const_local;
1087 }
1088
1089 /** Dump a block as graph containing its nodes.
1090  *
1091  *  Expects to find nodes belonging to the block as list in its
1092  *  link field.
1093  *  Dumps the edges of all nodes including itself. */
1094 static void
1095 dump_whole_block(FILE *F, ir_node *block) {
1096   ir_node *node;
1097   assert(is_Block(block));
1098
1099   fprintf(F, "graph: { title: \"");
1100   PRINT_NODEID(block);
1101   fprintf(F, "\"  label: \"");
1102   dump_node_opcode(F, block);
1103   fprintf (F, " %ld", get_irn_node_nr(block));
1104 #if DO_HEAPANALYSIS
1105   if (get_opt_dump_abstvals())
1106     fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1107 #endif
1108   fprintf(F, "\" status:clustered color:%s \n",
1109        get_Block_matured(block) ? "yellow" : "red");
1110
1111   /* dump the blocks edges */
1112   dump_ir_data_edges(F, block);
1113
1114   /* dump the nodes that go into the block */
1115   for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1116     dump_node(F, node);
1117     dump_ir_data_edges(F, node);
1118   }
1119
1120   /* Close the vcg information for the block */
1121   fprintf(F, "}\n");
1122   dump_const_node_local(F, block);
1123 #if DO_HEAPANALYSIS
1124   dump_irn_chi_term(F, block);
1125 #endif
1126   fprintf(F, "\n");
1127 }
1128
1129 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1130  *  The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1131 static void
1132 dump_block_graph(FILE *F, ir_graph *irg) {
1133   int i;
1134   ir_graph *rem = current_ir_graph;
1135   ir_node **arr = ird_get_irg_link(irg);
1136   current_ir_graph = irg;
1137
1138   for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1139     ir_node * node = arr[i];
1140     if (is_Block(node)) {
1141       /* Dumps the block and all the nodes in the block, which are to
1142          be found in Block->link. */
1143       dump_whole_block(F, node);
1144     } else {
1145       /* Nodes that are not in a Block. */
1146       dump_node(F, node);
1147       if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1148         dump_const_block_local(F, node);
1149       }
1150       dump_ir_data_edges(F, node);
1151     }
1152   }
1153
1154   if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1155     dump_loop_nodes_into_graph(F, irg);
1156
1157   current_ir_graph = rem;
1158 }
1159
1160 /** Dumps an irg as a graph.
1161  *  If interprocedural view edges can point to nodes out of this graph.
1162  */
1163 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1164
1165   fprintf(F, "graph: { title: \"");
1166   PRINT_IRGID(irg);
1167   fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1168       get_ent_dump_name(get_irg_entity(irg)));
1169
1170   dump_block_graph(F, irg);
1171
1172   /* Close the vcg information for the irg */
1173   fprintf(F, "}\n\n");
1174 }
1175
1176 /*******************************************************************/
1177 /* Basic type and entity nodes and edges.                          */
1178 /*******************************************************************/
1179
1180 /** dumps the edges between nodes and their type or entity attributes. */
1181 static void dump_node2type_edges(ir_node *n, void *env)
1182 {
1183   FILE *F = env;
1184   assert(n);
1185
1186   switch (get_irn_opcode(n)) {
1187   case iro_Const :
1188     /* @@@ some consts have an entity */
1189     break;
1190   case iro_SymConst:
1191     if (   (get_SymConst_kind(n) ==symconst_type_tag)
1192        || (get_SymConst_kind(n) ==symconst_size))
1193       {
1194         print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1195       }
1196     break;
1197   case iro_Sel: {
1198       print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1199     } break;
1200   case iro_Call: {
1201       print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1202     } break;
1203   case iro_Alloc: {
1204       print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1205     } break;
1206   case iro_Free: {
1207       print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1208     } break;
1209   case iro_Cast: {
1210       print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1211     } break;
1212   default:
1213     break;
1214   }
1215 }
1216
1217
1218 static int print_type_info(FILE *F, type *tp) {
1219   int bad = 0;
1220
1221   if (get_type_state(tp) == layout_undefined) {
1222     fprintf(F, "state: layout_undefined\n");
1223   } else {
1224     fprintf(F, "state: layout_fixed,\n");
1225   }
1226   if (get_type_mode(tp))
1227     fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1228   fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1229
1230   return bad;
1231 }
1232
1233 static void print_typespecific_info(FILE *F, type *tp) {
1234   switch (get_type_tpop_code(tp)) {
1235   case tpo_class:
1236     {
1237       fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1238     } break;
1239   case tpo_struct:
1240     {
1241     } break;
1242   case tpo_method:
1243     {
1244       fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1245       fprintf(F, "params: %d\n", get_method_n_params(tp));
1246       fprintf(F, "results: %d\n", get_method_n_ress(tp));
1247     } break;
1248   case tpo_union:
1249     {
1250     } break;
1251   case tpo_array:
1252     {
1253     } break;
1254   case tpo_enumeration:
1255     {
1256     } break;
1257   case tpo_pointer:
1258     {
1259     } break;
1260   case tpo_primitive:
1261     {
1262     } break;
1263   default: break;
1264   } /* switch type */
1265 }
1266
1267
1268 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1269   switch (get_type_tpop_code(tp)) {
1270   case tpo_class:
1271     {
1272       if (peculiarity_existent == get_class_peculiarity(tp))
1273     fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1274       else
1275     fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1276     } break;
1277   case tpo_struct:
1278     {
1279       fprintf (F, " " TYPE_METH_NODE_ATTR);
1280     } break;
1281   case tpo_method:
1282     {
1283     } break;
1284   case tpo_union:
1285     {
1286     } break;
1287   case tpo_array:
1288     {
1289     } break;
1290   case tpo_enumeration:
1291     {
1292     } break;
1293   case tpo_pointer:
1294     {
1295     } break;
1296   case tpo_primitive:
1297     {
1298     } break;
1299   default: break;
1300   } /* switch type */
1301 }
1302
1303 static int print_type_node(FILE *F, type *tp)
1304 {
1305   int bad = 0;
1306
1307   fprintf (F, "node: {title: ");
1308   PRINT_TYPEID(tp);
1309   fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1310   fprintf (F, " info1: \"");
1311   bad |= print_type_info(F, tp);
1312   print_typespecific_info(F, tp);
1313   fprintf (F, "\"");
1314   print_typespecific_vcgattr(F, tp);
1315   fprintf (F, "}\n");
1316
1317   return bad;
1318 }
1319
1320 #define X(a)    case a: fprintf(F, #a); break
1321 void dump_entity_node(FILE *F, entity *ent, int color)
1322 {
1323   fprintf (F, "node: {title: \"");
1324   PRINT_ENTID(ent); fprintf(F, "\"");
1325   fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1326   fprintf (F, "label: ");
1327   fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1328   if (color)
1329     fprintf(F, "color: %d", color);
1330   else
1331     fprintf (F, ENTITY_NODE_ATTR);
1332   fprintf (F, "\n info1: \"");
1333
1334   dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1335
1336   fprintf(F, "\"\n}\n");
1337 }
1338 #undef X
1339
1340 static void dump_enum_item(FILE *F, type *tp, int pos)
1341 {
1342   char buf[1024];
1343   ident *id  = get_enumeration_nameid(tp, pos);
1344   tarval *tv = get_enumeration_enum(tp, pos);
1345
1346   tarval_snprintf(buf, sizeof(buf), tv);
1347   fprintf (F, "node: {title: \"");
1348   PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1349   fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1350   fprintf (F, "label: ");
1351   fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1352   fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1353 }
1354
1355 /* dumps a type or entity and it's edges. */
1356 static void
1357 dump_type_info(type_or_ent *tore, void *env) {
1358   FILE *F = env;
1359   int i = 0;  /* to shutup gcc */
1360
1361   /* dump this type or entity */
1362
1363   switch (get_kind(tore)) {
1364   case k_entity:
1365     {
1366       entity *ent = (entity *)tore;
1367       ir_node *value;
1368       /* The node */
1369       dump_entity_node(F, ent, 0);
1370       /* The Edges */
1371       /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
1372       fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1373                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1374       print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1375       if (is_Class_type(get_entity_owner(ent))) {
1376         for(i = 0; i < get_entity_n_overwrites(ent); i++)
1377           print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1378       }
1379       /* attached subgraphs */
1380       if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1381         if (is_atomic_entity(ent)) {
1382           value = get_atomic_ent_value(ent);
1383           if (value) {
1384             print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1385             /* DDMN(value);  $$$ */
1386             dump_const_expression(F, value);
1387           }
1388         }
1389         if (is_compound_entity(ent)) {
1390           for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1391             value = get_compound_ent_value(ent, i);
1392             if (value) {
1393               print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1394               dump_const_expression(F, value);
1395               print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1396               /*
1397               fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1398               ENT_CORR_EDGE_ATTR  "}\n", GET_ENTID(ent),
1399               get_compound_ent_value_member(ent, i), i);
1400               */
1401             }
1402           }
1403         }
1404       }
1405     } break;
1406   case k_type:
1407     {
1408       type *tp = (type *)tore;
1409       print_type_node(F, tp);
1410       /* and now the edges */
1411       switch (get_type_tpop_code(tp)) {
1412       case tpo_class:
1413         {
1414           for (i=0; i < get_class_n_supertypes(tp); i++)
1415             print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1416           for (i=0; i < get_class_n_members(tp); i++)
1417             print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1418         } break;
1419       case tpo_struct:
1420         {
1421           for (i=0; i < get_struct_n_members(tp); i++)
1422             print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1423         } break;
1424       case tpo_method:
1425         {
1426           for (i = 0; i < get_method_n_params(tp); i++)
1427             print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1428           for (i = 0; i < get_method_n_ress(tp); i++)
1429             print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1430         } break;
1431       case tpo_union:
1432         {
1433           for (i = 0; i < get_union_n_members(tp); i++)
1434             print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1435         } break;
1436       case tpo_array:
1437         {
1438           print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1439           print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1440           for (i = 0; i < get_array_n_dimensions(tp); i++) {
1441             ir_node *upper = get_array_upper_bound(tp, i);
1442             ir_node *lower = get_array_lower_bound(tp, i);
1443             print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1444             print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1445             dump_const_expression(F, upper);
1446             dump_const_expression(F, lower);
1447           }
1448
1449         } break;
1450       case tpo_enumeration:
1451         {
1452           for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1453             dump_enum_item(F, tp, i);
1454             print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1455           }
1456         } break;
1457       case tpo_pointer:
1458         {
1459           print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1460         } break;
1461       case tpo_primitive:
1462         {
1463         } break;
1464       default: break;
1465       } /* switch type */
1466     }
1467     break; /* case k_type */
1468   default:
1469     {
1470       printf(" *** irdump,  dump_type_info(l.%i), faulty type.\n", __LINE__);
1471     } break;
1472   } /* switch kind_or_entity */
1473 }
1474
1475 typedef struct _h_env {
1476   int dump_ent;
1477   FILE *f;
1478 } h_env_t;
1479
1480 /** For dumping class hierarchies.
1481  * Dumps a class type node and a superclass edge.
1482  * If env->dump_ent dumps entities of classes and overwrites edges.
1483  */
1484 static void
1485 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1486   h_env_t *env = ctx;
1487   FILE *F = env->f;
1488   int i = 0;  /* to shutup gcc */
1489
1490   /* dump this type or entity */
1491   switch (get_kind(tore)) {
1492   case k_entity: {
1493     entity *ent = (entity *)tore;
1494     if (get_entity_owner(ent) == get_glob_type()) break;
1495     if (!is_Method_type(get_entity_type(ent))) break;  /* GL */
1496     if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1497       /* The node */
1498       dump_entity_node(F, ent, 0);
1499       /* The edges */
1500       print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1501       for(i = 0; i < get_entity_n_overwrites(ent); i++)
1502         print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1503     }
1504   } break; /* case k_entity */
1505   case k_type:
1506     {
1507       type *tp = (type *)tore;
1508       if (tp == get_glob_type()) break;
1509       switch (get_type_tpop_code(tp)) {
1510         case tpo_class: {
1511           print_type_node(F, tp);
1512           /* and now the edges */
1513           for (i=0; i < get_class_n_supertypes(tp); i++)
1514           {
1515               print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1516           }
1517         } break;
1518         default: break;
1519       } /* switch type */
1520     }
1521     break; /* case k_type */
1522   default:
1523     {
1524       printf(" *** irdump,  dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1525     } break;
1526   } /* switch kind_or_entity */
1527 }
1528
1529 /*******************************************************************/
1530 /* dump analysis information that is expressed in graph terms.     */
1531 /*******************************************************************/
1532
1533 /* dump out edges */
1534 static void
1535 dump_out_edge(ir_node *n, void *env) {
1536   FILE *F = env;
1537   int i;
1538   for (i = 0; i < get_irn_n_outs(n); i++) {
1539     assert(get_irn_out(n, i));
1540     fprintf (F, "edge: {sourcename: \"");
1541     PRINT_NODEID(n);
1542     fprintf (F, "\" targetname: \"");
1543     PRINT_NODEID(get_irn_out(n, i));
1544     fprintf (F, "\" color: red linestyle: dashed");
1545     fprintf (F, "}\n");
1546   }
1547 }
1548
1549 static INLINE void
1550 dump_loop_label(FILE *F, ir_loop *loop) {
1551   fprintf (F, "loop %d, %d sons, %d nodes",
1552        get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1553 }
1554
1555 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1556   fprintf (F, " info1: \"");
1557   fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1558 #if DEBUG_libfirm   /* GL @@@ debug analyses */
1559   fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1560 #endif
1561   fprintf (F, "\"");
1562 }
1563
1564 static INLINE void
1565 dump_loop_node(FILE *F, ir_loop *loop) {
1566   fprintf (F, "node: {title: \"");
1567   PRINT_LOOPID(loop);
1568   fprintf (F, "\" label: \"");
1569   dump_loop_label(F, loop);
1570   fprintf (F, "\" ");
1571   dump_loop_info(F, loop);
1572   fprintf (F, "}\n");
1573
1574 }
1575
1576 static INLINE void
1577 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1578   assert(loop);
1579   fprintf (F, "edge: {sourcename: \"");
1580   PRINT_LOOPID(loop);
1581   fprintf (F, "\" targetname: \"");
1582   PRINT_NODEID(get_loop_node(loop, i));
1583   fprintf (F, "\" color: green");
1584   fprintf (F, "}\n");
1585 }
1586
1587 static INLINE void
1588 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1589   assert(loop);
1590   fprintf (F, "edge: {sourcename: \"");
1591   PRINT_LOOPID(loop);
1592   fprintf (F, "\" targetname: \"");
1593   PRINT_LOOPID(get_loop_son(loop, i));
1594   fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1595        get_loop_element_pos(loop, get_loop_son(loop, i)));
1596 }
1597
1598 static
1599 void dump_loops(FILE *F, ir_loop *loop) {
1600   int i;
1601   /* dump this loop node */
1602   dump_loop_node(F, loop);
1603
1604   /* dump edges to nodes in loop -- only if it is a real loop */
1605   if (get_loop_depth(loop) != 0) {
1606     for (i = 0; i < get_loop_n_nodes(loop); i++) {
1607       dump_loop_node_edge(F, loop, i);
1608     }
1609   }
1610   for (i = 0; i < get_loop_n_sons(loop); i++) {
1611     dump_loops(F, get_loop_son(loop, i));
1612     dump_loop_son_edge(F, loop, i);
1613   }
1614 }
1615
1616 static INLINE
1617 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1618   ir_graph *rem = current_ir_graph;
1619   current_ir_graph = irg;
1620
1621   if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1622
1623   current_ir_graph = rem;
1624 }
1625
1626
1627 /**
1628  * dumps the VCG header
1629  */
1630 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1631   char *label;
1632
1633   if (edge_label) {
1634     label = "yes";
1635   } else {
1636     label = "no";
1637   }
1638
1639   if (!orientation) orientation = "bottom_to_top";
1640
1641   /* print header */
1642   fprintf (F,
1643        "graph: { title: \"ir graph of %s\"\n"
1644        "display_edge_labels: %s\n"
1645        "layoutalgorithm: mindepth\n"
1646        "manhattan_edges: yes\n"
1647        "port_sharing: no\n"
1648        "orientation: %s\n"
1649        "classname 1:  \"intrablock Data\"\n"
1650        "classname 16: \"interblock Data\"\n"
1651        "classname 2:  \"Block\"\n"
1652        "classname 13: \"Control Flow\"\n"
1653        "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1654        "classname 14: \"intrablock Memory\"\n"
1655        "classname 17: \"interblock Memory\"\n"
1656        "classname 15: \"Dominators\"\n"
1657        "classname 3:  \"Entity type\"\n"
1658        "classname 4:  \"Entity owner\"\n"
1659        "classname 5:  \"Method Param\"\n"
1660        "classname 6:  \"Method Res\"\n"
1661        "classname 7:  \"Super\"\n"
1662        "classname 8:  \"Union\"\n"
1663        "classname 9:  \"Points-to\"\n"
1664        "classname 10: \"Array Element Type\"\n"
1665        "classname 11: \"Overwrites\"\n"
1666        "classname 12: \"Member\"\n"
1667        "infoname 1: \"Attribute\"\n"
1668        "infoname 2: \"Verification errors\"\n",
1669        name, label, orientation);
1670
1671   /* don't use all, the range is too whith/black. */
1672   n_colors   = 18;
1673   base_color = 105;
1674   fprintf (F,
1675        "colorentry 100:    0   0    0\n"
1676        "colorentry 101:   20   0    0\n"
1677        "colorentry 102:   40   0    0\n"
1678        "colorentry 103:   60   0    0\n"
1679        "colorentry 104:   80   0    0\n"
1680        "colorentry 105:  100   0    0\n"
1681        "colorentry 106:  120   0    0\n"
1682        "colorentry 107:  140   0    0\n"
1683        "colorentry 108:  150   0    0\n"
1684        "colorentry 109:  180   0    0\n"
1685        "colorentry 110:  200   0    0\n"
1686        "colorentry 111:  220   0    0\n"
1687        "colorentry 112:  240   0    0\n"
1688        "colorentry 113:  255   0    0\n"
1689        "colorentry 113:  255  20   20\n"
1690        "colorentry 114:  255  40   40\n"
1691        "colorentry 115:  255  60   60\n"
1692        "colorentry 116:  255  80   80\n"
1693        "colorentry 117:  255 100  100\n"
1694        "colorentry 118:  255 120  120\n"
1695        "colorentry 119:  255 140  140\n"
1696        "colorentry 120:  255 150  150\n"
1697        "colorentry 121:  255 180  180\n"
1698        "colorentry 122:  255 200  200\n"
1699        "colorentry 123:  255 220  220\n"
1700        "colorentry 124:  255 240  240\n"
1701        "colorentry 125:  255 250  250\n"
1702        );
1703
1704   fprintf (F, "\n");        /* a separator */
1705 }
1706
1707 /**
1708  * open a vcg file
1709  *
1710  * @param irg     The graph to be dumped
1711  * @param suffix1 first filename suffix
1712  * @param suffix2 second filename suffix
1713  */
1714 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1715   FILE *F;
1716   const char *nm = get_irg_dump_name(irg);
1717   int len = strlen(nm), i, j;
1718   char *fname;  /* filename to put the vcg information in */
1719
1720   if (!suffix1) suffix1 = "";
1721   if (!suffix2) suffix2 = "";
1722
1723   /* open file for vcg graph */
1724   fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1725
1726   /* strncpy (fname, nm, len); */     /* copy the filename */
1727   j = 0;
1728   for (i = 0; i < len; ++i) {  /* replace '/' in the name: escape by @. */
1729     if (nm[i] == '/') {
1730       fname[j] = '@'; j++; fname[j] = '1'; j++;
1731     } else if (nm[i] == '@') {
1732       fname[j] = '@'; j++; fname[j] = '2'; j++;
1733     } else {
1734       fname[j] = nm[i]; j++;
1735     }
1736   }
1737   fname[j] = '\0';
1738   strcat (fname, suffix1);  /* append file suffix */
1739   strcat (fname, suffix2);  /* append file suffix */
1740   strcat (fname, ".vcg");   /* append the .vcg suffix */
1741
1742   /* vcg really expect only a <CR> at end of line, so
1743    * the "b"inary mode is what you mean (and even needed for Win32)
1744    */
1745   F = fopen (fname, "wb");  /* open file for writing */
1746   if (!F) {
1747     panic("cannot open %s for writing (%m)", fname);  /* not reached */
1748   }
1749   free(fname);
1750
1751   return F;
1752 }
1753
1754 /**
1755  * open a vcg file
1756  *
1757  * @param irg     The graph to be dumped
1758  * @param suffix  filename suffix
1759  */
1760 FILE *vcg_open_name (const char *name, const char *suffix) {
1761   FILE *F;
1762   char *fname;  /* filename to put the vcg information in */
1763   int i, j, len = strlen(name);
1764
1765   if (!suffix) suffix = "";
1766
1767   /** open file for vcg graph */
1768   fname = malloc (len * 2 + 5 + strlen(suffix));
1769   /* strcpy (fname, name);*/    /* copy the filename */
1770   j = 0;
1771   for (i = 0; i < len; ++i) {  /* replace '/' in the name: escape by @. */
1772     if (name[i] == '/') {
1773       fname[j] = '@'; j++; fname[j] = '1'; j++;
1774     } else if (name[i] == '@') {
1775       fname[j] = '@'; j++; fname[j] = '2'; j++;
1776     } else {
1777       fname[j] = name[i]; j++;
1778     }
1779   }
1780   fname[j] = '\0';
1781   strcat (fname, suffix);
1782   strcat (fname, ".vcg");  /* append the .vcg suffix */
1783
1784   /* vcg really expect only a <CR> at end of line, so
1785    * the "b"inary mode is what you mean (and even needed for Win32)
1786    */
1787   F = fopen (fname, "wb");  /* open file for writing */
1788   if (!F) {
1789     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
1790   }
1791   free(fname);
1792
1793   return F;
1794 }
1795
1796 /**
1797  * Dumps the vcg file footer
1798  */
1799 static INLINE void dump_vcg_footer (FILE *F) {
1800   fprintf (F, "}\n");
1801 }
1802
1803 /**
1804  * close the vcg file
1805  */
1806 void vcg_close (FILE *F) {
1807   dump_vcg_footer(F);    /* print footer */
1808   fclose (F);           /* close vcg file */
1809 }
1810
1811 /************************************************************************/
1812 /************************************************************************/
1813 /* Routines that dump all or parts of the firm representation to a file */
1814 /************************************************************************/
1815 /************************************************************************/
1816
1817 /************************************************************************/
1818 /* Dump ir graphs, different formats and additional information.        */
1819 /************************************************************************/
1820
1821 /** Routine to dump a graph, blocks as conventional nodes.  */
1822 void
1823 dump_ir_graph (ir_graph *irg, const char *suffix )
1824 {
1825   FILE *f;
1826   ir_graph *rem;
1827   char *suffix1;
1828   rem = current_ir_graph;
1829
1830   if (strncmp(get_entity_name(get_irg_entity(irg)),
1831           dump_file_filter, strlen(dump_file_filter)) != 0) return;
1832
1833   current_ir_graph = irg;
1834   if (get_interprocedural_view()) suffix1 = "-pure-ip";
1835   else                            suffix1 = "-pure";
1836   f = vcg_open(irg, suffix, suffix1);
1837   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1838
1839   /* walk over the graph */
1840   /* dump_whole_node must be called in post visiting predecessors */
1841   irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1842
1843   /* dump the out edges in a separate walk */
1844   if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1845     irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
1846   }
1847
1848   vcg_close(f);
1849
1850   current_ir_graph = rem;
1851 }
1852
1853
1854 void
1855 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1856 {
1857   FILE *f;
1858   int i;
1859   char *suffix1;
1860
1861   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1862     return;
1863
1864   if (get_interprocedural_view()) suffix1 = "-ip";
1865   else                            suffix1 = "";
1866   f = vcg_open(irg, suffix, suffix1);
1867   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1868
1869   construct_block_lists(irg);
1870
1871   for (i = 0; i < get_irp_n_irgs(); i++) {
1872     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1873     if (arr) {
1874       dump_graph_from_list(f, get_irp_irg(i));
1875       DEL_ARR_F(arr);
1876     }
1877   }
1878
1879   vcg_close(f);
1880 }
1881
1882 /** dumps a graph with type information */
1883 void
1884 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1885 {
1886   FILE *f;
1887   ir_graph *rem = current_ir_graph;
1888   char *suffix1;
1889
1890   /* if a filter is set, dump only the irg's that match the filter */
1891   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1892     return;
1893
1894   current_ir_graph = irg;
1895
1896   if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
1897   else                            suffix1 = "-pure-wtypes";
1898   f = vcg_open(irg,suffix, suffix1);
1899   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1900
1901   /* dump common ir graph */
1902   irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1903   /* dump type info */
1904   type_walk_irg(irg, dump_type_info, NULL, f);
1905   inc_irg_visited(get_const_code_irg());
1906   /* dump edges from graph to type info */
1907   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1908
1909   vcg_close(f);
1910   current_ir_graph = rem;
1911 }
1912
1913 void
1914 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1915 {
1916   FILE *f;
1917   int i;
1918   char *suffix1;
1919   ir_graph *rem = current_ir_graph;
1920
1921   /* if a filter is set, dump only the irg's that match the filter */
1922   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1923     return;
1924
1925   if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
1926   else                            suffix1 = "-wtypes";
1927   f = vcg_open(irg, suffix, suffix1);
1928   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1929
1930   /* dump common blocked ir graph */
1931   construct_block_lists(irg);
1932
1933   for (i = 0; i < get_irp_n_irgs(); i++) {
1934     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1935     if (arr) {
1936       dump_graph_from_list(f, get_irp_irg(i));
1937       DEL_ARR_F(arr);
1938     }
1939   }
1940
1941   /* dump type info */
1942   current_ir_graph = irg;
1943   type_walk_irg(irg, dump_type_info, NULL, f);
1944   inc_irg_visited(get_const_code_irg());
1945
1946   /* dump edges from graph to type info */
1947   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1948
1949   current_ir_graph = rem;
1950   vcg_close(f);
1951 }
1952
1953 /*---------------------------------------------------------------------*/
1954 /* The following routines dump a control flow graph.                   */
1955 /*---------------------------------------------------------------------*/
1956
1957 static void
1958 dump_block_to_cfg(ir_node *block, void *env) {
1959   FILE *F = env;
1960   int i, fl;
1961   ir_node *pred;
1962
1963   if (is_Block(block)) {
1964     /* This is a block. Dump a node for the block. */
1965     fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1966     fprintf (F, "\" label: \"");
1967     if (block == get_irg_start_block(get_irn_irg(block)))
1968       fprintf(F, "Start ");
1969     if (block == get_irg_end_block(get_irn_irg(block)))
1970       fprintf(F, "End ");
1971
1972     fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1973     PRINT_NODEID(block);
1974     fprintf (F, "\" ");
1975     fprintf(F, "info1:\"");
1976     if (dump_dominator_information_flag) {
1977       fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
1978       fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block));
1979       fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block));
1980                 }
1981
1982     /* show arity and possible Bad predecessors of the block */
1983     fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
1984     for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
1985       ir_node *pred = get_Block_cfgpred(block, i);
1986       if (is_Bad(pred)) {
1987     if (! fl)
1988       fprintf(F, "Bad pred at pos: ");
1989     fprintf(F, "%d ", i);
1990     fl = 1;
1991       }
1992     }
1993     if (fl)
1994       fprintf(F, "\n");
1995
1996     fprintf (F, "\"");  /* closing quote of info */
1997
1998     if ((block == get_irg_start_block(get_irn_irg(block))) ||
1999     (block == get_irg_end_block(get_irn_irg(block)))     )
2000       fprintf(F, " color:blue ");
2001     else if (fl)
2002       fprintf(F, " color:yellow ");
2003
2004     fprintf (F, "}\n");
2005     /* Dump the edges */
2006     for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2007       if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2008         pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2009         fprintf (F, "edge: { sourcename: \"");
2010         PRINT_NODEID(block);
2011         fprintf (F, "\" targetname: \"");
2012         PRINT_NODEID(pred);
2013         fprintf (F, "\"}\n");
2014       }
2015
2016     /* Dump dominator edge */
2017     if (dump_dominator_information_flag && get_Block_idom(block)) {
2018       pred = get_Block_idom(block);
2019       fprintf (F, "edge: { sourcename: \"");
2020       PRINT_NODEID(block);
2021       fprintf (F, "\" targetname: \"");
2022       PRINT_NODEID(pred);
2023       fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2024     }
2025   }
2026 }
2027
2028 void
2029 dump_cfg (ir_graph *irg, const char *suffix)
2030 {
2031   FILE *f;
2032   ir_graph *rem = current_ir_graph;
2033   int ddif = dump_dominator_information_flag;
2034   int ipv = get_interprocedural_view();
2035
2036   /* if a filter is set, dump only the irg's that match the filter */
2037   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2038     return;
2039
2040   current_ir_graph = irg;
2041
2042   f = vcg_open(irg, suffix, "-cfg");
2043   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2044
2045   if (ipv) {
2046     printf("Warning: dumping cfg not in interprocedural view!\n");
2047     set_interprocedural_view(false);
2048   }
2049
2050   if (get_irg_dom_state(irg) != dom_consistent)
2051     dump_dominator_information_flag = 0;
2052
2053   /* walk over the blocks in the graph */
2054   irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2055   dump_node(f, get_irg_bad(irg));
2056
2057   dump_dominator_information_flag = ddif;
2058   set_interprocedural_view(ipv);
2059   vcg_close(f);
2060   current_ir_graph = rem;
2061 }
2062
2063
2064 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2065   if (pset_find_ptr(mark_set, n)) return;
2066
2067   pset_insert_ptr(mark_set, n);
2068
2069   if (depth > 0) {
2070     int i, start = is_Block(n) ? 0 : -1;
2071     dump_whole_node(n, F);
2072     for (i = start; i < get_irn_arity(n); ++i)
2073       descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2074   } else {
2075     dump_node(F, n);
2076     /* Don't dump edges to nodes further out.  These might be edges to
2077        nodes we already dumped, if there is a shorter path to these. */
2078   }
2079 }
2080
2081 static int subgraph_counter = 0;
2082 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2083   FILE *F;
2084   char buf[32];
2085   pset *mark_set = pset_new_ptr(1);
2086   sprintf(buf, "-subg_%03d", subgraph_counter++);
2087   F = vcg_open(get_irn_irg(root), suffix, buf);
2088   dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2089   descend_and_dump(F, root, depth, mark_set);
2090   vcg_close(F);
2091   del_pset(mark_set);
2092 }
2093
2094
2095 static int weight_overall(int rec, int loop) {
2096   return 2*rec + loop;
2097 }
2098
2099 static int compute_color (int my, int max) {
2100   int color;
2101   if (!max) {
2102     color = 0;
2103   } else {
2104     int step;
2105
2106     /* if small, scale to the full color range. */
2107     if (max < n_colors)
2108       my = my * (n_colors/max);
2109
2110     step = 1 + (max / n_colors);
2111
2112     color = my/step;
2113   }
2114   return base_color + n_colors - color;
2115 }
2116
2117 static int get_entity_color(entity *ent) {
2118   ir_graph *irg = get_entity_irg(ent);
2119   assert(irg);
2120
2121   {
2122     int rec_depth     = get_irg_recursion_depth(irg);
2123     int loop_depth    = get_irg_loop_depth(irg);
2124     int overall_depth = weight_overall(rec_depth, loop_depth);
2125
2126     int max_rec_depth     = irp->max_callgraph_recursion_depth;
2127     int max_loop_depth    = irp->max_callgraph_loop_depth;
2128     int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2129
2130     /* int my_rec_color     = compute_color(rec_depth, max_rec_depth); */
2131     /* int my_loop_color    = compute_color(loop_depth, max_loop_depth); */
2132     int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2133
2134     return my_overall_color;
2135   }
2136 }
2137
2138 void dump_callgraph(const char *suffix) {
2139   FILE *F;
2140   int i, n_irgs = get_irp_n_irgs();
2141   int rem = edge_label;
2142   edge_label = 1;
2143   //ident *prefix = new_id_from_str("java/");
2144
2145   F = vcg_open_name("Callgraph", suffix);
2146   dump_vcg_header(F, "Callgraph", NULL);
2147
2148   for (i = 0; i < n_irgs; ++i) {
2149     ir_graph *irg = get_irp_irg(i);
2150     entity *ent = get_irg_entity(irg);
2151     int j, n_callees = get_irg_n_callees(irg);
2152
2153     /* Do not dump runtime system. */
2154     //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2155
2156     dump_entity_node(F, ent, get_entity_color(ent));
2157     for (j = 0; j < n_callees; ++j) {
2158       entity *c = get_irg_entity(get_irg_callee(irg, j));
2159       //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2160       int be = is_irg_callee_backedge(irg, j);
2161       char *attr;
2162       attr = (be) ?
2163         "label:\"recursion %d\" color: %d" :
2164         "label:\"calls %d\" color: %d";
2165       print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2166     }
2167   }
2168
2169   edge_label = rem;
2170   vcg_close(F);
2171 }
2172
2173 /* Dump all irgs in interprocedural view to a single file. */
2174 void dump_all_cg_block_graph(const char *suffix) {
2175   FILE *f;
2176   int i;
2177   int rem_view = get_interprocedural_view();
2178   set_interprocedural_view(true);
2179
2180   f = vcg_open_name("All_graphs", suffix);
2181   dump_vcg_header(f, "All_graphs", NULL);
2182
2183   /* collect nodes in all irgs reachable in call graph*/
2184   for (i = 0; i < get_irp_n_irgs(); i++)
2185     ird_set_irg_link(get_irp_irg(i), NULL);
2186
2187   cg_walk(clear_link, collect_node, NULL);
2188
2189   /* dump all graphs */
2190   for (i = 0; i < get_irp_n_irgs(); i++) {
2191     current_ir_graph = get_irp_irg(i);
2192     assert(ird_get_irg_link(current_ir_graph));
2193     dump_graph_from_list(f, current_ir_graph);
2194     DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2195   }
2196
2197   vcg_close(f);
2198   set_interprocedural_view(rem_view);
2199 }
2200
2201 /*---------------------------------------------------------------------*/
2202 /* the following routines dumps type information without any ir nodes. */
2203 /*---------------------------------------------------------------------*/
2204
2205 void
2206 dump_type_graph (ir_graph *irg, const char *suffix)
2207 {
2208   FILE *f;
2209   ir_graph *rem;
2210   rem = current_ir_graph;
2211
2212   /* if a filter is set, dump only the irg's that match the filter */
2213   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2214
2215   current_ir_graph = irg;
2216
2217   f = vcg_open(irg, suffix, "-type");
2218   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2219
2220   /* walk over the blocks in the graph */
2221   type_walk_irg(irg, dump_type_info, NULL, f);
2222   /* The walker for the const code can be called several times for the
2223      same (sub) expression.  So that no nodes are dumped several times
2224      we decrease the visited flag of the corresponding graph after each
2225      walk.  So now increase it finally. */
2226   inc_irg_visited(get_const_code_irg());
2227
2228   vcg_close(f);
2229   current_ir_graph = rem;
2230 }
2231
2232 void
2233 dump_all_types (const char *suffix)
2234 {
2235   FILE *f = vcg_open_name("All_types", suffix);
2236   dump_vcg_header(f, "All_types", NULL);
2237   type_walk(dump_type_info, NULL, f);
2238   inc_irg_visited(get_const_code_irg());
2239   vcg_close(f);
2240 }
2241
2242 void
2243 dump_class_hierarchy (bool entities, const char *suffix)
2244 {
2245   FILE *f = vcg_open_name("class_hierarchy", suffix);
2246   h_env_t env;
2247
2248   env.f = f;
2249   dump_vcg_header(f, "class_hierarchy", NULL);
2250   if (entities)
2251     env.dump_ent = 1;
2252   else
2253     env.dump_ent = 0;
2254   type_walk(dump_class_hierarchy_node, NULL, &env);
2255   vcg_close(f);
2256 }
2257
2258 /*---------------------------------------------------------------------*/
2259 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
2260 /*  dump_ir_graph                                                      */
2261 /*  dump_ir_block_graph                                                */
2262 /*  dump_cfg                                                           */
2263 /*  dump_type_graph                                                    */
2264 /*  dump_ir_graph_w_types                                              */
2265 /*---------------------------------------------------------------------*/
2266
2267 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2268   int i, n_irgs = get_irp_n_irgs();
2269   for (i = 0; i < n_irgs; ++i) {
2270     dmp_grph(get_irp_irg(i), suffix);
2271   }
2272 }
2273
2274
2275 /*--------------------------------------------------------------------------------*
2276  * Dumps a stand alone loop graph with firm nodes which belong to one loop node   *
2277  * packed together in one subgraph/box                                            *
2278  *--------------------------------------------------------------------------------*/
2279
2280 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2281   int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2282   loop_element le;
2283   ir_loop *son = NULL;
2284
2285   /* Dump a new loop node. */
2286   dump_loop_node(F, loop);
2287
2288   /* Dump the loop elements. */
2289
2290   for(i = 0; i < get_loop_n_elements(loop); i++) {
2291     le = get_loop_element(loop, i);
2292     son = le.son;
2293     if (get_kind(son) == k_ir_loop) {
2294
2295       /* We are a loop son -> Recurse */
2296
2297       if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2298         fprintf(F, "\" }\n");
2299         fprintf (F, "edge: {sourcename: \"");
2300         PRINT_LOOPID(loop);
2301         fprintf (F, "\" targetname: \"");
2302         PRINT_LOOPID(loop);
2303         fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2304         loop_node_started = 0;
2305       }
2306       dump_loop_son_edge(F, loop, son_number++);
2307       dump_loops_standalone(F, son);
2308     } else if (get_kind(son) == k_ir_node) {
2309       /* We are a loop node -> Collect firm nodes */
2310
2311       ir_node *n = le.node;
2312       int bad = 0;
2313
2314       if (!loop_node_started) {
2315         /* Start a new node which contains all firm nodes of the current loop */
2316         fprintf (F, "node: { title: \"");
2317         PRINT_LOOPID(loop);
2318         fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2319         loop_node_started = 1;
2320         first = i;
2321       }
2322       else
2323         fprintf(F, "\n");
2324
2325       bad |= dump_node_opcode(F, n);
2326       bad |= dump_node_mode(F, n);
2327       bad |= dump_node_typeinfo(F, n);
2328       fprintf (F, " ");
2329       bad |= dump_node_nodeattr(F, n);
2330       fprintf (F, " %ld", get_irn_node_nr(n));
2331       /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2332       if (has_backedges(n)) fprintf(F, "\t loop head!");
2333     } else { /* for callgraph loop tree */
2334       ir_graph *n;
2335       assert(get_kind(son) == k_ir_graph);
2336
2337       /* We are a loop node -> Collect firm graphs */
2338       n = (ir_graph *)le.node;
2339       if (!loop_node_started) {
2340         /* Start a new node which contains all firm nodes of the current loop */
2341         fprintf (F, "node: { title: \"");
2342         PRINT_LOOPID(loop);
2343         fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2344         loop_node_started = 1;
2345         first = i;
2346       }
2347       else
2348         fprintf(F, "\n");
2349       fprintf (F, " %s", get_irg_dump_name(n));
2350       /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2351     }
2352   }
2353
2354   if (loop_node_started) {
2355     fprintf(F, "\" }\n");
2356     fprintf (F, "edge: {sourcename: \"");
2357     PRINT_LOOPID(loop);
2358     fprintf (F, "\" targetname: \"");
2359     PRINT_LOOPID(loop);
2360     fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2361     loop_node_started = 0;
2362   }
2363 }
2364
2365 void dump_loop_tree(ir_graph *irg, const char *suffix)
2366 {
2367   FILE *f;
2368   ir_graph *rem = current_ir_graph;
2369   int el_rem = edge_label;
2370   edge_label = 1;
2371
2372   /* if a filter is set, dump only the irg's that match the filter */
2373   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2374     return;
2375
2376   current_ir_graph = irg;
2377
2378   f = vcg_open(irg, suffix, "-looptree");
2379   dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2380
2381   if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2382
2383   vcg_close(f);
2384
2385   edge_label = el_rem;
2386   current_ir_graph = rem;
2387 }
2388
2389 void dump_callgraph_loop_tree(const char *suffix) {
2390   FILE *F;
2391   F = vcg_open_name("Callgraph_looptree", suffix);
2392   dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2393   dump_loops_standalone(F, irp->outermost_cg_loop);
2394   vcg_close(F);
2395 }
2396
2397
2398 /*-----------------------------------------------------------------------------*/
2399 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2400 /*-----------------------------------------------------------------------------*/
2401
2402 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2403   int i, son_number = 0, node_number = 0;
2404
2405   if (dump_loop_information_flag) dump_loop_node(F, loop);
2406
2407   for (i = 0; i < get_loop_n_elements(loop); i++) {
2408     loop_element le = get_loop_element(loop, i);
2409     if (*(le.kind) == k_ir_loop) {
2410       if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2411       /* Recur */
2412       collect_nodeloop(F, le.son, loopnodes);
2413     } else {
2414       if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2415       eset_insert(loopnodes, le.node);
2416     }
2417   }
2418 }
2419
2420 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2421   int i, j, start;
2422
2423   for(i = 0; i < get_loop_n_elements(loop); i++) {
2424     loop_element le = get_loop_element(loop, i);
2425     if (*(le.kind) == k_ir_loop) {
2426       /* Recur */
2427       collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2428     } else {
2429       if (is_Block(le.node)) start = 0; else start = -1;
2430       for (j = start; j < get_irn_arity(le.node); j++) {
2431         ir_node *pred = get_irn_n(le.node, j);
2432         if (!eset_contains(loopnodes, pred)) {
2433           eset_insert(extnodes, pred);
2434           if (!is_Block(pred)) {
2435             pred = get_nodes_block(pred);
2436             if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2437           }
2438         }
2439       }
2440     }
2441   }
2442 }
2443
2444 void dump_loop(ir_loop *l, const char *suffix) {
2445   FILE *F;
2446   char name[50];
2447   eset *loopnodes = eset_create();
2448   eset *extnodes = eset_create();
2449   ir_node *n, *b;
2450
2451   snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2452   F = vcg_open_name (name, suffix);
2453   dump_vcg_header(F, name, NULL);
2454
2455   /* collect all nodes to dump */
2456   collect_nodeloop(F, l, loopnodes);
2457   collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2458
2459   /* build block lists */
2460   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2461     set_irn_link(n, NULL);
2462   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2463     set_irn_link(n, NULL);
2464   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2465     if (!is_Block(n)) {
2466       b = get_nodes_block(n);
2467       set_irn_link(n, get_irn_link(b));
2468       set_irn_link(b, n);
2469     }
2470   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2471     if (!is_Block(n)) {
2472       b = get_nodes_block(n);
2473       set_irn_link(n, get_irn_link(b));
2474       set_irn_link(b, n);
2475     }
2476
2477   for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2478     if (is_Block(b)) {
2479       fprintf(F, "graph: { title: \"");
2480       PRINT_NODEID(b);
2481       fprintf(F, "\"  label: \"");
2482       dump_node_opcode(F, b);
2483       fprintf (F, " %ld", get_irn_node_nr(b));
2484       fprintf(F, "\" status:clustered color:yellow\n");
2485
2486       /* dump the blocks edges */
2487       dump_ir_data_edges(F, b);
2488
2489       /* dump the nodes that go into the block */
2490       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2491         if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2492         dump_node(F, n);
2493         overrule_nodecolor = NULL;
2494         if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2495       }
2496
2497       /* Close the vcg information for the block */
2498       fprintf(F, "}\n");
2499       dump_const_node_local(F, b);
2500       fprintf(F, "\n");
2501     }
2502   for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2503     if (is_Block(b)) {
2504       fprintf(F, "graph: { title: \"");
2505       PRINT_NODEID(b);
2506       fprintf(F, "\"  label: \"");
2507       dump_node_opcode(F, b);
2508       fprintf (F, " %ld", get_irn_node_nr(b));
2509       fprintf(F, "\" status:clustered color:lightblue\n");
2510
2511       /* dump the nodes that go into the block */
2512       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2513         if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2514         dump_node(F, n);
2515         overrule_nodecolor = NULL;
2516         if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2517       }
2518
2519       /* Close the vcg information for the block */
2520       fprintf(F, "}\n");
2521       dump_const_node_local(F, b);
2522       fprintf(F, "\n");
2523     }
2524
2525   eset_destroy(loopnodes);
2526   eset_destroy(extnodes);
2527   vcg_close(F);
2528 }