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