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