implemented Confirm node
[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
13
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif
17
18 # include <string.h>
19 # include <stdlib.h>
20
21 # include "irnode_t.h"
22 # include "irgraph_t.h"
23 # include "entity_t.h"
24 # include "irop_t.h"
25 # include "firm_common_t.h"
26
27 # include "irdump.h"
28
29 # include "irgwalk.h"
30 # include "typewalk.h"
31 # include "irprog.h"
32 # include "tv_t.h"
33 # include "type_or_entity.h"
34 # include "irouts.h"
35 # include "irdom.h"
36 # include "irloop.h"
37
38 # include "panic.h"
39 # include "array.h"
40 # include "pmap.h"
41
42 # include "exc.h"
43
44
45 /* Attributes of nodes */
46 #define PRINT_DEFAULT_NODE_ATTR
47 #define DEFAULT_NODE_ATTR " "
48 #define DEFAULT_TYPE_ATTRIBUTE " "
49
50 /* Attributes of edges between Firm nodes */
51 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
52 #define CF_EDGE_ATTR    "color: red"
53 #define MEM_EDGE_ATTR   "color: blue"
54 #define DOMINATOR_EDGE_ATTR "color: red"
55
56 #define BACK_EDGE_ATTR "linestyle: dashed "
57
58 /* Attributes of edges between Firm nodes and type/entity nodes */
59 #define NODE2TYPE_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
60
61 /* Attributes of edges in type/entity graphs. */
62 #define TYPE_METH_NODE_ATTR  "color: lightyellow"
63 #define TYPE_CLASS_NODE_ATTR "color: green"
64 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
65 #define ENTITY_NODE_ATTR     "color: yellow"
66 #define ENT_TYPE_EDGE_ATTR   "class: 3 label: \"type\" color: red"
67 #define ENT_OWN_EDGE_ATTR    "class: 4 label: \"owner\" color: black"
68 #define METH_PAR_EDGE_ATTR   "class: 5 label: \"param %d\" color: green"
69 #define METH_RES_EDGE_ATTR   "class: 6 label: \"res %d\" color: green"
70 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
71 #define UNION_EDGE_ATTR      "class: 8 label: \"component\" color: blue"
72 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
73 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
74 #define ARR_ENT_EDGE_ATTR    "class: 10 label: \"arr ent\" color: green"
75 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
76 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
77 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
78 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
79
80
81 #if DEBUG_libfirm && NODEID_AS_LABEL
82 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
83 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
84 #define PRINT_ENTID(X)  fprintf(F, "e%ld", get_entity_nr(X))
85 #define PRINT_IRGID(X)  fprintf(F, "g%ld", get_irg_graph_nr(X))
86 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
87
88 #else
89 #define PRINT_NODEID(X) fprintf(F, "n%p", (void*) X)
90 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *) X)
91 #define PRINT_ENTID(X)  fprintf(F, "e%p", (void*) X)
92 #define PRINT_IRGID(X)  fprintf(F, "g%p",(void*) X)
93 #define PRINT_CONSTID(X,Y) fprintf(F, "\"%p%p\"", (void*) X, (void*) Y)
94 #endif
95
96 #define PRINT_TYPE_TYPE_EDGE(S,T,...){fprintf (F, "edge: { sourcename: "); PRINT_TYPEID(S); fprintf (F, " targetname: "); PRINT_TYPEID(T); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
97 #define PRINT_TYPE_ENT_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: "); PRINT_TYPEID(S); fprintf (F, " targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");  fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
98 #define PRINT_ENT_ENT_EDGE(S,T,...)  {fprintf (F, "edge: { sourcename: \""); PRINT_ENTID(S);  fprintf (F, "\" targetname: \""); PRINT_ENTID(T);  fprintf(F, "\""); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
99 #define PRINT_ENT_TYPE_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: \""); PRINT_ENTID(S);  fprintf (F, "\" targetname: "); PRINT_TYPEID(T); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
100 #define PRINT_NODE_TYPE_EDGE(S,T,...){fprintf (F, "edge: { sourcename: \""); PRINT_NODEID(S); fprintf (F, "\" targetname: "); PRINT_TYPEID(T); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
101 #define PRINT_NODE_ENT_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: \""); PRINT_NODEID(S); fprintf (F, "\" targetname: \""); PRINT_ENTID(T);  fprintf(F, "\""); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
102 #define PRINT_ENT_NODE_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: \""); PRINT_ENTID(S);  fprintf (F, "\" targetname: \""); PRINT_NODEID(T); fprintf(F, "\""); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
103
104
105 /* A suffix to manipulate the file name. */
106 char *dump_file_suffix = NULL;
107
108 /* file to dump to */
109 static FILE *F;
110
111 /* A compiler option to turn off edge labels */
112 int edge_label = 1;
113 /* A compiler option to turn off dumping values of constant entities */
114 int const_entities = 1;
115 /* A compiler option to dump the keep alive edges */
116 int dump_keepalive = 0;
117 /* Compiler options to dump analysis information in dump_ir_graph */
118 int dump_out_edge_flag = 0;
119 int dump_dominator_information_flag = 0;
120 int dump_loop_information_flag = 0;
121 int dump_const_local = 0;
122 bool opt_dump_analysed_type_info = 1;
123
124 INLINE bool get_opt_dump_const_local(void) {
125   if (!dump_out_edge_flag && !dump_loop_information_flag)
126     return dump_const_local;
127   else
128     return false;
129 }
130
131 /* A global variable to record output of the Bad node. */
132 static int Bad_dumped;
133
134 static void dump_ir_blocks_nodes (ir_node *n, void *env);
135 static void dump_whole_node(ir_node *n, void* env);
136
137 /*******************************************************************/
138 /* routines to dump information about a single node                */
139 /*******************************************************************/
140
141
142
143 static INLINE void
144 dump_node_opcode (ir_node *n)
145 {
146   char buf[1024];
147   int res;
148
149   switch(get_irn_opcode(n)) {
150
151   case iro_Const: {
152     res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
153     assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
154     fprintf(F, buf);
155   } break;
156
157   case iro_SymConst: {
158     if (get_SymConst_kind(n) == linkage_ptr_info) {
159       /* don't use get_SymConst_ptr_info as it mangles the name. */
160       fprintf (F, "SymC %s", get_id_str(get_SymConst_ptrinfo(n)));
161     } else {
162       assert(get_kind(get_SymConst_type(n)) == k_type);
163       assert(get_type_ident(get_SymConst_type(n)));
164       fprintf (F, "SymC %s ", get_type_name(get_SymConst_type(n)));
165       if (get_SymConst_kind(n) == type_tag)
166         fprintf (F, "tag");
167       else
168         fprintf (F, "size");
169     }
170   } break;
171
172   case iro_Filter: {
173     if (!interprocedural_view) fprintf(F, "Proj'");
174   } break;
175
176   default: {
177     fprintf (F, "%s", get_id_str(get_irn_opident(n)));
178   }
179
180   }  /* end switch */
181 }
182
183 static INLINE void
184 dump_node_mode (ir_node *n)
185 {
186   switch (get_irn_opcode(n)) {
187   case iro_Phi:
188   case iro_Const:
189   case iro_Id:
190   case iro_Proj:
191   case iro_Filter:
192   case iro_Conv:
193   case iro_Tuple:
194   case iro_Add:
195   case iro_Sub:
196   case iro_Mul:
197   case iro_And:
198   case iro_Or:
199   case iro_Eor:
200   case iro_Shl:
201   case iro_Shr:
202   case iro_Abs:
203   case iro_Cmp:
204   case iro_Confirm:
205     fprintf (F, "%s", get_mode_name(get_irn_mode(n)));
206     break;
207   default:
208     ;
209   }
210 }
211
212 static void dump_node_typeinfo(ir_node *n) {
213   if (!opt_dump_analysed_type_info) return;
214   if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent  ||
215       get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent  ) {
216     type *tp = get_irn_type(n);
217     if (tp != none_type)
218       fprintf (F, " [%s]", get_type_name(tp));
219     else
220       fprintf (F, " []");
221   }
222 }
223
224 static INLINE void
225 dump_node_nodeattr (ir_node *n)
226 {
227   switch (get_irn_opcode(n)) {
228   case iro_Start:
229     if (false && interprocedural_view) {
230       fprintf (F, "%s", get_entity_name(get_irg_ent(current_ir_graph)));
231     }
232     break;
233   case iro_Proj:
234     if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
235       fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
236     } else {
237       fprintf (F, "%ld", get_Proj_proj(n));
238     }
239     break;
240   case iro_Filter:
241     fprintf (F, "%ld", get_Filter_proj(n));
242     break;
243   case iro_Sel: {
244     assert(get_kind(get_Sel_entity(n)) == k_entity);
245     fprintf (F, "%s", get_entity_name(get_Sel_entity(n)));
246     } break;
247   case iro_Cast: {
248     fprintf (F, "(%s)", get_type_name(get_Cast_type(n)));
249     } break;
250   case iro_Confirm: {
251     fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
252     } break;
253
254   default:
255     ;
256   } /* end switch */
257 }
258
259 static INLINE void
260 dump_node_vcgattr (ir_node *n)
261 {
262   switch (get_irn_opcode(n)) {
263   case iro_Start:
264   case iro_EndReg:
265     /* fall through */
266   case iro_EndExcept:
267     /* fall through */
268   case iro_End:
269     fprintf (F, "color: blue");
270     break;
271   case iro_Block:
272     fprintf (F, "color: lightyellow");
273     break;
274   case iro_Phi:
275     fprintf (F, "color: green");
276     break;
277   case iro_Const:
278   case iro_Proj:
279   case iro_Filter:
280   case iro_Tuple:
281     fprintf (F, "color: yellow");
282     break;
283   default:
284     PRINT_DEFAULT_NODE_ATTR;
285   }
286 }
287
288 static INLINE void
289 dump_node_info (ir_node *n) {
290   int i;
291   fprintf (F, " info1: \"");
292   fprintf (F, "visited: %ld \n", get_irn_visited(n));
293
294   /* Source types */
295   switch(get_irn_opcode(n)) {
296   case iro_Start: {
297     type *tp = get_entity_type(get_irg_ent(get_Start_irg(n)));
298     fprintf(F, "start of method of type %s \n", get_type_name(tp));
299     for (i = 0; i < get_method_n_params(tp); ++i)
300       fprintf(F, "  param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
301   } break;
302   case iro_Alloc: {
303     fprintf(F, "allocating entity of type %s \n", get_type_name(get_Alloc_type(n)));
304   } break;
305   case iro_Free: {
306     fprintf(F, "freeing entity of type %s \n", get_type_name(get_Free_type(n)));
307   } break;
308   case iro_Sel: {
309     fprintf(F, "Selecting entity of type %s \n", get_type_name(get_entity_type(get_Sel_entity(n))));
310     fprintf(F, "  from entity of type %s \n", get_type_name(get_entity_owner(get_Sel_entity(n))));
311   } break;
312   case iro_Call: {
313     type *tp = get_Call_type(n);
314     fprintf(F, "calling method of type %s \n", get_type_name(tp));
315     for (i = 0; i < get_method_n_params(tp); ++i)
316       fprintf(F, "  param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
317     for (i = 0; i < get_method_n_ress(tp); ++i)
318       fprintf(F, "  resul %d type: %s \n", i, get_type_name(get_method_res_type(tp, i)));
319   } break;
320   case iro_Return: {
321     if (!interprocedural_view) {
322       type *tp = get_entity_type(get_irg_ent(current_ir_graph));
323       fprintf(F, "return in method of type %s \n", get_type_name(tp));
324       for (i = 0; i < get_method_n_ress(tp); ++i)
325         fprintf(F, "  res %d type: %s \n", i, get_type_name(get_method_res_type(tp, i)));
326     }
327     } break;
328   case iro_Const: {
329     type *tp = get_Const_type(n);
330     assert(tp != none_type);
331     fprintf(F, "Const of type %s \n", get_type_name(get_Const_type(n)));
332   } break;
333   default: ;
334   }
335
336   if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent  ||
337       get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent  )
338     if (get_irn_type(n) != none_type)
339       fprintf (F, "\nAnalysed type: %s", get_type_name(get_irn_type(n)));
340
341   fprintf (F, "\"");
342
343 }
344
345 static bool pred_in_wrong_graph(ir_node *n, int pos, pmap *irgmap) {
346   ir_node *block = (is_Block(n)) ? n : get_nodes_Block(n);
347
348   if (irgmap &&
349       ((get_irn_op(n) == op_Filter) || (get_irn_op(n) == op_Block))) {
350     ir_node *pred = skip_Proj(get_Block_cfgpred(block, pos));
351     if (is_ip_cfop(pred)) {
352       ir_graph *irg = get_ip_cfop_irg(pred);
353       if (pmap_find(irgmap, irg) == NULL) return true;
354     }
355   }
356
357   return false;
358 }
359
360
361 static INLINE
362 bool is_constlike_node(ir_node *n) {
363   ir_op *op = get_irn_op(n);
364   return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
365 }
366
367
368 /* outputs the predecessors of n, that are constants, local.  I.e.,
369    generates a copy of the constant for each node called with. */
370 static void dump_const_node_local(ir_node *n, pmap *irgmap) {
371   int i;
372   if (!get_opt_dump_const_local()) return;
373   /* Use visited flag to avoid outputting nodes twice.
374      initialize it first. */
375   for (i = 0; i < get_irn_arity(n); i++) {
376     ir_node *con = get_irn_n(n, i);
377     if (is_constlike_node(con)) {
378       if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
379       set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
380     }
381   }
382   for (i = 0; i < get_irn_arity(n); i++) {
383     ir_node *con = get_irn_n(n, i);
384     if (is_constlike_node(con) && irn_not_visited(con)) {
385       if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
386       mark_irn_visited(con);
387       /* Generate a new name for the node by appending the names of
388          n and const. */
389       fprintf (F, "node: {title: "); PRINT_CONSTID(n,con);
390       fprintf(F, " label: \"");
391       dump_node_opcode(con);
392       dump_node_mode (con);
393       dump_node_typeinfo(con);
394       fprintf (F, " ");
395       dump_node_nodeattr(con);
396 #ifdef DEBUG_libfirm
397       fprintf (F, " %ld", get_irn_node_nr(con));
398 #endif
399       fprintf (F, "\" ");
400       dump_node_vcgattr(con);
401       dump_node_info(con);
402       fprintf (F, "}\n");
403     }
404   }
405 }
406
407 static void
408 dump_node (ir_node *n, pmap * map) {
409   if (get_opt_dump_const_local() && is_constlike_node(n)) return;
410
411   /* dump this node */
412   fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
413
414   dump_node_opcode(n);
415   dump_node_mode (n);
416   dump_node_typeinfo(n);
417   fprintf (F, " ");
418   dump_node_nodeattr(n);
419 #ifdef DEBUG_libfirm
420   fprintf (F, " %ld", get_irn_node_nr(n));
421 #endif
422   fprintf (F, "\" ");
423   dump_node_vcgattr(n);
424   dump_node_info(n);
425   fprintf (F, "}\n");
426   dump_const_node_local(n, map);
427 }
428
429 /* dump the edge to the block this node belongs to */
430 static void
431 dump_ir_block_edge(ir_node *n)  {
432   if (get_opt_dump_const_local() && is_constlike_node(n)) return;
433   if (is_no_Block(n)) {
434     fprintf (F, "edge: { sourcename: \"");
435     PRINT_NODEID(n);
436     fprintf (F, "\" targetname: \"");
437     PRINT_NODEID(get_nodes_Block(n));
438     fprintf (F, "\" "   BLOCK_EDGE_ATTR "}\n");
439   }
440 }
441
442 static void print_edge_vcgattr(ir_node *from, int to) {
443   assert(from);
444
445   if (is_backedge(from, to)) fprintf (F, BACK_EDGE_ATTR);
446
447   switch (get_irn_opcode(from)) {
448   case iro_Block:
449     fprintf (F, CF_EDGE_ATTR);
450     break;
451   case iro_Start:   break;
452   case iro_End:
453     if (to >= 0) {
454       if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
455         fprintf (F, CF_EDGE_ATTR);
456       if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
457         fprintf (F, MEM_EDGE_ATTR);
458     }
459     break;
460   case iro_EndReg: break;
461   case iro_EndExcept: break;
462   case iro_Jmp:     break;
463   case iro_Break:   break;
464   case iro_Cond:    break;
465   case iro_Return:
466   case iro_Raise:
467     if (to == 0) fprintf (F, MEM_EDGE_ATTR);
468     break;
469   case iro_Const:   break;
470   case iro_SymConst:break;
471   case iro_Sel:
472   case iro_Call:
473     if (to == 0) fprintf (F, MEM_EDGE_ATTR);
474     break;
475   case iro_CallBegin: break;
476   case iro_Add:     break;
477   case iro_Sub:     break;
478   case iro_Minus:   break;
479   case iro_Mul:     break;
480   case iro_Quot:
481   case iro_DivMod:
482   case iro_Div:
483   case iro_Mod:
484     if (to == 0) fprintf (F, MEM_EDGE_ATTR);
485     break;
486   case iro_Abs:    break;
487   case iro_And:    break;
488   case iro_Or:     break;
489   case iro_Eor:    break;
490   case iro_Shl:    break;
491   case iro_Shr:    break;
492   case iro_Shrs:   break;
493   case iro_Rot:    break;
494   case iro_Cmp:    break;
495   case iro_Conv:   break;
496   case iro_Phi:
497     if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
498     break;
499   case iro_Load:
500   case iro_Store:
501   case iro_Alloc:
502   case iro_Free:
503     if (to == 0) fprintf (F, MEM_EDGE_ATTR);
504     break;
505   case iro_Sync:
506     fprintf (F, MEM_EDGE_ATTR);
507     break;
508   case iro_Tuple:  break;
509   case iro_Proj:
510   case iro_Filter:
511     switch (get_irn_modecode(from)) {
512     case irm_X:
513       fprintf (F, CF_EDGE_ATTR);
514       break;
515     case irm_M:
516       fprintf (F, MEM_EDGE_ATTR);
517       break;
518     default: break;
519     }
520     break;
521   case iro_Bad:    break;
522   case iro_Unknown: break;
523   case iro_Id:     break;
524   default:
525     ;
526   }
527 }
528
529 /* dump edges to our inputs */
530 static void
531 dump_ir_data_edges(ir_node *n, pmap *irgmap)  {
532   int i, visited = get_irn_visited(n);
533
534   if ((get_irn_op(n) == op_End) && (!dump_keepalive))
535     return;
536
537   for (i = 0; i < get_irn_arity(n); i++) {
538     ir_node * pred = get_irn_n(n, i);
539     assert(pred);
540     if ((interprocedural_view && get_irn_visited(pred) < visited))
541       continue; /* pred not dumped */
542     if (is_backedge(n, i))
543       fprintf (F, "backedge: {sourcename: \"");
544     else
545       fprintf (F, "edge: {sourcename: \"");
546     PRINT_NODEID(n);
547     fprintf (F, "\" targetname: ");
548     if ((get_opt_dump_const_local()) && is_constlike_node(pred) &&
549         !pred_in_wrong_graph(n, i, irgmap))
550     {
551       PRINT_CONSTID(n, pred);
552     }
553     else
554       {fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
555     }
556     fprintf (F, " label: \"%d\" ", i);
557     print_edge_vcgattr(n, i);
558     fprintf (F, "}\n");
559   }
560 }
561
562 /* dump out edges */
563 static void
564 dump_out_edge (ir_node *n, void* env) {
565   int i;
566   for (i = 0; i < get_irn_n_outs(n); i++) {
567     assert(get_irn_out(n, i));
568     fprintf (F, "edge: {sourcename: \"");
569     PRINT_NODEID(n);
570     fprintf (F, "\" targetname: \"");
571     PRINT_NODEID(get_irn_out(n, i));
572     fprintf (F, "\" color: red linestyle: dashed");
573     fprintf (F, "}\n");
574   }
575 }
576
577 static INLINE void
578 dump_loop_node_edge (ir_loop *loop, int i) {
579   assert(loop);
580   fprintf (F, "edge: {sourcename: \"%p\" targetname: \"", (void*) loop);
581   PRINT_NODEID(get_loop_node(loop, i));
582   fprintf (F, "\" color: green");
583   fprintf (F, "}\n");
584 }
585
586 static
587 void dump_loops (ir_loop *loop) {
588   int i;
589   /* dump this loop node */
590   fprintf (F, "node: {title: \"%p\" label: \"loop %d, %d sons, %d nodes\" }\n",
591             (void*)loop, get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
592   /* dump edges to nodes in loop -- only if it is a real loop */
593   if (get_loop_depth(loop) != 0) {
594     for (i = 0; i < get_loop_n_nodes(loop); i++) {
595       dump_loop_node_edge(loop, i);
596     }
597   }
598   for (i = 0; i < get_loop_n_sons(loop); i++) {
599     dump_loops(get_loop_son(loop, i));
600   }
601 }
602
603 static INLINE
604 void dump_loop_info(ir_graph *irg) {
605   ir_graph *rem = current_ir_graph;
606   current_ir_graph = irg;
607
608   if (get_irg_loop(irg))
609     dump_loops(get_irg_loop(irg));
610
611   current_ir_graph = rem;
612 }
613
614
615 /* dumps the edges between nodes and their type or entity attributes. */
616 static void dump_node2type_edges (ir_node *n, void *env)
617 {
618   assert(n);
619
620   switch (get_irn_opcode(n)) {
621   case iro_Const :
622     /* @@@ some consts have an entity */
623     break;
624   case iro_SymConst:
625     if (   (get_SymConst_kind(n) == type_tag)
626            || (get_SymConst_kind(n) == size))
627       {
628         PRINT_NODE_TYPE_EDGE(n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
629       }
630     break;
631   case iro_Sel: {
632       PRINT_NODE_ENT_EDGE(n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
633     } break;
634   case iro_Call: {
635       PRINT_NODE_TYPE_EDGE(n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
636     } break;
637   case iro_Alloc: {
638       PRINT_NODE_TYPE_EDGE(n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
639     } break;
640   case iro_Free: {
641       PRINT_NODE_TYPE_EDGE(n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
642     } break;
643   case iro_Cast: {
644       PRINT_NODE_TYPE_EDGE(n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
645     } break;
646   default:
647     break;
648   }
649 }
650
651
652 static void dump_const_expression(ir_node *value) {
653   ir_graph *rem = current_ir_graph;
654   int rem_dump_const_local = dump_const_local;
655   dump_const_local = 0;
656   current_ir_graph = get_const_code_irg();
657   irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
658   /* Decrease visited flag so that we walk with the same flag for the next
659      expresssion.  This guarantees that we don't dump the same node twice,
660      as for const expressions cse is performed to save memory. */
661   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
662   current_ir_graph = rem;
663   dump_const_local = rem_dump_const_local;
664 }
665
666
667 static void print_type_info(type *tp) {
668   if (get_type_state(tp) == layout_undefined) {
669     fprintf(F, "state: layout_undefined\n");
670   } else {
671     fprintf(F, "state: layout_fixed,\n");
672   }
673   if (get_type_mode(tp))
674     fprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
675   fprintf(F, "size: %dB,\n", get_type_size(tp));
676 }
677
678
679 static void print_typespecific_info(type *tp) {
680   switch (get_type_tpop_code(tp)) {
681   case tpo_class:
682     {
683       if (peculiarity_existent == get_class_peculiarity(tp))
684         fprintf (F, " " TYPE_CLASS_NODE_ATTR);
685       else
686         fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
687     } break;
688   case tpo_struct:
689     {
690       fprintf (F, " " TYPE_METH_NODE_ATTR);
691     } break;
692   case tpo_method:
693     {
694     } break;
695   case tpo_union:
696     {
697     } break;
698   case tpo_array:
699     {
700     } break;
701   case tpo_enumeration:
702     {
703     } break;
704   case tpo_pointer:
705     {
706     } break;
707   case tpo_primitive:
708     {
709     } break;
710   default: break;
711   } /* switch type */
712 }
713
714 static void print_type_node(type *tp)
715 {
716   fprintf (F, "node: {title: ");
717   PRINT_TYPEID(tp);
718   fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name(tp));
719   fprintf (F, " info1: \"");
720   print_type_info(tp);
721   fprintf (F, "\"");
722   print_typespecific_info(tp);
723   fprintf (F, "}\n");
724 }
725
726 #define X(a)    case a: fprintf(F, #a); break
727 void dump_entity_node(entity *ent)
728 {
729   fprintf (F, "node: {title: \"");
730   PRINT_ENTID(ent); fprintf(F, "\"");
731   fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
732   fprintf (F, "label: ");
733   fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_entity_name(ent));
734   fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
735
736   fprintf (F, "\nallocation:  ");
737   switch (get_entity_allocation(ent)) {
738     X(allocation_dynamic);
739     X(allocation_automatic);
740     X(allocation_static);
741     X(allocation_parameter);
742   }
743
744   fprintf (F, "\nvisibility:  ");
745   switch (get_entity_visibility(ent)) {
746     X(visibility_local);
747     X(visibility_external_visible);
748     X(visibility_external_allocated);
749   }
750
751   fprintf (F, "\nvariability: ");
752   switch (get_entity_variability(ent)) {
753     X(variability_uninitialized);
754     X(variability_initialized);
755     X(variability_part_constant);
756     X(variability_constant);
757   }
758
759   fprintf (F, "\nvolatility:  ");
760   switch (get_entity_volatility(ent)) {
761     X(volatility_non_volatile);
762     X(volatility_is_volatile);
763   }
764
765   fprintf (F, "\npeculiarity: ");
766   switch (get_entity_peculiarity(ent)) {
767     X(peculiarity_description);
768     X(peculiarity_inherited);
769     X(peculiarity_existent);
770   }
771   fprintf(F, "\nname:    %s\nld_name: %s",
772           get_entity_name(ent), get_entity_ld_name(ent));
773   fprintf(F, "\noffset:  %d", get_entity_offset(ent));
774   if (is_method_type(get_entity_type(ent))) {
775     if (get_entity_irg(ent))   /* can be null */
776       { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
777     else
778       { fprintf (F, "\nirg = NULL"); }
779   }
780   fprintf(F, "\"\n}\n");
781 }
782 #undef X
783
784 /* dumps a type or entity and it's edges. */
785 static void
786 dump_type_info (type_or_ent *tore, void *env) {
787   int i = 0;  /* to shutup gcc */
788
789   /* dump this type or entity */
790
791   switch (get_kind(tore)) {
792   case k_entity:
793     {
794       entity *ent = (entity *)tore;
795       ir_node *value;
796       /* The node */
797       dump_entity_node(ent);
798       /* The Edges */
799       /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
800       fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
801                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
802       PRINT_ENT_TYPE_EDGE(ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
803       if(is_class_type(get_entity_owner(ent))) {
804         for(i = 0; i < get_entity_n_overwrites(ent); i++){
805           PRINT_ENT_ENT_EDGE(ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
806         }
807       }
808       /* attached subgraphs */
809       if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
810         if (is_atomic_entity(ent)) {
811           value = get_atomic_ent_value(ent);
812           if (value) {
813             PRINT_ENT_NODE_EDGE(ent, value, ENT_VALUE_EDGE_ATTR, i);
814             /* DDMN(value);  $$$ */
815             dump_const_expression(value);
816           }
817         }
818         if (is_compound_entity(ent)) {
819           for (i = 0; i < get_compound_ent_n_values(ent); i++) {
820             value = get_compound_ent_value(ent, i);
821             if (value) {
822               PRINT_ENT_NODE_EDGE(ent,value,ENT_VALUE_EDGE_ATTR,i);
823               dump_const_expression(value);
824               PRINT_ENT_ENT_EDGE(ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
825               /*
826                 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
827                 ENT_CORR_EDGE_ATTR  "}\n", GET_ENTID(ent),
828                 get_compound_ent_value_member(ent, i), i);
829               */
830             }
831           }
832         }
833       }
834     } break;
835   case k_type:
836     {
837       type *tp = (type *)tore;
838       print_type_node(tp);
839       /* and now the edges */
840       switch (get_type_tpop_code(tp)) {
841       case tpo_class:
842         {
843           for (i=0; i < get_class_n_supertypes(tp); i++) {
844             PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
845           }
846
847           for (i=0; i < get_class_n_members(tp); i++) {
848             PRINT_TYPE_ENT_EDGE(tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
849           }
850         } break;
851       case tpo_struct:
852         {
853           for (i=0; i < get_struct_n_members(tp); i++) {
854             PRINT_TYPE_ENT_EDGE(tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
855           }
856         } break;
857       case tpo_method:
858         {
859           for (i = 0; i < get_method_n_params(tp); i++)
860           {
861                   PRINT_TYPE_TYPE_EDGE(tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
862           }
863           for (i = 0; i < get_method_n_ress(tp); i++)
864           {
865                   PRINT_TYPE_TYPE_EDGE(tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
866           }
867         } break;
868       case tpo_union:
869         {
870           for (i = 0; i < get_union_n_members(tp); i++)
871           {
872                   PRINT_TYPE_ENT_EDGE(tp,get_union_member(tp, i),UNION_EDGE_ATTR);
873           }
874         } break;
875       case tpo_array:
876         {
877                   PRINT_TYPE_TYPE_EDGE(tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
878                   PRINT_TYPE_ENT_EDGE(tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
879                   for (i = 0; i < get_array_n_dimensions(tp); i++) {
880                     ir_node *upper = get_array_upper_bound(tp, i);
881                     ir_node *lower = get_array_lower_bound(tp, i);
882                     PRINT_NODE_TYPE_EDGE(upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
883                     PRINT_NODE_TYPE_EDGE(lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
884                     dump_const_expression(upper);
885                     dump_const_expression(lower);
886                   }
887
888         } break;
889       case tpo_enumeration:
890         {
891         } break;
892       case tpo_pointer:
893         {
894                   PRINT_TYPE_TYPE_EDGE(tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
895         } break;
896       case tpo_primitive:
897         {
898         } break;
899       default: break;
900       } /* switch type */
901     }
902     break; /* case k_type */
903   default:
904     {
905       printf(" *** irdump,  dump_type_info(l.%i), faulty type.\n", __LINE__);
906     } break;
907   } /* switch kind_or_entity */
908 }
909
910 /* dumps a class type node and a superclass edge.
911    If env != null dumps entities of classes and overwrites edges. */
912 static void
913 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
914   int i = 0;  /* to shutup gcc */
915
916   /* dump this type or entity */
917   switch (get_kind(tore)) {
918   case k_entity: {
919     entity *ent = (entity *)tore;
920     if (get_entity_owner(ent) == get_glob_type()) break;
921     if ((env) && is_class_type(get_entity_owner(ent))) {
922       /* The node */
923       dump_entity_node(ent);
924       /* The edges */
925       PRINT_TYPE_ENT_EDGE(get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
926       for(i = 0; i < get_entity_n_overwrites(ent); i++)
927       {
928       PRINT_ENT_ENT_EDGE(get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
929       }
930     }
931   } break; /* case k_entity */
932   case k_type:
933     {
934       type *tp = (type *)tore;
935       if (tp == get_glob_type()) break;
936       switch (get_type_tpop_code(tp)) {
937         case tpo_class: {
938           print_type_node(tp);
939           /* and now the edges */
940           for (i=0; i < get_class_n_supertypes(tp); i++)
941           {
942                   PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
943           }
944         } break;
945         default: break;
946       } /* switch type */
947     }
948     break; /* case k_type */
949   default:
950     {
951       printf(" *** irdump,  dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
952     } break;
953   } /* switch kind_or_entity */
954 }
955
956 /************************************************************************/
957 /* open and close vcg file                                              */
958 /************************************************************************/
959
960 static void vcg_open (ir_graph *irg, char *suffix) {
961   char *fname;  /* filename to put the vcg information in */
962   const char *cp;
963   ident *id;
964   int len;
965   char label[4];
966   entity *ent;
967
968   /** open file for vcg graph */
969   ent = get_irg_ent(irg);
970   id    = ent->ld_name ? ent->ld_name : ent->name;
971   /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
972   len   = get_id_strlen (id);
973   cp    = get_id_str (id);
974   if (dump_file_suffix)
975     fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
976   else
977     fname = malloc (len + 5 + strlen(suffix));
978   strncpy (fname, cp, len);      /* copy the filename */
979   fname[len] = '\0';
980   if (dump_file_suffix) strcat (fname, dump_file_suffix);  /* append file suffix */
981   strcat (fname, suffix);  /* append file suffix */
982   strcat (fname, ".vcg");   /* append the .vcg suffix */
983   F = fopen (fname, "w");   /* open file for writing */
984   if (!F) {
985     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
986   }
987
988   if (edge_label) {
989     strcpy(label, "yes");
990   } else {
991     strcpy (label, "no");
992   }
993
994   /* print header */
995   fprintf (F,
996             "graph: { title: \"ir graph of %s\"\n"
997             "display_edge_labels: %s\n"
998             "layoutalgorithm: mindepth\n"
999             "manhattan_edges: yes\n"
1000             "port_sharing: no\n"
1001             "orientation: bottom_to_top\n"
1002             "classname 1: \"Data\"\n"
1003             "classname 2: \"Block\"\n"
1004             "classname 3: \"Entity type\"\n"
1005             "classname 4: \"Entity owner\"\n"
1006             "classname 5: \"Method Param\"\n"
1007             "classname 6: \"Method Res\"\n"
1008             "classname 7: \"Super\"\n"
1009             "classname 8: \"Union\"\n"
1010             "classname 9: \"Points-to\"\n"
1011             "classname 10: \"Array Element Type\"\n"
1012             "classname 11: \"Overwrites\"\n"
1013             "classname 12: \"Member\"\n"
1014             , cp, label);
1015
1016   fprintf (F, "\n");            /* a separator */
1017 }
1018
1019 static void vcg_open_name (const char *name) {
1020   char *fname;  /* filename to put the vcg information in */
1021   int len;
1022   char label[4];
1023
1024   /** open file for vcg graph */
1025   len   = strlen(name);
1026   fname = malloc (len + 5);
1027   if (dump_file_suffix)
1028     fname = malloc (len + 5 + strlen(dump_file_suffix));
1029   else
1030     fname = malloc (len + 5);
1031   strcpy (fname, name);    /* copy the filename */
1032   if (dump_file_suffix) strcat (fname, dump_file_suffix);
1033   strcat (fname, ".vcg");  /* append the .vcg suffix */
1034   F = fopen (fname, "w");  /* open file for writing */
1035   if (!F) {
1036     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
1037   }
1038
1039   if (edge_label) {
1040     strcpy(label, "yes");
1041   } else {
1042     strcpy (label, "no");
1043   }
1044
1045   /* print header */
1046   fprintf (F,
1047             "graph: { title: \"ir graph of %s\"\n"
1048             "display_edge_labels: %s\n"
1049             "layoutalgorithm: mindepth\n"
1050             "manhattan_edges: yes\n"
1051             "port_sharing: no\n"
1052             "orientation: bottom_to_top\n"
1053             "classname 1: \"Data\"\n"
1054             "classname 2: \"Block\"\n"
1055             "classname 3: \"Entity type\"\n"
1056             "classname 4: \"Entity owner\"\n"
1057             "classname 5: \"Method Param\"\n"
1058             "classname 6: \"Method Res\"\n"
1059             "classname 7: \"Super\"\n"
1060             "classname 8: \"Union\"\n"
1061             "classname 9: \"Points-to\"\n"
1062             "classname 10: \"Array Element Type\"\n"
1063             "classname 11: \"Overwrites\"\n"
1064             "classname 12: \"Member\"\n"
1065             , name, label);
1066
1067   fprintf (F, "\n");            /* a separator */
1068 }
1069
1070 static void
1071 vcg_close (void) {
1072   fprintf (F, "}\n");  /* print footer */
1073   fclose (F);           /* close vcg file */
1074 }
1075
1076 /************************************************************************/
1077 /* routines to dump a graph, blocks as conventional nodes.              */
1078 /************************************************************************/
1079
1080 static int node_floats(ir_node *n) {
1081   return ((get_op_pinned(get_irn_op(n)) == floats) &&
1082           (get_irg_pinned(current_ir_graph) == floats));
1083 }
1084
1085 static void
1086 dump_whole_node (ir_node *n, void* env) {
1087   dump_node(n, NULL);
1088   if (!node_floats(n)) dump_ir_block_edge(n);
1089   dump_ir_data_edges(n, NULL);
1090 }
1091
1092 void
1093 dump_ir_graph (ir_graph *irg)
1094 {
1095   ir_graph *rem;
1096   rem = current_ir_graph;
1097   current_ir_graph = irg;
1098
1099   vcg_open (irg, "");
1100
1101   /* walk over the graph */
1102   /* dump_whole_node must be called in post visiting predecessors */
1103   irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1104
1105   /* dump the out edges in a separate walk */
1106   if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1107     irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1108   }
1109
1110   vcg_close();
1111
1112   current_ir_graph = rem;
1113 }
1114
1115 /***********************************************************************/
1116 /* the following routines dump the nodes as attached to the blocks.    */
1117 /***********************************************************************/
1118
1119 static void
1120 dump_ir_blocks_nodes (ir_node *n, void *env) {
1121   ir_node *block = (ir_node *)env;
1122
1123   if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1124     dump_node(n, NULL);
1125     dump_ir_data_edges(n, NULL);
1126   }
1127   if (get_irn_op(n) == op_Bad)
1128     Bad_dumped = 1;
1129 }
1130
1131 static void
1132 dump_ir_block (ir_node *block, void *env) {
1133   ir_graph *irg = (ir_graph *)env;
1134
1135   if (get_irn_opcode(block) == iro_Block) {
1136
1137     /* This is a block. So dump the vcg information to make a block. */
1138     fprintf(F, "graph: { title: \"");
1139         PRINT_NODEID(block);
1140         fprintf(F, "\" label: \"");
1141 #ifdef DEBUG_libfirm
1142     fprintf (F, "%ld", get_irn_node_nr(block));
1143 #else
1144     fprintf (F, "%s", get_op_name(get_irn_op(block)));
1145 #endif
1146     if (exc_normal != get_Block_exc (block))
1147       fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1148
1149     fprintf(F, "\" status:clustered color:%s \n",
1150              get_Block_matured (block) ? "yellow" : "red");
1151     /* dump the blocks edges */
1152     dump_ir_data_edges(block, NULL);
1153
1154     /* dump the nodes that go into the block */
1155     irg_walk(get_irg_end(irg), dump_ir_blocks_nodes, NULL, block);
1156
1157     /* Close the vcg information for the block */
1158     fprintf(F, "}\n\n");
1159     dump_const_node_local(block, NULL);
1160   }
1161 }
1162
1163
1164 static void
1165 dump_blockless_nodes (ir_node *n, void *env) {
1166   if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1167     dump_node(n, NULL);
1168     dump_ir_data_edges(n, NULL);
1169     dump_ir_block_edge(n);
1170     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1171     return;
1172   }
1173   if (node_floats(n)) {
1174     dump_node(n, NULL);
1175     dump_ir_data_edges(n, NULL);
1176     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1177   }
1178 }
1179
1180 static void dump_ir_block_graph_2  (ir_graph *irg)
1181 {
1182   Bad_dumped = 0;
1183   /* walk over the blocks in the graph */
1184   irg_block_walk(get_irg_end(irg), dump_ir_block, NULL, irg);
1185
1186   /* dump all nodes that are not in a Block */
1187   irg_walk(get_irg_end(irg), dump_blockless_nodes, NULL, NULL);
1188
1189   /* dump the Bad node */
1190   if (!Bad_dumped)
1191     dump_node(get_irg_bad(irg), NULL);
1192 }
1193
1194 void
1195 dump_ir_block_graph (ir_graph *irg)
1196 {
1197   ir_graph *rem;
1198   rem = current_ir_graph;
1199   current_ir_graph = irg;
1200
1201   vcg_open (irg, "");
1202
1203   dump_ir_block_graph_2 (irg);
1204
1205   if (dump_loop_information_flag) dump_loop_info(irg);
1206
1207   vcg_close();
1208   current_ir_graph = rem;
1209 }
1210
1211
1212 /***********************************************************************/
1213 /* the following routines dump a control flow graph                    */
1214 /***********************************************************************/
1215
1216
1217 static void
1218 dump_block_to_cfg (ir_node *block, void *env) {
1219   int i;
1220   ir_node *pred;
1221
1222   if (get_irn_opcode(block) == iro_Block) {
1223     /* This is a block. Dump a node for the block. */
1224     fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1225     fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1226 #ifdef DEBUG_libfirm
1227     fprintf (F, "%ld", get_irn_node_nr(block));
1228 #else
1229     fprintf (F, "%p", (void*) block);
1230 #endif
1231
1232     if (exc_normal != get_Block_exc (block))
1233       fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1234
1235     fprintf (F, "\" ");
1236     if (dump_dominator_information_flag)
1237       fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1238     fprintf (F, "}\n");
1239     /* Dump the edges */
1240     for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1241       if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1242         pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1243         fprintf (F, "edge: { sourcename: \"");
1244         PRINT_NODEID(block);
1245         fprintf (F, "\" targetname: \"");
1246         PRINT_NODEID(pred);
1247         fprintf (F, "\"}\n");
1248       }
1249
1250     /* Dump dominator edge */
1251     if (dump_dominator_information_flag && get_Block_idom(block)) {
1252       pred = get_Block_idom(block);
1253       fprintf (F, "edge: { sourcename: \"");
1254       PRINT_NODEID(block);
1255       fprintf (F, "\" targetname: \"");
1256       PRINT_NODEID(pred);
1257       fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1258     }
1259   }
1260 }
1261
1262 void
1263 dump_cfg (ir_graph *irg)
1264 {
1265   ir_graph *rem = current_ir_graph;
1266   int ddif = dump_dominator_information_flag;
1267   current_ir_graph = irg;
1268   vcg_open (irg, "-cfg");
1269
1270   if (get_irg_dom_state(irg) != dom_consistent)
1271     dump_dominator_information_flag = 0;
1272
1273   /* walk over the blocks in the graph */
1274   irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1275   dump_node (get_irg_bad(irg), NULL);
1276
1277   dump_dominator_information_flag = ddif;
1278   vcg_close();
1279   current_ir_graph = rem;
1280 }
1281
1282
1283 /***********************************************************************/
1284 /* the following routine dumps all type information reachable from an  */
1285 /* irg                                                                 */
1286 /***********************************************************************/
1287
1288
1289 void
1290 dump_type_graph (ir_graph *irg)
1291 {
1292   ir_graph *rem;
1293   rem = current_ir_graph;
1294   current_ir_graph = irg;
1295
1296   vcg_open (irg, "-type");
1297
1298   /* walk over the blocks in the graph */
1299   type_walk_irg(irg, dump_type_info, NULL, NULL);
1300   /* The walker for the const code can be called several times for the
1301      same (sub) experssion.  So that no nodes are dumped several times
1302      we decrease the visited flag of the corresponding graph after each
1303      walk.  So now increase it finally. */
1304   inc_irg_visited(get_const_code_irg());
1305
1306   vcg_close();
1307   current_ir_graph = rem;
1308 }
1309
1310 /***********************************************************************/
1311 /* the following routine dumps all type information                    */
1312 /***********************************************************************/
1313
1314
1315 void
1316 dump_all_types (void)
1317 {
1318   vcg_open_name ("All_types");
1319   type_walk(dump_type_info, NULL, NULL);
1320   inc_irg_visited(get_const_code_irg());
1321   vcg_close();
1322 }
1323
1324 void
1325 dump_class_hierarchy (bool entities)
1326 {
1327   vcg_open_name ("class_hierarchy");
1328   if (entities)
1329     type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1330   else
1331     type_walk(dump_class_hierarchy_node, NULL, NULL);
1332   vcg_close();
1333 }
1334
1335 /***********************************************************************/
1336 /* dumps a graph with type information                                 */
1337 /***********************************************************************/
1338
1339
1340 void
1341 dump_ir_graph_w_types (ir_graph *irg)
1342 {
1343   ir_graph *rem;
1344   rem = current_ir_graph;
1345   current_ir_graph = irg;
1346
1347   vcg_open (irg, "-all");
1348
1349   /* dump common ir graph */
1350   irg_walk(get_irg_end(irg), dump_whole_node, NULL, NULL);
1351   /* dump type info */
1352   type_walk_irg(irg, dump_type_info, NULL, NULL);
1353   inc_irg_visited(get_const_code_irg());
1354   /* dump edges from graph to type info */
1355   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1356
1357   vcg_close();
1358   current_ir_graph = rem;
1359 }
1360
1361 void
1362 dump_ir_block_graph_w_types (ir_graph *irg)
1363 {
1364   ir_graph *rem;
1365   rem = current_ir_graph;
1366   current_ir_graph = irg;
1367
1368   vcg_open (irg, "-all");
1369
1370   /* dump common blocked ir graph */
1371   dump_ir_block_graph_2(irg);
1372   /* dump type info */
1373   type_walk_irg(irg, dump_type_info, NULL, NULL);
1374   inc_irg_visited(get_const_code_irg());
1375   /* dump edges from graph to type info */
1376   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1377
1378   vcg_close();
1379   current_ir_graph = rem;
1380 }
1381
1382 /***********************************************************************/
1383 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
1384 /*  dump_ir_graph                                                      */
1385 /*  dump_ir_block_graph                                                */
1386 /*  dump_cfg                                                           */
1387 /*  dump_type_graph                                                    */
1388 /*  dump_ir_graph_w_types                                              */
1389 /***********************************************************************/
1390 void dump_all_ir_graphs (dump_graph_func *dump_graph) {
1391   int i;
1392   for (i=0; i < get_irp_n_irgs(); i++) {
1393     dump_graph(get_irp_irg(i));
1394   }
1395 }
1396
1397
1398 /* To turn off display of edge labels.  Edge labels offen cause xvcg to
1399    abort with a segmentation fault. */
1400 void turn_off_edge_labels(void) {
1401   edge_label = 0;
1402 }
1403
1404
1405 void dump_consts_local(bool b) {
1406   dump_const_local = b;
1407 }
1408
1409 void turn_off_constant_entity_values(void) {
1410   const_entities = 0;
1411 }
1412
1413 void dump_keepalive_edges(bool b) {
1414   dump_keepalive = b;
1415 }
1416
1417 bool get_opt_dump_keepalive_edges(void) {
1418   return dump_keepalive;
1419 }
1420
1421 void dump_out_edges(void) {
1422   dump_out_edge_flag = 1;
1423 }
1424
1425 void dump_dominator_information(void) {
1426   dump_dominator_information_flag = 1;
1427 }
1428
1429 void dump_loop_information(void) {
1430   dump_loop_information_flag = 1;
1431 }
1432
1433 void dont_dump_loop_information(void) {
1434   dump_loop_information_flag = 0;
1435 }
1436
1437 static void clear_link(ir_node * node, void * env) {
1438   set_irn_link(node, NULL);
1439 }
1440
1441
1442 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1443   assert(node); assert(map);
1444   if (is_Block(node)
1445       || node_floats(node)
1446       || get_irn_op(node) == op_Bad
1447       || get_irn_op(node) == op_Unknown) {
1448     pmap_entry * entry = pmap_find(map, current_ir_graph);
1449     if (entry)
1450     {
1451       ir_node ** arr;
1452       arr = entry->value;
1453       assert(arr);
1454       ARR_APP1(ir_node *, arr, node);
1455       entry->value = (void *)arr;
1456     } else {
1457       ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1458       assert(arr);
1459       arr[0] = node;
1460       pmap_insert(map, current_ir_graph, arr);
1461     }
1462   } else {
1463     ir_node * block = get_nodes_Block(node);
1464     set_irn_link(node, get_irn_link(block));
1465     set_irn_link(block, node);
1466   }
1467 }
1468
1469
1470 static void dump_cg_ir_block(ir_node * block, void * env) {
1471   ir_node *node;
1472   pmap *irgmap = (pmap *)env;
1473   assert(is_Block(block));
1474
1475   fprintf(F, "graph: { title: \"");
1476   PRINT_NODEID(block);
1477   fprintf(F, "\"  label: \"");
1478   dump_node_opcode(block);
1479   fprintf (F, " %ld", get_irn_node_nr(block));
1480
1481   if (exc_normal != get_Block_exc(block)) {
1482     fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1483   }
1484
1485   fprintf(F, "\" status:clustered color:%s \n",
1486            get_Block_matured(block) ? "yellow" : "red");
1487
1488   /* dump the blocks edges */
1489   dump_ir_data_edges(block, irgmap);
1490
1491   /* dump the nodes that go into the block */
1492   for (node = get_irn_link(block); node; node = get_irn_link(node)) {
1493     dump_node(node, irgmap);
1494     dump_ir_data_edges(node, irgmap);
1495   }
1496
1497   /* Close the vcg information for the block */
1498   fprintf(F, "}\n");
1499   dump_const_node_local(block, irgmap);
1500   fprintf(F, "\n");
1501 }
1502
1503 static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1504   int i;
1505
1506   fprintf(F, "graph: { title: \"%p\" label: \"%s\" status:clustered color:white \n",
1507            (void*) irg, get_entity_name(get_irg_ent(irg)));
1508
1509   for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1510     ir_node * node = arr[i];
1511     if (is_Block(node)) {
1512       /* Dumps the block and all the nodes in the block, which are to
1513          be found in Block->link. */
1514       dump_cg_ir_block(node, irgmap);
1515     } else {
1516       /* Nodes that are not in a Block. */
1517       dump_node(node, NULL);
1518       dump_ir_data_edges(node, NULL);
1519     }
1520   }
1521   /* Close the vcg information for the irg */
1522   fprintf(F, "}\n\n");
1523 }
1524
1525 /* dump interprocedural graph with surrounding methods */
1526 void dump_cg_block_graph(ir_graph * irg) {
1527   pmap * map = pmap_create();
1528   pmap * map2 = pmap_create();
1529   pmap_entry * entry;
1530
1531   vcg_open(irg, "");
1532
1533   irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1534   for (entry = pmap_first(map); entry; entry = pmap_next(map))
1535     pmap_insert(map2, entry->key, entry->value);
1536   for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1537     d_cg_block_graph(entry->key, entry->value, map2);
1538     DEL_ARR_F(entry->value);
1539   }
1540
1541   pmap_destroy(map);
1542   pmap_destroy(map2);
1543
1544   if (dump_loop_information_flag) dump_loop_info(irg);
1545   vcg_close();
1546 }
1547
1548 static void collect_node(ir_node * node, void *env) {
1549   if (is_Block(node)
1550       || node_floats(node)
1551       || get_irn_op(node) == op_Bad
1552       || get_irn_op(node) == op_Unknown) {
1553     ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1554     ARR_APP1(ir_node *, arr, node);
1555     set_irg_link(current_ir_graph, arr);    /* arr is an l-value, APP_ARR might change it! */
1556   } else {
1557     ir_node * block = get_nodes_Block(node);
1558     set_irn_link(node, get_irn_link(block));
1559     set_irn_link(block, node);
1560   }
1561 }
1562
1563 /* Links all nodes that have the block field set in the link field of
1564    the block.  Adds all blocks and nodes not associated with a block
1565    in a array in irg->link. */
1566 static void collect_nodes(void) {
1567   int i;
1568   for (i = 0; i < get_irp_n_irgs(); i++)
1569     set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1570   cg_walk(clear_link, collect_node, NULL);
1571 }
1572
1573 static void dump_graphs(void) {
1574   int i;
1575   for (i = 0; i < get_irp_n_irgs(); i++) {
1576     current_ir_graph = get_irp_irg(i);
1577     d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1578   }
1579 }
1580
1581 /* Dump all irgs in interprocedural view to a single file. */
1582 void dump_all_cg_block_graph(void) {
1583   int i;
1584   int rem_view = interprocedural_view;
1585   interprocedural_view = 1;
1586   vcg_open_name ("All_graphs");
1587
1588   collect_nodes();
1589   dump_graphs();
1590
1591   if (dump_loop_information_flag)
1592     for (i = 0; i < get_irp_n_irgs(); i++)
1593       dump_loop_info(get_irp_irg(i));
1594
1595   vcg_close();
1596   interprocedural_view = rem_view;
1597 }
1598
1599 /* dump interprocedural block graph with surrounding methods */
1600 void dump_cg_graph(ir_graph * irg) {
1601   pmap * map = pmap_create();
1602   pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1603   pmap_entry * entry;
1604   vcg_open(irg, "");
1605
1606   irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1607   for (entry = pmap_first(map); entry; entry = pmap_next(map))
1608     pmap_insert(map2, entry->key, entry->value);
1609   for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1610     ir_node ** arr = entry->value;
1611     int i;
1612     ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1613
1614     fprintf(F, "graph: { title: %s label: %s status:clustered color:white \n",
1615              get_id_str(irg_ident), get_id_str(irg_ident));
1616
1617     for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1618       ir_node * node = arr[i];
1619       dump_node(node, map2);
1620       dump_ir_data_edges(node, NULL);
1621       if (is_Block(node)) {
1622         for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1623           dump_node(node, map2);
1624           dump_ir_block_edge(node);
1625           dump_ir_data_edges(node, NULL);
1626         }
1627       }
1628     }
1629
1630     DEL_ARR_F(arr);
1631
1632     /* Close the vcg information for the irg */
1633     fprintf(F, "}\n\n");
1634   }
1635
1636   pmap_destroy(map);
1637   pmap_destroy(map2);
1638
1639   vcg_close();
1640 }
1641
1642 /* Dump the information of type field specified in ana/irtypeinfo.h.
1643  * If the flag is set, the type name is output in [] in the node label,
1644  * else it is output as info.
1645  */
1646 void dump_analysed_type_info(bool b) {
1647   opt_dump_analysed_type_info = b;
1648 }