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