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