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