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