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