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