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