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