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