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