loop info
[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       PRINT_CONSTID(n, pred);
551     } else {
552       fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
553     }
554     fprintf (F, " label: \"%d\" ", i);
555     print_edge_vcgattr(n, i);
556     fprintf (F, "}\n");
557   }
558 }
559
560 /* dump out edges */
561 static void
562 dump_out_edge (ir_node *n, void* env) {
563   int i;
564   for (i = 0; i < get_irn_n_outs(n); i++) {
565     assert(get_irn_out(n, i));
566     fprintf (F, "edge: {sourcename: \"");
567     PRINT_NODEID(n);
568     fprintf (F, "\" targetname: \"");
569     PRINT_NODEID(get_irn_out(n, i));
570     fprintf (F, "\" color: red linestyle: dashed");
571     fprintf (F, "}\n");
572   }
573 }
574
575 static INLINE void
576 dump_loop_node_edge (ir_loop *loop, int i) {
577   assert(loop);
578   fprintf (F, "edge: {sourcename: \"%p\" targetname: \"", (void*) loop);
579   PRINT_NODEID(get_loop_node(loop, i));
580   fprintf (F, "\" color: green");
581   fprintf (F, "}\n");
582 }
583
584 static INLINE void
585 dump_loop_son_edge (ir_loop *loop, int i) {
586   assert(loop);
587   fprintf (F, "edge: {sourcename: \"%p\" targetname: \"%p\" color: darkgreen}\n",
588            (void *)loop, (void *)get_loop_son(loop, i));
589 }
590
591 static
592 void dump_loops (ir_loop *loop) {
593   int i;
594   /* dump this loop node */
595   fprintf (F, "node: {title: \"%p\" label: \"loop %d, %d sons, %d nodes\" }\n",
596             (void*)loop, get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
597   /* dump edges to nodes in loop -- only if it is a real loop */
598   if (get_loop_depth(loop) != 0) {
599     for (i = 0; i < get_loop_n_nodes(loop); i++) {
600       dump_loop_node_edge(loop, i);
601     }
602   }
603   for (i = 0; i < get_loop_n_sons(loop); i++) {
604     dump_loops(get_loop_son(loop, i));
605     dump_loop_son_edge(loop, i);
606   }
607 }
608
609 static INLINE
610 void dump_loop_info(ir_graph *irg) {
611   ir_graph *rem = current_ir_graph;
612   current_ir_graph = irg;
613
614   if (get_irg_loop(irg))
615     dump_loops(get_irg_loop(irg));
616
617   current_ir_graph = rem;
618 }
619
620
621 /* dumps the edges between nodes and their type or entity attributes. */
622 static void dump_node2type_edges (ir_node *n, void *env)
623 {
624   assert(n);
625
626   switch (get_irn_opcode(n)) {
627   case iro_Const :
628     /* @@@ some consts have an entity */
629     break;
630   case iro_SymConst:
631     if (   (get_SymConst_kind(n) == type_tag)
632            || (get_SymConst_kind(n) == size))
633       {
634         PRINT_NODE_TYPE_EDGE(n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
635       }
636     break;
637   case iro_Sel: {
638       PRINT_NODE_ENT_EDGE(n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
639     } break;
640   case iro_Call: {
641       PRINT_NODE_TYPE_EDGE(n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
642     } break;
643   case iro_Alloc: {
644       PRINT_NODE_TYPE_EDGE(n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
645     } break;
646   case iro_Free: {
647       PRINT_NODE_TYPE_EDGE(n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
648     } break;
649   case iro_Cast: {
650       PRINT_NODE_TYPE_EDGE(n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
651     } break;
652   default:
653     break;
654   }
655 }
656
657
658 static void dump_const_expression(ir_node *value) {
659   ir_graph *rem = current_ir_graph;
660   int rem_dump_const_local = dump_const_local;
661   dump_const_local = 0;
662   current_ir_graph = get_const_code_irg();
663   irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
664   /* Decrease visited flag so that we walk with the same flag for the next
665      expresssion.  This guarantees that we don't dump the same node twice,
666      as for const expressions cse is performed to save memory. */
667   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
668   current_ir_graph = rem;
669   dump_const_local = rem_dump_const_local;
670 }
671
672
673 static void print_type_info(type *tp) {
674   if (get_type_state(tp) == layout_undefined) {
675     fprintf(F, "state: layout_undefined\n");
676   } else {
677     fprintf(F, "state: layout_fixed,\n");
678   }
679   if (get_type_mode(tp))
680     fprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
681   fprintf(F, "size: %dB,\n", get_type_size(tp));
682 }
683
684
685 static void print_typespecific_info(type *tp) {
686   switch (get_type_tpop_code(tp)) {
687   case tpo_class:
688     {
689       if (peculiarity_existent == get_class_peculiarity(tp))
690         fprintf (F, " " TYPE_CLASS_NODE_ATTR);
691       else
692         fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
693     } break;
694   case tpo_struct:
695     {
696       fprintf (F, " " TYPE_METH_NODE_ATTR);
697     } break;
698   case tpo_method:
699     {
700     } break;
701   case tpo_union:
702     {
703     } break;
704   case tpo_array:
705     {
706     } break;
707   case tpo_enumeration:
708     {
709     } break;
710   case tpo_pointer:
711     {
712     } break;
713   case tpo_primitive:
714     {
715     } break;
716   default: break;
717   } /* switch type */
718 }
719
720 static void print_type_node(type *tp)
721 {
722   fprintf (F, "node: {title: ");
723   PRINT_TYPEID(tp);
724   fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name(tp));
725   fprintf (F, " info1: \"");
726   print_type_info(tp);
727   fprintf (F, "\"");
728   print_typespecific_info(tp);
729   fprintf (F, "}\n");
730 }
731
732 #define X(a)    case a: fprintf(F, #a); break
733 void dump_entity_node(entity *ent)
734 {
735   fprintf (F, "node: {title: \"");
736   PRINT_ENTID(ent); fprintf(F, "\"");
737   fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
738   fprintf (F, "label: ");
739   fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_entity_name(ent));
740   fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
741
742   fprintf (F, "\nallocation:  ");
743   switch (get_entity_allocation(ent)) {
744     X(allocation_dynamic);
745     X(allocation_automatic);
746     X(allocation_static);
747     X(allocation_parameter);
748   }
749
750   fprintf (F, "\nvisibility:  ");
751   switch (get_entity_visibility(ent)) {
752     X(visibility_local);
753     X(visibility_external_visible);
754     X(visibility_external_allocated);
755   }
756
757   fprintf (F, "\nvariability: ");
758   switch (get_entity_variability(ent)) {
759     X(variability_uninitialized);
760     X(variability_initialized);
761     X(variability_part_constant);
762     X(variability_constant);
763   }
764
765   fprintf (F, "\nvolatility:  ");
766   switch (get_entity_volatility(ent)) {
767     X(volatility_non_volatile);
768     X(volatility_is_volatile);
769   }
770
771   fprintf (F, "\npeculiarity: ");
772   switch (get_entity_peculiarity(ent)) {
773     X(peculiarity_description);
774     X(peculiarity_inherited);
775     X(peculiarity_existent);
776   }
777   fprintf(F, "\nname:    %s\nld_name: %s",
778           get_entity_name(ent), get_entity_ld_name(ent));
779   fprintf(F, "\noffset:  %d", get_entity_offset(ent));
780   if (is_method_type(get_entity_type(ent))) {
781     if (get_entity_irg(ent))   /* can be null */
782       { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
783     else
784       { fprintf (F, "\nirg = NULL"); }
785   }
786   fprintf(F, "\"\n}\n");
787 }
788 #undef X
789
790 /* dumps a type or entity and it's edges. */
791 static void
792 dump_type_info (type_or_ent *tore, void *env) {
793   int i = 0;  /* to shutup gcc */
794
795   /* dump this type or entity */
796
797   switch (get_kind(tore)) {
798   case k_entity:
799     {
800       entity *ent = (entity *)tore;
801       ir_node *value;
802       /* The node */
803       dump_entity_node(ent);
804       /* The Edges */
805       /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
806       fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
807                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
808       PRINT_ENT_TYPE_EDGE(ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
809       if(is_class_type(get_entity_owner(ent))) {
810         for(i = 0; i < get_entity_n_overwrites(ent); i++){
811           PRINT_ENT_ENT_EDGE(ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
812         }
813       }
814       /* attached subgraphs */
815       if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
816         if (is_atomic_entity(ent)) {
817           value = get_atomic_ent_value(ent);
818           if (value) {
819             PRINT_ENT_NODE_EDGE(ent, value, ENT_VALUE_EDGE_ATTR, i);
820             /* DDMN(value);  $$$ */
821             dump_const_expression(value);
822           }
823         }
824         if (is_compound_entity(ent)) {
825           for (i = 0; i < get_compound_ent_n_values(ent); i++) {
826             value = get_compound_ent_value(ent, i);
827             if (value) {
828               PRINT_ENT_NODE_EDGE(ent,value,ENT_VALUE_EDGE_ATTR,i);
829               dump_const_expression(value);
830               PRINT_ENT_ENT_EDGE(ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
831               /*
832                 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
833                 ENT_CORR_EDGE_ATTR  "}\n", GET_ENTID(ent),
834                 get_compound_ent_value_member(ent, i), i);
835               */
836             }
837           }
838         }
839       }
840     } break;
841   case k_type:
842     {
843       type *tp = (type *)tore;
844       print_type_node(tp);
845       /* and now the edges */
846       switch (get_type_tpop_code(tp)) {
847       case tpo_class:
848         {
849           for (i=0; i < get_class_n_supertypes(tp); i++) {
850             PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
851           }
852
853           for (i=0; i < get_class_n_members(tp); i++) {
854             PRINT_TYPE_ENT_EDGE(tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
855           }
856         } break;
857       case tpo_struct:
858         {
859           for (i=0; i < get_struct_n_members(tp); i++) {
860             PRINT_TYPE_ENT_EDGE(tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
861           }
862         } break;
863       case tpo_method:
864         {
865           for (i = 0; i < get_method_n_params(tp); i++)
866           {
867                   PRINT_TYPE_TYPE_EDGE(tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
868           }
869           for (i = 0; i < get_method_n_ress(tp); i++)
870           {
871                   PRINT_TYPE_TYPE_EDGE(tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
872           }
873         } break;
874       case tpo_union:
875         {
876           for (i = 0; i < get_union_n_members(tp); i++)
877           {
878                   PRINT_TYPE_ENT_EDGE(tp,get_union_member(tp, i),UNION_EDGE_ATTR);
879           }
880         } break;
881       case tpo_array:
882         {
883                   PRINT_TYPE_TYPE_EDGE(tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
884                   PRINT_TYPE_ENT_EDGE(tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
885                   for (i = 0; i < get_array_n_dimensions(tp); i++) {
886                     ir_node *upper = get_array_upper_bound(tp, i);
887                     ir_node *lower = get_array_lower_bound(tp, i);
888                     PRINT_NODE_TYPE_EDGE(upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
889                     PRINT_NODE_TYPE_EDGE(lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
890                     dump_const_expression(upper);
891                     dump_const_expression(lower);
892                   }
893
894         } break;
895       case tpo_enumeration:
896         {
897         } break;
898       case tpo_pointer:
899         {
900                   PRINT_TYPE_TYPE_EDGE(tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
901         } break;
902       case tpo_primitive:
903         {
904         } break;
905       default: break;
906       } /* switch type */
907     }
908     break; /* case k_type */
909   default:
910     {
911       printf(" *** irdump,  dump_type_info(l.%i), faulty type.\n", __LINE__);
912     } break;
913   } /* switch kind_or_entity */
914 }
915
916 /* dumps a class type node and a superclass edge.
917    If env != null dumps entities of classes and overwrites edges. */
918 static void
919 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
920   int i = 0;  /* to shutup gcc */
921
922   /* dump this type or entity */
923   switch (get_kind(tore)) {
924   case k_entity: {
925     entity *ent = (entity *)tore;
926     if (get_entity_owner(ent) == get_glob_type()) break;
927     if ((env) && is_class_type(get_entity_owner(ent))) {
928       /* The node */
929       dump_entity_node(ent);
930       /* The edges */
931       PRINT_TYPE_ENT_EDGE(get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
932       for(i = 0; i < get_entity_n_overwrites(ent); i++)
933       {
934       PRINT_ENT_ENT_EDGE(get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
935       }
936     }
937   } break; /* case k_entity */
938   case k_type:
939     {
940       type *tp = (type *)tore;
941       if (tp == get_glob_type()) break;
942       switch (get_type_tpop_code(tp)) {
943         case tpo_class: {
944           print_type_node(tp);
945           /* and now the edges */
946           for (i=0; i < get_class_n_supertypes(tp); i++)
947           {
948                   PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
949           }
950         } break;
951         default: break;
952       } /* switch type */
953     }
954     break; /* case k_type */
955   default:
956     {
957       printf(" *** irdump,  dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
958     } break;
959   } /* switch kind_or_entity */
960 }
961
962 /************************************************************************/
963 /* open and close vcg file                                              */
964 /************************************************************************/
965
966 static void vcg_open (ir_graph *irg, char *suffix) {
967   char *fname;  /* filename to put the vcg information in */
968   const char *cp;
969   ident *id;
970   int len;
971   char label[4];
972   entity *ent;
973
974   /** open file for vcg graph */
975   ent = get_irg_ent(irg);
976   id    = ent->ld_name ? ent->ld_name : ent->name;
977   /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
978   len   = get_id_strlen (id);
979   cp    = get_id_str (id);
980   if (dump_file_suffix)
981     fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
982   else
983     fname = malloc (len + 5 + strlen(suffix));
984   strncpy (fname, cp, len);      /* copy the filename */
985   fname[len] = '\0';
986   if (dump_file_suffix) strcat (fname, dump_file_suffix);  /* append file suffix */
987   strcat (fname, suffix);  /* append file suffix */
988   strcat (fname, ".vcg");   /* append the .vcg suffix */
989   F = fopen (fname, "w");   /* open file for writing */
990   if (!F) {
991     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
992   }
993
994   if (edge_label) {
995     strcpy(label, "yes");
996   } else {
997     strcpy (label, "no");
998   }
999
1000   /* print header */
1001   fprintf (F,
1002             "graph: { title: \"ir graph of %s\"\n"
1003             "display_edge_labels: %s\n"
1004             "layoutalgorithm: mindepth\n"
1005             "manhattan_edges: yes\n"
1006             "port_sharing: no\n"
1007             "orientation: bottom_to_top\n"
1008             "classname 1: \"Data\"\n"
1009             "classname 2: \"Block\"\n"
1010             "classname 3: \"Entity type\"\n"
1011             "classname 4: \"Entity owner\"\n"
1012             "classname 5: \"Method Param\"\n"
1013             "classname 6: \"Method Res\"\n"
1014             "classname 7: \"Super\"\n"
1015             "classname 8: \"Union\"\n"
1016             "classname 9: \"Points-to\"\n"
1017             "classname 10: \"Array Element Type\"\n"
1018             "classname 11: \"Overwrites\"\n"
1019             "classname 12: \"Member\"\n"
1020             , cp, label);
1021
1022   fprintf (F, "\n");            /* a separator */
1023 }
1024
1025 static void vcg_open_name (const char *name) {
1026   char *fname;  /* filename to put the vcg information in */
1027   int len;
1028   char label[4];
1029
1030   /** open file for vcg graph */
1031   len   = strlen(name);
1032   fname = malloc (len + 5);
1033   if (dump_file_suffix)
1034     fname = malloc (len + 5 + strlen(dump_file_suffix));
1035   else
1036     fname = malloc (len + 5);
1037   strcpy (fname, name);    /* copy the filename */
1038   if (dump_file_suffix) strcat (fname, dump_file_suffix);
1039   strcat (fname, ".vcg");  /* append the .vcg suffix */
1040   F = fopen (fname, "w");  /* open file for writing */
1041   if (!F) {
1042     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
1043   }
1044
1045   if (edge_label) {
1046     strcpy(label, "yes");
1047   } else {
1048     strcpy (label, "no");
1049   }
1050
1051   /* print header */
1052   fprintf (F,
1053             "graph: { title: \"ir graph of %s\"\n"
1054             "display_edge_labels: %s\n"
1055             "layoutalgorithm: mindepth\n"
1056             "manhattan_edges: yes\n"
1057             "port_sharing: no\n"
1058             "orientation: bottom_to_top\n"
1059             "classname 1: \"Data\"\n"
1060             "classname 2: \"Block\"\n"
1061             "classname 3: \"Entity type\"\n"
1062             "classname 4: \"Entity owner\"\n"
1063             "classname 5: \"Method Param\"\n"
1064             "classname 6: \"Method Res\"\n"
1065             "classname 7: \"Super\"\n"
1066             "classname 8: \"Union\"\n"
1067             "classname 9: \"Points-to\"\n"
1068             "classname 10: \"Array Element Type\"\n"
1069             "classname 11: \"Overwrites\"\n"
1070             "classname 12: \"Member\"\n"
1071             , name, label);
1072
1073   fprintf (F, "\n");            /* a separator */
1074 }
1075
1076 static void
1077 vcg_close (void) {
1078   fprintf (F, "}\n");  /* print footer */
1079   fclose (F);           /* close vcg file */
1080 }
1081
1082 /************************************************************************/
1083 /* routines to dump a graph, blocks as conventional nodes.              */
1084 /************************************************************************/
1085
1086 static int node_floats(ir_node *n) {
1087   return ((get_op_pinned(get_irn_op(n)) == floats) &&
1088           (get_irg_pinned(current_ir_graph) == floats));
1089 }
1090
1091 static void
1092 dump_whole_node (ir_node *n, void* env) {
1093   dump_node(n, NULL);
1094   if (!node_floats(n)) dump_ir_block_edge(n);
1095   dump_ir_data_edges(n, NULL);
1096 }
1097
1098 void
1099 dump_ir_graph (ir_graph *irg)
1100 {
1101   ir_graph *rem;
1102   rem = current_ir_graph;
1103   current_ir_graph = irg;
1104
1105   vcg_open (irg, "");
1106
1107   /* walk over the graph */
1108   /* dump_whole_node must be called in post visiting predecessors */
1109   irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1110
1111   /* dump the out edges in a separate walk */
1112   if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1113     irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1114   }
1115
1116   vcg_close();
1117
1118   current_ir_graph = rem;
1119 }
1120
1121 /***********************************************************************/
1122 /* the following routines dump the nodes as attached to the blocks.    */
1123 /***********************************************************************/
1124
1125 static void
1126 dump_ir_blocks_nodes (ir_node *n, void *env) {
1127   ir_node *block = (ir_node *)env;
1128
1129   if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1130     dump_node(n, NULL);
1131     dump_ir_data_edges(n, NULL);
1132   }
1133   if (get_irn_op(n) == op_Bad)
1134     Bad_dumped = 1;
1135 }
1136
1137 static void
1138 dump_ir_block (ir_node *block, void *env) {
1139   ir_graph *irg = (ir_graph *)env;
1140
1141   if (get_irn_opcode(block) == iro_Block) {
1142
1143     /* This is a block. So dump the vcg information to make a block. */
1144     fprintf(F, "graph: { title: \"");
1145         PRINT_NODEID(block);
1146         fprintf(F, "\" label: \"");
1147 #ifdef DEBUG_libfirm
1148     fprintf (F, "%ld", get_irn_node_nr(block));
1149 #else
1150     fprintf (F, "%s", get_op_name(get_irn_op(block)));
1151 #endif
1152     if (exc_normal != get_Block_exc (block))
1153       fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1154
1155     fprintf(F, "\" status:clustered color:%s \n",
1156              get_Block_matured (block) ? "yellow" : "red");
1157     /* dump the blocks edges */
1158     dump_ir_data_edges(block, NULL);
1159
1160     /* dump the nodes that go into the block */
1161     irg_walk(get_irg_end(irg), dump_ir_blocks_nodes, NULL, block);
1162
1163     /* Close the vcg information for the block */
1164     fprintf(F, "}\n\n");
1165     dump_const_node_local(block, NULL);
1166   }
1167 }
1168
1169
1170 static void
1171 dump_blockless_nodes (ir_node *n, void *env) {
1172   if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1173     dump_node(n, NULL);
1174     dump_ir_data_edges(n, NULL);
1175     dump_ir_block_edge(n);
1176     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1177     return;
1178   }
1179   if (node_floats(n)) {
1180     dump_node(n, NULL);
1181     dump_ir_data_edges(n, NULL);
1182     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1183   }
1184 }
1185
1186 static void dump_ir_block_graph_2  (ir_graph *irg)
1187 {
1188   Bad_dumped = 0;
1189   /* walk over the blocks in the graph */
1190   irg_block_walk(get_irg_end(irg), dump_ir_block, NULL, irg);
1191
1192   /* dump all nodes that are not in a Block */
1193   irg_walk(get_irg_end(irg), dump_blockless_nodes, NULL, NULL);
1194
1195   /* dump the Bad node */
1196   if (!Bad_dumped)
1197     dump_node(get_irg_bad(irg), NULL);
1198 }
1199
1200 void
1201 dump_ir_block_graph (ir_graph *irg)
1202 {
1203   ir_graph *rem;
1204   rem = current_ir_graph;
1205   current_ir_graph = irg;
1206
1207   vcg_open (irg, "");
1208
1209   dump_ir_block_graph_2 (irg);
1210
1211   if (dump_loop_information_flag) dump_loop_info(irg);
1212
1213   vcg_close();
1214   current_ir_graph = rem;
1215 }
1216
1217
1218 /***********************************************************************/
1219 /* the following routines dump a control flow graph                    */
1220 /***********************************************************************/
1221
1222
1223 static void
1224 dump_block_to_cfg (ir_node *block, void *env) {
1225   int i;
1226   ir_node *pred;
1227
1228   if (get_irn_opcode(block) == iro_Block) {
1229     /* This is a block. Dump a node for the block. */
1230     fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1231     fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1232 #ifdef DEBUG_libfirm
1233     fprintf (F, "%ld", get_irn_node_nr(block));
1234 #else
1235     fprintf (F, "%p", (void*) block);
1236 #endif
1237
1238     if (exc_normal != get_Block_exc (block))
1239       fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1240
1241     fprintf (F, "\" ");
1242     if (dump_dominator_information_flag)
1243       fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1244     fprintf (F, "}\n");
1245     /* Dump the edges */
1246     for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1247       if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1248         pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1249         fprintf (F, "edge: { sourcename: \"");
1250         PRINT_NODEID(block);
1251         fprintf (F, "\" targetname: \"");
1252         PRINT_NODEID(pred);
1253         fprintf (F, "\"}\n");
1254       }
1255
1256     /* Dump dominator edge */
1257     if (dump_dominator_information_flag && get_Block_idom(block)) {
1258       pred = get_Block_idom(block);
1259       fprintf (F, "edge: { sourcename: \"");
1260       PRINT_NODEID(block);
1261       fprintf (F, "\" targetname: \"");
1262       PRINT_NODEID(pred);
1263       fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1264     }
1265   }
1266 }
1267
1268 void
1269 dump_cfg (ir_graph *irg)
1270 {
1271   ir_graph *rem = current_ir_graph;
1272   int ddif = dump_dominator_information_flag;
1273   current_ir_graph = irg;
1274   vcg_open (irg, "-cfg");
1275
1276   if (get_irg_dom_state(irg) != dom_consistent)
1277     dump_dominator_information_flag = 0;
1278
1279   /* walk over the blocks in the graph */
1280   irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1281   dump_node (get_irg_bad(irg), NULL);
1282
1283   dump_dominator_information_flag = ddif;
1284   vcg_close();
1285   current_ir_graph = rem;
1286 }
1287
1288
1289 /***********************************************************************/
1290 /* the following routine dumps all type information reachable from an  */
1291 /* irg                                                                 */
1292 /***********************************************************************/
1293
1294
1295 void
1296 dump_type_graph (ir_graph *irg)
1297 {
1298   ir_graph *rem;
1299   rem = current_ir_graph;
1300   current_ir_graph = irg;
1301
1302   vcg_open (irg, "-type");
1303
1304   /* walk over the blocks in the graph */
1305   type_walk_irg(irg, dump_type_info, NULL, NULL);
1306   /* The walker for the const code can be called several times for the
1307      same (sub) experssion.  So that no nodes are dumped several times
1308      we decrease the visited flag of the corresponding graph after each
1309      walk.  So now increase it finally. */
1310   inc_irg_visited(get_const_code_irg());
1311
1312   vcg_close();
1313   current_ir_graph = rem;
1314 }
1315
1316 /***********************************************************************/
1317 /* the following routine dumps all type information                    */
1318 /***********************************************************************/
1319
1320
1321 void
1322 dump_all_types (void)
1323 {
1324   vcg_open_name ("All_types");
1325   type_walk(dump_type_info, NULL, NULL);
1326   inc_irg_visited(get_const_code_irg());
1327   vcg_close();
1328 }
1329
1330 void
1331 dump_class_hierarchy (bool entities)
1332 {
1333   vcg_open_name ("class_hierarchy");
1334   if (entities)
1335     type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1336   else
1337     type_walk(dump_class_hierarchy_node, NULL, NULL);
1338   vcg_close();
1339 }
1340
1341 /***********************************************************************/
1342 /* dumps a graph with type information                                 */
1343 /***********************************************************************/
1344
1345
1346 void
1347 dump_ir_graph_w_types (ir_graph *irg)
1348 {
1349   ir_graph *rem;
1350   rem = current_ir_graph;
1351   current_ir_graph = irg;
1352
1353   vcg_open (irg, "-all");
1354
1355   /* dump common ir graph */
1356   irg_walk(get_irg_end(irg), dump_whole_node, NULL, NULL);
1357   /* dump type info */
1358   type_walk_irg(irg, dump_type_info, NULL, NULL);
1359   inc_irg_visited(get_const_code_irg());
1360   /* dump edges from graph to type info */
1361   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1362
1363   vcg_close();
1364   current_ir_graph = rem;
1365 }
1366
1367 void
1368 dump_ir_block_graph_w_types (ir_graph *irg)
1369 {
1370   ir_graph *rem;
1371   rem = current_ir_graph;
1372   current_ir_graph = irg;
1373
1374   vcg_open (irg, "-all");
1375
1376   /* dump common blocked ir graph */
1377   dump_ir_block_graph_2(irg);
1378   /* dump type info */
1379   type_walk_irg(irg, dump_type_info, NULL, NULL);
1380   inc_irg_visited(get_const_code_irg());
1381   /* dump edges from graph to type info */
1382   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1383
1384   vcg_close();
1385   current_ir_graph = rem;
1386 }
1387
1388 /***********************************************************************/
1389 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
1390 /*  dump_ir_graph                                                      */
1391 /*  dump_ir_block_graph                                                */
1392 /*  dump_cfg                                                           */
1393 /*  dump_type_graph                                                    */
1394 /*  dump_ir_graph_w_types                                              */
1395 /***********************************************************************/
1396 void dump_all_ir_graphs (dump_graph_func *dump_graph) {
1397   int i;
1398   for (i=0; i < get_irp_n_irgs(); i++) {
1399     dump_graph(get_irp_irg(i));
1400   }
1401 }
1402
1403
1404 /* To turn off display of edge labels.  Edge labels offen cause xvcg to
1405    abort with a segmentation fault. */
1406 void turn_off_edge_labels(void) {
1407   edge_label = 0;
1408 }
1409
1410
1411 void dump_consts_local(bool b) {
1412   dump_const_local = b;
1413 }
1414
1415 void turn_off_constant_entity_values(void) {
1416   const_entities = 0;
1417 }
1418
1419 void dump_keepalive_edges(bool b) {
1420   dump_keepalive = b;
1421 }
1422
1423 bool get_opt_dump_keepalive_edges(void) {
1424   return dump_keepalive;
1425 }
1426
1427 void dump_out_edges(void) {
1428   dump_out_edge_flag = 1;
1429 }
1430
1431 void dump_dominator_information(void) {
1432   dump_dominator_information_flag = 1;
1433 }
1434
1435 void dump_loop_information(void) {
1436   dump_loop_information_flag = 1;
1437 }
1438
1439 void dont_dump_loop_information(void) {
1440   dump_loop_information_flag = 0;
1441 }
1442
1443 static void clear_link(ir_node * node, void * env) {
1444   set_irn_link(node, NULL);
1445 }
1446
1447
1448 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1449   assert(node); assert(map);
1450   if (is_Block(node)
1451       || node_floats(node)
1452       || get_irn_op(node) == op_Bad
1453       || get_irn_op(node) == op_Unknown) {
1454     pmap_entry * entry = pmap_find(map, current_ir_graph);
1455     if (entry)
1456     {
1457       ir_node ** arr;
1458       arr = entry->value;
1459       assert(arr);
1460       ARR_APP1(ir_node *, arr, node);
1461       entry->value = (void *)arr;
1462     } else {
1463       ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1464       assert(arr);
1465       arr[0] = node;
1466       pmap_insert(map, current_ir_graph, arr);
1467     }
1468   } else {
1469     ir_node * block = get_nodes_Block(node);
1470     set_irn_link(node, get_irn_link(block));
1471     set_irn_link(block, node);
1472   }
1473 }
1474
1475
1476 static void dump_cg_ir_block(ir_node * block, void * env) {
1477   ir_node *node;
1478   pmap *irgmap = (pmap *)env;
1479   assert(is_Block(block));
1480
1481   fprintf(F, "graph: { title: \"");
1482   PRINT_NODEID(block);
1483   fprintf(F, "\"  label: \"");
1484   dump_node_opcode(block);
1485   fprintf (F, " %ld", get_irn_node_nr(block));
1486
1487   if (exc_normal != get_Block_exc(block)) {
1488     fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1489   }
1490
1491   fprintf(F, "\" status:clustered color:%s \n",
1492            get_Block_matured(block) ? "yellow" : "red");
1493
1494   /* dump the blocks edges */
1495   dump_ir_data_edges(block, irgmap);
1496
1497   /* dump the nodes that go into the block */
1498   for (node = get_irn_link(block); node; node = get_irn_link(node)) {
1499     dump_node(node, irgmap);
1500     dump_ir_data_edges(node, irgmap);
1501   }
1502
1503   /* Close the vcg information for the block */
1504   fprintf(F, "}\n");
1505   dump_const_node_local(block, irgmap);
1506   fprintf(F, "\n");
1507 }
1508
1509 static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1510   int i;
1511
1512   fprintf(F, "graph: { title: \"%p\" label: \"%s\" status:clustered color:white \n",
1513            (void*) irg, get_entity_name(get_irg_ent(irg)));
1514
1515   for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1516     ir_node * node = arr[i];
1517     if (is_Block(node)) {
1518       /* Dumps the block and all the nodes in the block, which are to
1519          be found in Block->link. */
1520       dump_cg_ir_block(node, irgmap);
1521     } else {
1522       /* Nodes that are not in a Block. */
1523       dump_node(node, NULL);
1524       dump_ir_data_edges(node, NULL);
1525     }
1526   }
1527   /* Close the vcg information for the irg */
1528   fprintf(F, "}\n\n");
1529 }
1530
1531 /* dump interprocedural graph with surrounding methods */
1532 void dump_cg_block_graph(ir_graph * irg) {
1533   pmap * map = pmap_create();
1534   pmap * map2 = pmap_create();
1535   pmap_entry * entry;
1536
1537   vcg_open(irg, "");
1538
1539   irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1540   for (entry = pmap_first(map); entry; entry = pmap_next(map))
1541     pmap_insert(map2, entry->key, entry->value);
1542   for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1543     d_cg_block_graph(entry->key, entry->value, map2);
1544     DEL_ARR_F(entry->value);
1545   }
1546
1547   pmap_destroy(map);
1548   pmap_destroy(map2);
1549
1550   if (dump_loop_information_flag) dump_loop_info(irg);
1551   vcg_close();
1552 }
1553
1554 static void collect_node(ir_node * node, void *env) {
1555   if (is_Block(node)
1556       || node_floats(node)
1557       || get_irn_op(node) == op_Bad
1558       || get_irn_op(node) == op_Unknown) {
1559     ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1560     ARR_APP1(ir_node *, arr, node);
1561     set_irg_link(current_ir_graph, arr);    /* arr is an l-value, APP_ARR might change it! */
1562   } else {
1563     ir_node * block = get_nodes_Block(node);
1564     set_irn_link(node, get_irn_link(block));
1565     set_irn_link(block, node);
1566   }
1567 }
1568
1569 /* Links all nodes that have the block field set in the link field of
1570    the block.  Adds all blocks and nodes not associated with a block
1571    in a array in irg->link. */
1572 static void collect_nodes(void) {
1573   int i;
1574   for (i = 0; i < get_irp_n_irgs(); i++)
1575     set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1576   cg_walk(clear_link, collect_node, NULL);
1577 }
1578
1579 static void dump_graphs(void) {
1580   int i;
1581   for (i = 0; i < get_irp_n_irgs(); i++) {
1582     current_ir_graph = get_irp_irg(i);
1583     d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1584   }
1585 }
1586
1587 /* Dump all irgs in interprocedural view to a single file. */
1588 void dump_all_cg_block_graph(void) {
1589   int i;
1590   int rem_view = interprocedural_view;
1591   interprocedural_view = 1;
1592   vcg_open_name ("All_graphs");
1593
1594   collect_nodes();
1595   dump_graphs();
1596
1597   if (dump_loop_information_flag)
1598     for (i = 0; i < get_irp_n_irgs(); i++)
1599       dump_loop_info(get_irp_irg(i));
1600
1601   vcg_close();
1602   interprocedural_view = rem_view;
1603 }
1604
1605 /* dump interprocedural block graph with surrounding methods */
1606 void dump_cg_graph(ir_graph * irg) {
1607   pmap * map = pmap_create();
1608   pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1609   pmap_entry * entry;
1610   vcg_open(irg, "");
1611
1612   irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1613   for (entry = pmap_first(map); entry; entry = pmap_next(map))
1614     pmap_insert(map2, entry->key, entry->value);
1615   for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1616     ir_node ** arr = entry->value;
1617     int i;
1618     ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1619
1620     fprintf(F, "graph: { title: %s label: %s status:clustered color:white \n",
1621              get_id_str(irg_ident), get_id_str(irg_ident));
1622
1623     for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1624       ir_node * node = arr[i];
1625       dump_node(node, map2);
1626       dump_ir_data_edges(node, NULL);
1627       if (is_Block(node)) {
1628         for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1629           dump_node(node, map2);
1630           dump_ir_block_edge(node);
1631           dump_ir_data_edges(node, NULL);
1632         }
1633       }
1634     }
1635
1636     DEL_ARR_F(arr);
1637
1638     /* Close the vcg information for the irg */
1639     fprintf(F, "}\n\n");
1640   }
1641
1642   pmap_destroy(map);
1643   pmap_destroy(map2);
1644
1645   vcg_close();
1646 }
1647
1648 /* Dump the information of type field specified in ana/irtypeinfo.h.
1649  * If the flag is set, the type name is output in [] in the node label,
1650  * else it is output as info.
1651  */
1652 void dump_analysed_type_info(bool b) {
1653   opt_dump_analysed_type_info = b;
1654 }