Implemented cf optimizations.
[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
32 /* Attributes of nodes */
33 #define DEFAULT_NODE_ATTR ""
34 #define DEFAULT_TYPE_ATTRIBUTE ""
35
36 /* Attributes of edges between Firm nodes */
37 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
38 #define CF_EDGE_ATTR    "color: red"
39 #define MEM_EDGE_ATTR   "color: blue"
40 #define DOMINATOR_EDGE_ATTR "color: red"
41
42 /* Attributes of edges between Firm nodes and type/entity nodes */
43 #define NODE2TYPE_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
44
45 /* Attributes of edges in type/entity graphs. */
46 #define TYPE_METH_NODE_ATTR  "color: lightyellow"
47 #define TYPE_CLASS_NODE_ATTR "color: green"
48 #define ENTITY_NODE_ATTR     "color: yellow"
49 #define ENT_TYPE_EDGE_ATTR   "class: 3 label: \"type\" color: red"
50 #define ENT_OWN_EDGE_ATTR    "class: 4 label: \"owner\" color: black"
51 #define METH_PAR_EDGE_ATTR   "class: 5 label: \"param %d\" color: green"
52 #define METH_RES_EDGE_ATTR   "class: 6 label: \"res %d\" color: green"
53 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: blue"
54 #define UNION_EDGE_ATTR      "class: 8 label: \"component\" color: blue"
55 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
56 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
57 #define ARR_ENT_EDGE_ATTR    "class: 10 label: \"arr ent\" color: green"
58 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
59 #define ENT_VALUE_EDGE_ATTR "label: \"value "
60 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
61 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
62
63
64 #if DEBUG_libfirm && NODEID_AS_LABEL
65 #define PRINT_NODEID(X) fprintf(F, "%d", get_irn_node_nr(X))
66 #else
67 #define PRINT_NODEID(X) fprintf(F, "%p", X)
68 #endif
69
70 /* A suffix to manipulate the file name. */
71 char *dump_file_suffix = NULL;
72
73 /* file to dump to */
74 static FILE *F;
75
76 /* A compiler option to turn off edge labels */
77 int edge_label = 1;
78 /* A compiler option to turn off dumping values of constant entities */
79 int const_entities = 1;
80 /* A compiler option to dump the keep alive edges */
81 int dump_keepalive = 0;
82 /* A compiler option to dump the out edges in dump_ir_graph */
83 int dump_out_edge_flag = 0;
84 int dump_dominator_information_flag = 0;
85
86 /* A global variable to record output of the Bad node. */
87 int Bad_dumped;
88
89
90 void dump_ir_blocks_nodes (ir_node *n, void *env);
91 void dump_whole_node (ir_node *n, void* env);
92
93 /*******************************************************************/
94 /* routines to dump information about a single node                */
95 /*******************************************************************/
96
97
98
99 inline void
100 dump_node_opcode (ir_node *n)
101 {
102
103   /* Const */
104   if (n->op->code == iro_Const) {
105     xfprintf (F, "%v", n->attr.con);
106
107   /* SymConst */
108   } else if (n->op->code == iro_SymConst) {
109     if (get_SymConst_kind(n) == linkage_ptr_info) {
110       /* don't use get_SymConst_ptr_info as it mangles the name. */
111       xfprintf (F, "SymC %I", n->attr.i.tori.ptrinfo);
112     } else {
113       assert(get_kind(get_SymConst_type(n)) == k_type);
114       assert(get_type_ident(get_SymConst_type(n)));
115       xfprintf (F, "SymC %I ", get_type_ident(get_SymConst_type(n)));
116       if (get_SymConst_kind == type_tag)
117         xfprintf (F, "tag");
118       else
119         xfprintf (F, "size");
120     }
121   /* all others */
122   } else {
123     xfprintf (F, "%I", get_irn_opident(n));
124   }
125 }
126
127 inline void
128 dump_node_mode (ir_node *n)
129 {
130   switch (n->op->code) {
131   case iro_Phi:
132   case iro_Const:
133   case iro_Id:
134   case iro_Proj:
135   case iro_Conv:
136   case iro_Tuple:
137   case iro_Add:
138   case iro_Sub:
139   case iro_Mul:
140   case iro_And:
141   case iro_Or:
142   case iro_Eor:
143   case iro_Shl:
144   case iro_Shr:
145   case iro_Abs:
146   case iro_Cmp:
147     xfprintf (F, "%I", get_mode_ident(n->mode));
148     break;
149   default:
150   }
151 }
152
153 inline void
154 dump_node_nodeattr (ir_node *n)
155 {
156   switch (n->op->code) {
157   case iro_Proj:
158     if (n->in[1]->op->code == iro_Cmp) {
159       xfprintf (F, "%s", get_pnc_string(n->attr.proj));
160     } else {
161       xfprintf (F, "%ld", n->attr.proj);
162     }
163     break;
164   case iro_Sel: {
165     assert(get_kind(get_Sel_entity(n)) == k_entity);
166     xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
167     } break;
168   default:
169   } /* end switch */
170 }
171
172 inline void
173 dump_node_vcgattr (ir_node *n)
174 {
175   switch (n->op->code) {
176   case iro_Start:
177   case iro_End:
178     xfprintf (F, "color: blue");
179     break;
180   case iro_Block:
181     xfprintf (F, "color: lightyellow");
182     break;
183   case iro_Phi:
184     xfprintf (F, "color: green");
185     break;
186   case iro_Const:
187   case iro_Proj:
188   case iro_Tuple:
189     xfprintf (F, "color: yellow");
190     break;
191   default:
192     xfprintf (F, DEFAULT_NODE_ATTR);
193   }
194 }
195
196 void
197 dump_node (ir_node *n) {
198
199   /* dump this node */
200   xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
201
202   dump_node_opcode(n);
203   dump_node_mode (n);
204   xfprintf (F, " ");
205   dump_node_nodeattr(n);
206 #ifdef DEBUG_libfirm
207   xfprintf (F, " %ld", get_irn_node_nr(n));
208 #endif
209   xfprintf (F, "\" ");
210   dump_node_vcgattr(n);
211   xfprintf (F, "}\n");
212 }
213
214 void
215 dump_ir_node (ir_node *n)
216 {
217   /* dump this node */
218   fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: ");
219
220   switch (n->op->code) {  /* node label */
221   case iro_Start:
222     xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
223     xfprintf (F, DEFAULT_NODE_ATTR);
224      break;
225   case iro_End:
226     xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
227     xfprintf (F, DEFAULT_NODE_ATTR);
228     break;
229   case iro_Block:
230     xfprintf (F, "\"%I\" color: lightyellow ", get_irn_opident(n));
231     xfprintf (F, DEFAULT_NODE_ATTR);
232     break;
233   case iro_Phi:
234     xfprintf (F, "\"%I%I\" color: green", get_irn_opident(n), get_irn_modeident(n));
235     if (get_irn_modecode(n) == irm_M)
236       xfprintf (F, DEFAULT_NODE_ATTR " color: green");
237     else
238       xfprintf (F, DEFAULT_NODE_ATTR);
239     break;
240   case iro_Const:
241     xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, get_irn_modeident(n));
242     xfprintf (F, DEFAULT_NODE_ATTR);
243     break;
244   case iro_Id:
245     xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
246     xfprintf (F, DEFAULT_NODE_ATTR);
247     break;
248   case iro_Proj:
249     if (n->in[1]->op->code == iro_Cmp) {
250       xfprintf (F, "\"%I%I %s\" color: yellow", get_irn_opident(n), get_irn_modeident(n),
251                 get_pnc_string(n->attr.proj));
252     } else {
253       xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.proj);
254     }
255     xfprintf (F, DEFAULT_NODE_ATTR);
256     break;
257   case iro_Conv:
258     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
259     xfprintf (F, DEFAULT_NODE_ATTR);
260     break;
261   case iro_Tuple:
262     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
263     xfprintf (F, DEFAULT_NODE_ATTR);
264     break;
265   case iro_Add:
266     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
267     xfprintf (F, DEFAULT_NODE_ATTR);
268     break;
269   case iro_Sub:
270     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
271     xfprintf (F, DEFAULT_NODE_ATTR);
272     break;
273   case iro_Mul:
274     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
275     xfprintf (F, DEFAULT_NODE_ATTR);
276     break;
277   case iro_Quot:
278     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
279     xfprintf (F, DEFAULT_NODE_ATTR);
280     break;
281   case iro_DivMod:
282     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
283     xfprintf (F, DEFAULT_NODE_ATTR);
284     break;
285   case iro_Div:
286     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
287     xfprintf (F, DEFAULT_NODE_ATTR);
288     break;
289   case iro_Mod:
290     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
291     xfprintf (F, DEFAULT_NODE_ATTR);
292     break;
293   case iro_And:
294     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
295     xfprintf (F, DEFAULT_NODE_ATTR);
296     break;
297   case iro_Or:
298     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
299     xfprintf (F, DEFAULT_NODE_ATTR);
300     break;
301   case iro_Eor:
302     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
303     xfprintf (F, DEFAULT_NODE_ATTR);
304     break;
305   case iro_Shl:
306     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
307     xfprintf (F, DEFAULT_NODE_ATTR);
308     break;
309   case iro_Shr:
310     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
311     xfprintf (F, DEFAULT_NODE_ATTR);
312     break;
313   case iro_Abs:
314     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
315     xfprintf (F, DEFAULT_NODE_ATTR);
316     break;
317   case iro_Cmp:
318     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
319     xfprintf (F, DEFAULT_NODE_ATTR);
320     break;
321   case iro_Jmp:
322     xfprintf (F, "\"%I\"", get_irn_opident(n));
323     xfprintf (F, DEFAULT_NODE_ATTR);
324     break;
325   case iro_Cond:
326     xfprintf (F, "\"%I\"", get_irn_opident(n));
327     xfprintf (F, DEFAULT_NODE_ATTR);
328     break;
329   case iro_Call:
330     xfprintf (F, "\"%I\"", get_irn_opident(n));
331     xfprintf (F, DEFAULT_NODE_ATTR);
332     break;
333   case iro_Return:
334     xfprintf (F, "\"%I\"", get_irn_opident(n));
335     xfprintf (F, DEFAULT_NODE_ATTR);
336     break;
337   case iro_Raise:
338     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
339     xfprintf (F, DEFAULT_NODE_ATTR);
340     break;
341   case iro_Load:
342   case iro_Store:
343     xfprintf (F, "\"%R\"", n);
344     xfprintf (F, DEFAULT_NODE_ATTR);
345     break;
346   case iro_Alloc:
347     xfprintf (F, "\"%I\" ", get_irn_opident(n));
348     xfprintf (F, DEFAULT_NODE_ATTR);
349     break;
350   case iro_Sel:
351     assert(get_kind(get_Sel_entity(n)) == k_entity);
352     xfprintf (F, "\"%I ", get_irn_opident(n));
353     xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
354     xfprintf (F, DEFAULT_NODE_ATTR);
355     break;
356   case iro_SymConst:
357     assert(get_kind(get_SymConst_type(n)) == k_type);
358     assert(get_type_ident(get_SymConst_type(n)));
359     xfprintf (F, "\"%s ", get_type_name(get_SymConst_type(n)));
360     switch (n->attr.i.num){
361     case type_tag:
362       xfprintf (F, "tag\" ");
363       break;
364     case size:
365       xfprintf (F, "size\" ");
366       break;
367     default:
368       assert(0);
369       break;
370     }
371     xfprintf (F, DEFAULT_NODE_ATTR);
372     break;
373   case iro_Sync:
374     xfprintf (F, "\"%I\" ", get_irn_opident(n));
375     xfprintf (F, DEFAULT_NODE_ATTR " color: green");
376     break;
377   case iro_Bad:
378     xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
379     xfprintf (F, DEFAULT_NODE_ATTR);
380     break;
381   default:
382     xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
383   }
384   xfprintf (F, "}\n");          /* footer */
385 }
386
387
388 /* dump the edge to the block this node belongs to */
389 void
390 dump_ir_block_edge(ir_node *n)  {
391   if (is_no_Block(n)) {
392     xfprintf (F, "edge: { sourcename: \"");
393     PRINT_NODEID(n);
394     xfprintf (F, "\" targetname: \"");
395     PRINT_NODEID(get_nodes_Block(n));
396     xfprintf (F, "\" "  BLOCK_EDGE_ATTR "}\n");
397   }
398 }
399
400 void print_edge_vcgattr(ir_node *from, int to) {
401   assert(from);
402
403   switch (get_irn_opcode(from)) {
404   case iro_Block:
405     xfprintf (F, CF_EDGE_ATTR);
406     break;
407   case iro_Start:   break;
408   case iro_End:     break;
409   case iro_Jmp:     break;
410   case iro_Cond:    break;
411   case iro_Return:
412   case iro_Raise:
413     if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
414     break;
415   case iro_Const:   break;
416   case iro_SymConst:break;
417   case iro_Sel:
418   case iro_Call:
419     if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
420     break;
421   case iro_Add:     break;
422   case iro_Sub:     break;
423   case iro_Minus:   break;
424   case iro_Mul:     break;
425   case iro_Quot:
426   case iro_DivMod:
427   case iro_Div:
428   case iro_Mod:
429     if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
430     break;
431   case iro_Abs:    break;
432   case iro_And:    break;
433   case iro_Or:     break;
434   case iro_Eor:    break;
435   case iro_Shl:    break;
436   case iro_Shr:    break;
437   case iro_Shrs:   break;
438   case iro_Rot:    break;
439   case iro_Cmp:    break;
440   case iro_Conv:   break;
441   case iro_Phi:
442     if (get_irn_modecode(from) == irm_M) xfprintf (F, MEM_EDGE_ATTR);
443     break;
444   case iro_Load:
445   case iro_Store:
446   case iro_Alloc:
447   case iro_Free:
448     if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
449     break;
450   case iro_Sync:
451     xfprintf (F, MEM_EDGE_ATTR);
452     break;
453   case iro_Tuple:  break;
454   case iro_Proj:
455     switch (get_irn_modecode(from)) {
456     case irm_X:
457       xfprintf (F, CF_EDGE_ATTR);
458       break;
459     case irm_M:
460       xfprintf (F, MEM_EDGE_ATTR);
461       break;
462     default: break;
463     }
464     break;
465   case iro_Bad:    break;
466   case iro_Id:     break;
467   default:
468   }
469 }
470
471 /* dump edges to our inputs */
472 void
473 dump_ir_data_edges(ir_node *n)  {
474   int i, max;
475
476   if ((get_irn_op(n) == op_End) && (!dump_keepalive))
477     return;
478
479   for (i = 0; i < get_irn_arity(n); i++) {
480     assert(get_irn_n(n, i));
481     fprintf (F, "edge: {sourcename: \"");
482     PRINT_NODEID(n);
483     fprintf (F, "\" targetname: \"");
484     PRINT_NODEID(get_irn_n(n, i));
485     fprintf (F, "\"");
486     fprintf (F, " label: \"%d\" ", i);
487     print_edge_vcgattr(n, i);
488     fprintf (F, "}\n");
489   }
490 }
491
492 /* dump out edges */
493 void
494 dump_out_edge (ir_node *n, void* env) {
495   int i;
496   for (i = 0; i < get_irn_n_outs(n); i++) {
497     assert(get_irn_out(n, i));
498     fprintf (F, "edge: {sourcename: \"");
499     PRINT_NODEID(n);
500     fprintf (F, "\" targetname: \"");
501     PRINT_NODEID(get_irn_out(n, i));
502     fprintf (F, "\" color: red linestyle: dashed");
503     fprintf (F, "}\n");
504   }
505 }
506
507
508 /* dumps the edges between nodes and their type or entity attributes. */
509 void dump_node2type_edges (ir_node *n, void *env)
510 {
511   assert(n);
512
513   switch (get_irn_opcode(n)) {
514   case iro_Const :
515     /* @@@ some consts have an entity */
516     break;
517   case iro_SymConst:
518     if (   (get_SymConst_kind(n) == type_tag)
519            || (get_SymConst_kind(n) == size)) {
520       xfprintf (F, "edge: { sourcename: \"");
521       PRINT_NODEID(n);
522       fprintf (F, "\" targetname: \"%p\" "
523                NODE2TYPE_EDGE_ATTR "}\n", get_SymConst_type(n));
524     }
525     break;
526   case iro_Sel: {
527     xfprintf (F, "edge: { sourcename: \"");
528     PRINT_NODEID(n);
529     fprintf (F, "\" targetname: \"%p\" "
530              NODE2TYPE_EDGE_ATTR "}\n", get_Sel_entity(n));
531     } break;
532   case iro_Call: {
533     xfprintf (F, "edge: { sourcename: \"");
534     PRINT_NODEID(n);
535     fprintf (F, "\" targetname: \"%p\" "
536              NODE2TYPE_EDGE_ATTR "}\n", get_Call_type(n));
537     } break;
538   case iro_Alloc: {
539     xfprintf (F, "edge: { sourcename: \"");
540     PRINT_NODEID(n);
541     fprintf (F, "\" targetname: \"%p\" "
542              NODE2TYPE_EDGE_ATTR "}\n", get_Alloc_type(n));
543     } break;
544   case iro_Free: {
545     xfprintf (F, "edge: { sourcename: \"");
546     PRINT_NODEID(n);
547     fprintf (F, "\" targetname: \"%p\" "
548              NODE2TYPE_EDGE_ATTR "}\n", get_Free_type(n));
549     } break;
550   default:
551     break;
552   }
553 }
554
555
556 void dump_const_expression(ir_node *value) {
557   ir_graph *rem = current_ir_graph;
558   current_ir_graph = get_const_code_irg();
559   irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
560   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
561   current_ir_graph = rem;
562 }
563
564
565 void print_type_info(type *tp) {
566   if (get_type_state(tp) == layout_undefined) {
567     xfprintf(F, "state: layout_undefined\n");
568   } else {
569     xfprintf(F, "state: layout_fixed,\n");
570   }
571   if (get_type_mode(tp))
572     xfprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
573   xfprintf(F, "size: %dB,\n", get_type_size(tp));
574 }
575
576
577 void print_typespecific_info(type *tp) {
578   switch (get_type_tpop_code(tp)) {
579   case tpo_class:
580     {
581            xfprintf (F, " " TYPE_CLASS_NODE_ATTR);
582     } break;
583   case tpo_struct:
584     {
585       xfprintf (F, " " TYPE_METH_NODE_ATTR);
586     } break;
587   case tpo_method:
588     {
589     } break;
590   case tpo_union:
591     {
592     } break;
593   case tpo_array:
594     {
595     } break;
596   case tpo_enumeration:
597     {
598     } break;
599   case tpo_pointer:
600     {
601     } break;
602   case tpo_primitive:
603     {
604     } break;
605   default: break;
606   } /* switch type */
607 }
608
609 void print_type_node(type *tp) {
610   xfprintf (F, "node: {title: \"%p\" ", tp);
611   xfprintf (F, "label: \"%I %I\"", get_type_tpop_nameid(tp), get_type_ident(tp));
612   xfprintf (F, "info1: \"");
613   print_type_info(tp);
614   xfprintf (F, "\"");
615   print_typespecific_info(tp);
616   xfprintf (F, "}\n");
617 }
618
619 /* dumps a type or entity and it's edges. */
620 void
621 dump_type_info (type_or_ent *tore, void *env) {
622   int i = 0;  /* to shutup gcc */
623
624   /* dump this type or entity */
625
626   switch (get_kind(tore)) {
627   case k_entity:
628     {
629       entity *ent = (entity *)tore;
630       ir_node *value;
631       /* The node */
632       xfprintf (F, "node: {title: \"%p\" ", tore);
633       xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
634       xfprintf (F, "label: ");
635       xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR , get_entity_ident(ent));
636       if(dynamic_allocated == get_entity_allocation(ent))
637         xfprintf (F, " info1:\"dynamic allocated\n");
638       else
639         xfprintf (F, " info1:\"static allocated\n");
640       switch (get_entity_visibility(ent)) {
641         case local:              fprintf (F, "local\n");             break;
642         case external_visible:   fprintf (F, "external_visible\n");  break;
643         case external_allocated: fprintf (F, "external_allocate\n");break;
644       }
645       switch (get_entity_variability(ent)) {
646         case uninitialized: fprintf (F, "uninitialized");break;
647         case initialized:   fprintf (F, "initialized");  break;
648         case part_constant: fprintf (F, "part_constant");break;
649         case constant:      fprintf (F, "constant");     break;
650       }
651       if (is_method_type(get_entity_type(ent)))
652         xfprintf (F, "\n irg = %p ", get_entity_irg(ent));
653       xfprintf(F, "\"}\n");
654       /* The Edges */
655       /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
656       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
657                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
658       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
659                 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
660       for(i = 0; i < get_entity_n_overwrites(ent); i++)
661         xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
662                   ENT_OVERWRITES_EDGE_ATTR "}\n", ent, get_entity_overwrites(ent, i));
663       /* attached subgraphs */
664       if (const_entities && (get_entity_variability(ent) != uninitialized)) {
665         if (is_atomic_entity(ent)) {
666           value = get_atomic_ent_value(ent);
667           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
668           PRINT_NODEID(value);
669           fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
670           dump_const_expression(value);
671         }
672         if (is_compound_entity(ent)) {
673           for (i = 0; i < get_compound_ent_n_values(ent); i++) {
674             value = get_compound_ent_value(ent, i);
675             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
676             PRINT_NODEID(value);
677             fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
678             dump_const_expression(value);
679             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
680                       ENT_CORR_EDGE_ATTR  "}\n", ent,
681                       get_compound_ent_value_member(ent, i), i);
682           }
683         }
684       }
685     } break;
686   case k_type:
687     {
688       type *tp = (type *)tore;
689       print_type_node(tp);
690       /* and now the edges */
691       switch (get_type_tpop_code(tp)) {
692       case tpo_class:
693         {
694           for (i=0; i < get_class_n_supertype(tp); i++)
695             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
696                       TYPE_SUPER_EDGE_ATTR "}\n",
697                       tp, get_class_supertype(tp, i));
698           for (i=0; i < get_class_n_member(tp); i++)
699             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
700                       TYPE_MEMBER_EDGE_ATTR "}\n",
701                       tp, get_class_member(tp, i));
702         } break;
703       case tpo_struct:
704         {
705           for (i=0; i < get_struct_n_member(tp); i++)
706             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
707                       TYPE_MEMBER_EDGE_ATTR "}\n",
708                       tp, get_struct_member(tp, i));
709         } break;
710       case tpo_method:
711         {
712           for (i = 0; i < get_method_n_params(tp); i++)
713             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
714                       METH_PAR_EDGE_ATTR "}\n",
715                       tp, get_method_param_type(tp, i), i);
716           for (i = 0; i < get_method_n_res(tp); i++)
717             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
718                       METH_RES_EDGE_ATTR "}\n",
719                       tp, get_method_res_type(tp, i), i);
720         } break;
721       case tpo_union:
722         {
723           for (i = 0; i < get_union_n_members(tp); i++)
724             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
725                       "label: \"\"f" UNION_EDGE_ATTR "}\n",
726                       tp, get_union_member(tp, i));
727         } break;
728       case tpo_array:
729         {
730           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
731                     ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
732           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
733                     ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
734         } break;
735       case tpo_enumeration:
736         {
737         } break;
738       case tpo_pointer:
739         {
740           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
741                     PTR_PTS_TO_EDGE_ATTR "}\n", tp,
742                     get_pointer_points_to_type(tp), i);
743         } break;
744       case tpo_primitive:
745         {
746         } break;
747       default: break;
748       } /* switch type */
749     }
750     break; /* case k_type */
751   default:
752     {
753       printf(" *** irdump,  %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
754     } break;
755   } /* switch kind_or_entity */
756 }
757
758 /************************************************************************/
759 /* open and close vcg file                                              */
760 /************************************************************************/
761
762 void vcg_open (ir_graph *irg, char *suffix) {
763   char *fname;  /* filename to put the vcg information in */
764   const char *cp;
765   ident *id;
766   int len;
767   char label[4];
768   entity *ent;
769
770   /** open file for vcg graph */
771   ent = get_irg_ent(irg);
772   id    = ent->ld_name ? ent->ld_name : ent->name;
773   /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
774   len   = id_to_strlen (id);
775   cp    = id_to_str (id);
776   if (dump_file_suffix)
777     fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
778   else
779     fname = malloc (len + 5 + strlen(suffix));
780   strncpy (fname, cp, len);      /* copy the filename */
781   fname[len] = '\0';
782   if (dump_file_suffix) strcat (fname, dump_file_suffix);  /* append file suffix */
783   strcat (fname, suffix);  /* append file suffix */
784   strcat (fname, ".vcg");   /* append the .vcg suffix */
785   F = fopen (fname, "w");   /* open file for writing */
786   if (!F) {
787     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
788   }
789
790   if (edge_label) {
791     strcpy(label, "yes");
792   } else {
793     strcpy (label, "no");
794   }
795
796   /* print header */
797   xfprintf (F,
798             "graph: { title: \"ir graph of %s\"\n"
799             "display_edge_labels: %s\n"
800             "layoutalgorithm: mindepth\n"
801             "manhattan_edges: yes\n"
802             "port_sharing: no\n"
803             "orientation: bottom_to_top\n"
804             "classname 1: \"Data\"\n"
805             "classname 2: \"Block\"\n"
806             "classname 3: \"Entity type\""
807             "classname 4: \"Entity owner\""
808             "classname 5: \"Method Param\""
809             "classname 6: \"Method Res\""
810             "classname 7: \"Super\""
811             "classname 8: \"Union\""
812             "classname 9: \"Points-to\""
813             "classname 10: \"Array Element Type\""
814             "classname 11: \"Overwrites\""
815             "classname 12: \"Member\""
816             , cp, label);
817
818   xfprintf (F, "\n");           /* a separator */
819 }
820
821 void vcg_open_name (const char *name) {
822   char *fname;  /* filename to put the vcg information in */
823   int len;
824   char label[4];
825
826   /** open file for vcg graph */
827   len   = strlen(name);
828   fname = malloc (len + 5);
829   strcpy (fname, name);    /* copy the filename */
830   strcat (fname, ".vcg");  /* append the .vcg suffix */
831   F = fopen (fname, "w");  /* open file for writing */
832   if (!F) {
833     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
834   }
835
836   if (edge_label) {
837     strcpy(label, "yes");
838   } else {
839     strcpy (label, "no");
840   }
841
842   /* print header */
843   xfprintf (F,
844             "graph: { title: \"ir graph of %s\"\n"
845             "display_edge_labels: %s\n"
846             "layoutalgorithm: mindepth\n"
847             "manhattan_edges: yes\n"
848             "port_sharing: no\n"
849             "orientation: bottom_to_top\n"
850             "classname 1: \"Data\"\n"
851             "classname 2: \"Block\"\n"
852             "classname 3: \"Entity type\"\n"
853             "classname 4: \"Entity owner\"\n"
854             "classname 5: \"Method Param\"\n"
855             "classname 6: \"Method Res\"\n"
856             "classname 7: \"Super\"\n"
857             "classname 8: \"Union\"\n"
858             "classname 9: \"Points-to\"\n"
859             "classname 10: \"Array Element Type\"\n"
860             "classname 11: \"Overwrites\"\n"
861             "classname 12: \"Member\"\n"
862             , name, label);
863
864   xfprintf (F, "\n");           /* a separator */
865 }
866
867 void
868 vcg_close () {
869   xfprintf (F, "}\n");  /* print footer */
870   fclose (F);           /* close vcg file */
871 }
872
873 /************************************************************************/
874 /* routines to dump a graph, blocks as conventional nodes.              */
875 /************************************************************************/
876
877 void
878 dump_whole_node (ir_node *n, void* env) {
879   dump_node(n);
880   if (!node_floats(n)) dump_ir_block_edge(n);
881   dump_ir_data_edges(n);
882 }
883
884 void
885 dump_ir_graph (ir_graph *irg)
886 {
887   ir_graph *rem;
888   rem = current_ir_graph;
889   current_ir_graph = irg;
890
891   vcg_open (irg, "");
892
893   /* walk over the graph */
894   irg_walk(irg->end, dump_whole_node, NULL, NULL);
895
896   /* dump the out edges in a separate walk */
897   if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
898     irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
899   }
900
901   vcg_close();
902
903   current_ir_graph = rem;
904 }
905
906 /***********************************************************************/
907 /* the following routines dump the nodes as attached to the blocks.    */
908 /***********************************************************************/
909
910 int node_floats(ir_node *n) {
911
912   return ((get_op_pinned(get_irn_op(n)) == floats) &&
913           (get_irg_pinned(current_ir_graph) == floats));
914 }
915
916 void
917 dump_ir_blocks_nodes (ir_node *n, void *env) {
918   ir_node *block = (ir_node *)env;
919
920   if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
921     dump_node(n);
922     dump_ir_data_edges(n);
923   }
924   if (get_irn_op(n) == op_Bad)
925     Bad_dumped = 1;
926 }
927
928 void
929 dump_ir_block (ir_node *block, void *env) {
930   ir_graph *irg = (ir_graph *)env;
931
932   if (get_irn_opcode(block) == iro_Block) {
933
934     /* This is a block. So dump the vcg information to make a block. */
935     xfprintf(F, "graph: { title: \""); PRINT_NODEID(block); fprintf(F, "\"  label: \"");
936 #ifdef DEBUG_libfirm
937     xfprintf (F, "%ld", get_irn_node_nr(block));
938 #else
939     xfprintf (F, "%I", block->op->name);
940 #endif
941     xfprintf(F, "\" status:clustered color:%s \n",
942                          get_Block_matured (block) ? "yellow" : "red");
943     /* dump the blocks edges */
944     dump_ir_data_edges(block);
945
946     /* dump the nodes that go into the block */
947     irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
948
949     /* Close the vcg information for the block */
950     xfprintf(F, "}\n\n");
951   }
952 }
953
954
955 void
956 dump_blockless_nodes (ir_node *n, void *env) {
957   if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
958     dump_node(n);
959     dump_ir_data_edges(n);
960     dump_ir_block_edge(n);
961     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
962     return;
963   }
964   if (node_floats(n)) {
965     dump_node(n);
966     dump_ir_data_edges(n);
967     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
968   }
969 }
970
971 void dump_ir_block_graph_2  (ir_graph *irg)
972 {
973   Bad_dumped = 0;
974   /* walk over the blocks in the graph */
975   irg_block_walk(irg->end, dump_ir_block, NULL, irg);
976
977   /* dump all nodes that are not in a Block */
978   irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
979
980   /* dump the Bad node */
981   if (!Bad_dumped)
982     dump_node(get_irg_bad(irg));
983 }
984
985 void
986 dump_ir_block_graph (ir_graph *irg)
987 {
988   ir_graph *rem;
989   rem = current_ir_graph;
990   current_ir_graph = irg;
991
992   vcg_open (irg, "");
993
994   dump_ir_block_graph_2 (irg);
995
996   vcg_close();
997   current_ir_graph = rem;
998 }
999
1000
1001 /***********************************************************************/
1002 /* the following routines dump a control flow graph                    */
1003 /***********************************************************************/
1004
1005
1006 void
1007 dump_block_to_cfg (ir_node *block, void *env) {
1008   int i;
1009   ir_node *pred;
1010
1011   if (get_irn_opcode(block) == iro_Block) {
1012     /* This is a block. Dump a node for the block. */
1013     xfprintf (F, "node: {title:\""); PRINT_NODEID(block);
1014     xfprintf (F, "\" label: \"%I ", block->op->name); PRINT_NODEID(block);
1015     xfprintf (F, "\" ");
1016     if (dump_dominator_information_flag)
1017       xfprintf(F, "info1:\"dom depth %d\"", get_Block_dom_depth(block));
1018     xfprintf (F, "}\n");
1019     /* Dump the edges */
1020     for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1021       if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1022         pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1023         xfprintf (F, "edge: { sourcename: \"");
1024         PRINT_NODEID(block);
1025         fprintf (F, "\" targetname: \"");
1026         PRINT_NODEID(pred);
1027         fprintf (F, "\" }\n");
1028       }
1029
1030     /* Dump dominator edge */
1031     if (dump_dominator_information_flag && get_Block_idom(block)) {
1032       pred = get_Block_idom(block);
1033       xfprintf (F, "edge: { sourcename: \"");
1034       PRINT_NODEID(block);
1035       fprintf (F, "\" targetname: \"");
1036       PRINT_NODEID(pred);
1037       fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1038     }
1039   }
1040 }
1041
1042 void
1043 dump_cfg (ir_graph *irg)
1044 {
1045   int rem = dump_dominator_information_flag;
1046   vcg_open (irg, "-cfg");
1047
1048   if (get_irg_dom_state(irg) != dom_consistent)
1049     dump_dominator_information_flag = 0;
1050
1051   /* walk over the blocks in the graph */
1052   irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1053
1054   dump_dominator_information_flag = rem;
1055   vcg_close();
1056 }
1057
1058
1059 /***********************************************************************/
1060 /* the following routine dumps all type information reachable from an  */
1061 /* irg                                                                 */
1062 /***********************************************************************/
1063
1064
1065 void
1066 dump_type_graph (ir_graph *irg)
1067 {
1068   ir_graph *rem;
1069   rem = current_ir_graph;
1070   current_ir_graph = irg;
1071
1072   vcg_open (irg, "-type");
1073
1074   /* walk over the blocks in the graph */
1075   type_walk_irg(irg, dump_type_info, NULL, NULL);
1076   /* The walker for the const code can be called several times for the
1077      same (sub) experssion.  So that no nodes are dumped several times
1078      we decrease the visited flag of the corresponding graph after each
1079      walk.  So now increase it finally. */
1080   inc_irg_visited(get_const_code_irg());
1081
1082   vcg_close();
1083   current_ir_graph = rem;
1084 }
1085
1086 /***********************************************************************/
1087 /* the following routine dumps all type information                    */
1088 /***********************************************************************/
1089
1090
1091 void
1092 dump_all_types (void)
1093 {
1094   vcg_open_name ("All_types");
1095   type_walk(dump_type_info, NULL, NULL);
1096   inc_irg_visited(get_const_code_irg());
1097   vcg_close();
1098 }
1099
1100 /***********************************************************************/
1101 /* dumps a graph with type information                                 */
1102 /***********************************************************************/
1103
1104
1105 void
1106 dump_ir_graph_w_types (ir_graph *irg)
1107 {
1108   ir_graph *rem;
1109   rem = current_ir_graph;
1110   current_ir_graph = irg;
1111
1112   vcg_open (irg, "-all");
1113
1114   /* dump common ir graph */
1115   irg_walk(irg->end, dump_whole_node, NULL, NULL);
1116   /* dump type info */
1117   type_walk_irg(irg, dump_type_info, NULL, NULL);
1118   inc_irg_visited(get_const_code_irg());
1119   /* dump edges from graph to type info */
1120   irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1121
1122   vcg_close();
1123   current_ir_graph = rem;
1124 }
1125
1126 void
1127 dump_ir_block_graph_w_types (ir_graph *irg)
1128 {
1129   ir_graph *rem;
1130   rem = current_ir_graph;
1131   current_ir_graph = irg;
1132
1133   vcg_open (irg, "-all");
1134
1135   /* dump common blocked ir graph */
1136   dump_ir_block_graph_2(irg);
1137   /* dump type info */
1138   type_walk_irg(irg, dump_type_info, NULL, NULL);
1139   inc_irg_visited(get_const_code_irg());
1140   /* dump edges from graph to type info */
1141   irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1142
1143   vcg_close();
1144   current_ir_graph = rem;
1145 }
1146
1147 /***********************************************************************/
1148 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
1149 /*  dump_ir_graph                                                      */
1150 /*  dump_ir_block_graph                                                */
1151 /*  dump_cfg                                                           */
1152 /*  dump_type_graph                                                    */
1153 /*  dump_ir_graph_w_types                                              */
1154 /***********************************************************************/
1155 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1156   int i;
1157   for (i=0; i < get_irp_n_irgs(); i++) {
1158     dump_graph(get_irp_irg(i));
1159   }
1160 }
1161
1162
1163 /* To turn off display of edge labels.  Edge labels offen cause xvcg to
1164    abort with a segmentation fault. */
1165 void turn_off_edge_labels() {
1166   edge_label = 0;
1167 }
1168
1169 void turn_off_constant_entity_values() {
1170   const_entities = 0;
1171 }
1172
1173 void dump_keepalive_edges() {
1174   dump_keepalive = 1;
1175 }
1176
1177 void dump_out_edges() {
1178   dump_out_edge_flag = 1;
1179 }
1180
1181 void dump_dominator_information() {
1182   dump_dominator_information_flag = 1;
1183 }