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