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