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