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