59d43cc31cedf61f6b2c530730d94f784428cb63
[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   if (dump_file_suffix)
959     fname = malloc (len + 5 + strlen(dump_file_suffix));
960   else
961     fname = malloc (len + 5);
962   strcpy (fname, name);    /* copy the filename */
963   if (dump_file_suffix) strcat (fname, dump_file_suffix);
964   strcat (fname, ".vcg");  /* append the .vcg suffix */
965   F = fopen (fname, "w");  /* open file for writing */
966   if (!F) {
967     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
968   }
969
970   if (edge_label) {
971     strcpy(label, "yes");
972   } else {
973     strcpy (label, "no");
974   }
975
976   /* print header */
977   xfprintf (F,
978             "graph: { title: \"ir graph of %s\"\n"
979             "display_edge_labels: %s\n"
980             "layoutalgorithm: mindepth\n"
981             "manhattan_edges: yes\n"
982             "port_sharing: no\n"
983             "orientation: bottom_to_top\n"
984             "classname 1: \"Data\"\n"
985             "classname 2: \"Block\"\n"
986             "classname 3: \"Entity type\"\n"
987             "classname 4: \"Entity owner\"\n"
988             "classname 5: \"Method Param\"\n"
989             "classname 6: \"Method Res\"\n"
990             "classname 7: \"Super\"\n"
991             "classname 8: \"Union\"\n"
992             "classname 9: \"Points-to\"\n"
993             "classname 10: \"Array Element Type\"\n"
994             "classname 11: \"Overwrites\"\n"
995             "classname 12: \"Member\"\n"
996             , name, label);
997
998   xfprintf (F, "\n");           /* a separator */
999 }
1000
1001 void
1002 vcg_close () {
1003   xfprintf (F, "}\n");  /* print footer */
1004   fclose (F);           /* close vcg file */
1005 }
1006
1007 /************************************************************************/
1008 /* routines to dump a graph, blocks as conventional nodes.              */
1009 /************************************************************************/
1010
1011 int node_floats(ir_node *n) {
1012   return ((get_op_pinned(get_irn_op(n)) == floats) &&
1013           (get_irg_pinned(current_ir_graph) == floats));
1014 }
1015
1016 void
1017 dump_whole_node (ir_node *n, void* env) {
1018   dump_node(n);
1019   if (!node_floats(n)) dump_ir_block_edge(n);
1020   dump_ir_data_edges(n);
1021 }
1022
1023 void
1024 dump_ir_graph (ir_graph *irg)
1025 {
1026   ir_graph *rem;
1027   rem = current_ir_graph;
1028   current_ir_graph = irg;
1029
1030   vcg_open (irg, "");
1031
1032   /* walk over the graph */
1033   /* dump_whole_node must be called in post visiting predecessors */
1034   irg_walk(irg->end, NULL, dump_whole_node, NULL);
1035
1036   /* dump the out edges in a separate walk */
1037   if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1038     irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
1039   }
1040
1041   vcg_close();
1042
1043   current_ir_graph = rem;
1044 }
1045
1046 /***********************************************************************/
1047 /* the following routines dump the nodes as attached to the blocks.    */
1048 /***********************************************************************/
1049
1050 void
1051 dump_ir_blocks_nodes (ir_node *n, void *env) {
1052   ir_node *block = (ir_node *)env;
1053
1054   if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1055     dump_node(n);
1056     dump_ir_data_edges(n);
1057   }
1058   if (get_irn_op(n) == op_Bad)
1059     Bad_dumped = 1;
1060 }
1061
1062 void
1063 dump_ir_block (ir_node *block, void *env) {
1064   ir_graph *irg = (ir_graph *)env;
1065
1066   if (get_irn_opcode(block) == iro_Block) {
1067
1068     /* This is a block. So dump the vcg information to make a block. */
1069     xfprintf(F, "graph: { title: \"");
1070         PRINT_NODEID(block);
1071         fprintf(F, "\"  label: \"");
1072 #ifdef DEBUG_libfirm
1073     xfprintf (F, "%ld", get_irn_node_nr(block));
1074 #else
1075     xfprintf (F, "%I", block->op->name);
1076 #endif
1077     if (exc_normal != get_Block_exc (block))
1078       fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1079
1080     xfprintf(F, "\" status:clustered color:%s \n",
1081              get_Block_matured (block) ? "yellow" : "red");
1082     /* dump the blocks edges */
1083     dump_ir_data_edges(block);
1084
1085     /* dump the nodes that go into the block */
1086     irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
1087
1088     /* Close the vcg information for the block */
1089     xfprintf(F, "}\n\n");
1090   }
1091 }
1092
1093
1094 void
1095 dump_blockless_nodes (ir_node *n, void *env) {
1096   if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1097     dump_node(n);
1098     dump_ir_data_edges(n);
1099     dump_ir_block_edge(n);
1100     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1101     return;
1102   }
1103   if (node_floats(n)) {
1104     dump_node(n);
1105     dump_ir_data_edges(n);
1106     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1107   }
1108 }
1109
1110 void dump_ir_block_graph_2  (ir_graph *irg)
1111 {
1112   Bad_dumped = 0;
1113   /* walk over the blocks in the graph */
1114   irg_block_walk(irg->end, dump_ir_block, NULL, irg);
1115
1116   /* dump all nodes that are not in a Block */
1117   irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
1118
1119   /* dump the Bad node */
1120   if (!Bad_dumped)
1121     dump_node(get_irg_bad(irg));
1122 }
1123
1124 void
1125 dump_ir_block_graph (ir_graph *irg)
1126 {
1127   ir_graph *rem;
1128   rem = current_ir_graph;
1129   current_ir_graph = irg;
1130
1131   vcg_open (irg, "");
1132
1133   dump_ir_block_graph_2 (irg);
1134
1135   if (dump_loop_information_flag) {
1136     dump_loop_info(irg);
1137   }
1138
1139   vcg_close();
1140   current_ir_graph = rem;
1141 }
1142
1143
1144 /***********************************************************************/
1145 /* the following routines dump a control flow graph                    */
1146 /***********************************************************************/
1147
1148
1149 void
1150 dump_block_to_cfg (ir_node *block, void *env) {
1151   int i;
1152   ir_node *pred;
1153
1154   if (get_irn_opcode(block) == iro_Block) {
1155     /* This is a block. Dump a node for the block. */
1156     xfprintf (F, "node: {title:\""); PRINT_NODEID(block);
1157     xfprintf (F, "\" label: \"%I ", block->op->name); PRINT_NODEID(block);
1158
1159         if (exc_normal != get_Block_exc (block))
1160           xfprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1161
1162     xfprintf (F, "\" ");
1163     if (dump_dominator_information_flag)
1164       xfprintf(F, "info1:\"dom depth %d\"", get_Block_dom_depth(block));
1165     xfprintf (F, "}\n");
1166     /* Dump the edges */
1167     for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1168       if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1169         pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1170         xfprintf (F, "edge: { sourcename: \"");
1171         PRINT_NODEID(block);
1172         fprintf (F, "\" targetname: \"");
1173         PRINT_NODEID(pred);
1174         fprintf (F, "\" }\n");
1175       }
1176
1177     /* Dump dominator edge */
1178     if (dump_dominator_information_flag && get_Block_idom(block)) {
1179       pred = get_Block_idom(block);
1180       xfprintf (F, "edge: { sourcename: \"");
1181       PRINT_NODEID(block);
1182       fprintf (F, "\" targetname: \"");
1183       PRINT_NODEID(pred);
1184       fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1185     }
1186   }
1187 }
1188
1189 void
1190 dump_cfg (ir_graph *irg)
1191 {
1192   ir_graph *rem = current_ir_graph;
1193   int ddif = dump_dominator_information_flag;
1194   current_ir_graph = irg;
1195   vcg_open (irg, "-cfg");
1196
1197   if (get_irg_dom_state(irg) != dom_consistent)
1198     dump_dominator_information_flag = 0;
1199
1200   /* walk over the blocks in the graph */
1201   irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1202   dump_ir_node (irg->bad);
1203
1204   dump_dominator_information_flag = ddif;
1205   vcg_close();
1206   current_ir_graph = rem;
1207 }
1208
1209
1210 /***********************************************************************/
1211 /* the following routine dumps all type information reachable from an  */
1212 /* irg                                                                 */
1213 /***********************************************************************/
1214
1215
1216 void
1217 dump_type_graph (ir_graph *irg)
1218 {
1219   ir_graph *rem;
1220   rem = current_ir_graph;
1221   current_ir_graph = irg;
1222
1223   vcg_open (irg, "-type");
1224
1225   /* walk over the blocks in the graph */
1226   type_walk_irg(irg, dump_type_info, NULL, NULL);
1227   /* The walker for the const code can be called several times for the
1228      same (sub) experssion.  So that no nodes are dumped several times
1229      we decrease the visited flag of the corresponding graph after each
1230      walk.  So now increase it finally. */
1231   inc_irg_visited(get_const_code_irg());
1232
1233   vcg_close();
1234   current_ir_graph = rem;
1235 }
1236
1237 /***********************************************************************/
1238 /* the following routine dumps all type information                    */
1239 /***********************************************************************/
1240
1241
1242 void
1243 dump_all_types (void)
1244 {
1245   vcg_open_name ("All_types");
1246   type_walk(dump_type_info, NULL, NULL);
1247   inc_irg_visited(get_const_code_irg());
1248   vcg_close();
1249 }
1250
1251 /***********************************************************************/
1252 /* dumps a graph with type information                                 */
1253 /***********************************************************************/
1254
1255
1256 void
1257 dump_ir_graph_w_types (ir_graph *irg)
1258 {
1259   ir_graph *rem;
1260   rem = current_ir_graph;
1261   current_ir_graph = irg;
1262
1263   vcg_open (irg, "-all");
1264
1265   /* dump common ir graph */
1266   irg_walk(irg->end, dump_whole_node, NULL, NULL);
1267   /* dump type info */
1268   type_walk_irg(irg, dump_type_info, NULL, NULL);
1269   inc_irg_visited(get_const_code_irg());
1270   /* dump edges from graph to type info */
1271   irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1272
1273   vcg_close();
1274   current_ir_graph = rem;
1275 }
1276
1277 void
1278 dump_ir_block_graph_w_types (ir_graph *irg)
1279 {
1280   ir_graph *rem;
1281   rem = current_ir_graph;
1282   current_ir_graph = irg;
1283
1284   vcg_open (irg, "-all");
1285
1286   /* dump common blocked ir graph */
1287   dump_ir_block_graph_2(irg);
1288   /* dump type info */
1289   type_walk_irg(irg, dump_type_info, NULL, NULL);
1290   inc_irg_visited(get_const_code_irg());
1291   /* dump edges from graph to type info */
1292   irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1293
1294   vcg_close();
1295   current_ir_graph = rem;
1296 }
1297
1298 /***********************************************************************/
1299 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
1300 /*  dump_ir_graph                                                      */
1301 /*  dump_ir_block_graph                                                */
1302 /*  dump_cfg                                                           */
1303 /*  dump_type_graph                                                    */
1304 /*  dump_ir_graph_w_types                                              */
1305 /***********************************************************************/
1306 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1307   int i;
1308   for (i=0; i < get_irp_n_irgs(); i++) {
1309     dump_graph(get_irp_irg(i));
1310   }
1311 }
1312
1313
1314 /* To turn off display of edge labels.  Edge labels offen cause xvcg to
1315    abort with a segmentation fault. */
1316 void turn_off_edge_labels() {
1317   edge_label = 0;
1318 }
1319
1320 void turn_off_constant_entity_values() {
1321   const_entities = 0;
1322 }
1323
1324 void dump_keepalive_edges() {
1325   dump_keepalive = 1;
1326 }
1327
1328 void dump_out_edges() {
1329   dump_out_edge_flag = 1;
1330 }
1331
1332 void dump_dominator_information() {
1333   dump_dominator_information_flag = 1;
1334 }
1335
1336 void dump_loop_information() {
1337   dump_loop_information_flag = 1;
1338 }
1339
1340 void dont_dump_loop_information() {
1341   dump_loop_information_flag = 0;
1342 }
1343
1344 static void clear_link(ir_node * node, void * env) {
1345   set_irn_link(node, NULL);
1346 }
1347
1348
1349 static INLINE bool is_Block(ir_node * node) {
1350   return !is_no_Block(node);
1351 }
1352
1353
1354 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1355   if (is_Block(node)
1356       || node_floats(node)
1357       || get_irn_op(node) == op_Bad
1358       || get_irn_op(node) == op_Unknown) {
1359     pmap_entry * entry = pmap_find(map, current_ir_graph);
1360     if (entry) {
1361       ARR_APP1(ir_node *, (ir_node **) entry->value, node);
1362     } else {
1363       ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1364       arr[0] = node;
1365       pmap_insert(map, current_ir_graph, arr);
1366     }
1367   } else {
1368     ir_node * block = get_nodes_Block(node);
1369     set_irn_link(node, get_irn_link(block));
1370     set_irn_link(block, node);
1371   }
1372 }
1373
1374
1375 static void dump_cg_ir_block(ir_node * node, void * env) {
1376   assert(is_Block(node));
1377   xfprintf(F, "graph: { title: \"");
1378   PRINT_NODEID(node);
1379   fprintf(F, "\"  label: \"");
1380 #ifdef DEBUG_libfirm
1381   xfprintf (F, "%ld", get_irn_node_nr(node));
1382 #else
1383   xfprintf (F, "%I", node->op->name);
1384 #endif
1385   if (exc_normal != get_Block_exc(node)) {
1386     fprintf (F, " (%s)", exc_to_string (get_Block_exc(node)));
1387   }
1388
1389   xfprintf(F, "\" status:clustered color:%s \n",
1390            get_Block_matured(node) ? "yellow" : "red");
1391
1392   /* dump the blocks edges */
1393   dump_ir_data_edges(node);
1394
1395   /* dump the nodes that go into the block */
1396   for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1397     dump_node(node);
1398     dump_ir_data_edges(node);
1399   }
1400
1401   /* Close the vcg information for the block */
1402   xfprintf(F, "}\n\n");
1403 }
1404
1405
1406 /* dump interprocedural graph with surrounding methods */
1407 void dump_cg_block_graph(ir_graph * irg) {
1408   pmap * map = pmap_create();
1409   pmap_entry * entry;
1410   vcg_open(irg, "");
1411
1412   irg_walk_graph(irg, clear_link, (irg_walk_func) collect_blocks_floats_cg, map);
1413   for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1414     ir_node ** arr = entry->value;
1415     int i;
1416
1417     xfprintf(F, "graph: { title: \"%I\" label: \"%I\" status:clustered color:white \n",
1418              get_entity_ident(get_irg_ent(entry->key)),
1419              get_entity_ident(get_irg_ent(entry->key)));
1420
1421     for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1422       ir_node * node = arr[i];
1423       if (is_Block(node)) {
1424         /* Dumps the block and all the nodes in the block , with are to be found in
1425            Block->link. */
1426         dump_cg_ir_block(node, NULL);
1427       } else {
1428         /* Node that are not in a Block. */
1429         dump_node(node);
1430         dump_ir_data_edges(node);
1431       }
1432     }
1433
1434     DEL_ARR_F(arr);
1435
1436     /* Close the vcg information for the irg */
1437     xfprintf(F, "}\n\n");
1438   }
1439
1440   pmap_destroy(map);
1441
1442   if (dump_loop_information_flag) {
1443     dump_loop_info(irg);
1444   }
1445
1446   vcg_close();
1447 }
1448
1449
1450 /* dump interprocedural block graph with surrounding methods */
1451 void dump_cg_graph(ir_graph * irg) {
1452   pmap * map = pmap_create();
1453   pmap_entry * entry;
1454   vcg_open(irg, "");
1455
1456   irg_walk_graph(irg, clear_link, (irg_walk_func) collect_blocks_floats_cg, map);
1457   for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1458     ir_node ** arr = entry->value;
1459     int i;
1460     ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1461
1462     xfprintf(F, "graph: { title: \"%I\" label: \"%I\" status:clustered color:white \n",
1463              irg_ident, irg_ident);
1464
1465     for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1466       ir_node * node = arr[i];
1467       dump_node(node);
1468       dump_ir_data_edges(node);
1469       if (is_Block(node)) {
1470         for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1471           dump_node(node);
1472           dump_ir_block_edge(node);
1473           dump_ir_data_edges(node);
1474         }
1475       }
1476     }
1477
1478     DEL_ARR_F(arr);
1479
1480     /* Close the vcg information for the irg */
1481     xfprintf(F, "}\n\n");
1482   }
1483
1484   pmap_destroy(map);
1485
1486   vcg_close();
1487 }