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