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