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