Bugfisx in dump_cfg.
[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:
409     if (to >= 0) {
410       if (get_irn_mode(get_End_keepalive(from, to)) == mode_R)
411         xfprintf (F, CF_EDGE_ATTR);
412       if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
413         xfprintf (F, MEM_EDGE_ATTR);
414     }
415     break;
416   case iro_Jmp:     break;
417   case iro_Cond:    break;
418   case iro_Return:
419   case iro_Raise:
420     if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
421     break;
422   case iro_Const:   break;
423   case iro_SymConst:break;
424   case iro_Sel:
425   case iro_Call:
426     if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
427     break;
428   case iro_Add:     break;
429   case iro_Sub:     break;
430   case iro_Minus:   break;
431   case iro_Mul:     break;
432   case iro_Quot:
433   case iro_DivMod:
434   case iro_Div:
435   case iro_Mod:
436     if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
437     break;
438   case iro_Abs:    break;
439   case iro_And:    break;
440   case iro_Or:     break;
441   case iro_Eor:    break;
442   case iro_Shl:    break;
443   case iro_Shr:    break;
444   case iro_Shrs:   break;
445   case iro_Rot:    break;
446   case iro_Cmp:    break;
447   case iro_Conv:   break;
448   case iro_Phi:
449     if (get_irn_modecode(from) == irm_M) xfprintf (F, MEM_EDGE_ATTR);
450     break;
451   case iro_Load:
452   case iro_Store:
453   case iro_Alloc:
454   case iro_Free:
455     if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
456     break;
457   case iro_Sync:
458     xfprintf (F, MEM_EDGE_ATTR);
459     break;
460   case iro_Tuple:  break;
461   case iro_Proj:
462     switch (get_irn_modecode(from)) {
463     case irm_X:
464       xfprintf (F, CF_EDGE_ATTR);
465       break;
466     case irm_M:
467       xfprintf (F, MEM_EDGE_ATTR);
468       break;
469     default: break;
470     }
471     break;
472   case iro_Bad:    break;
473   case iro_Id:     break;
474   default:
475   }
476 }
477
478 /* dump edges to our inputs */
479 void
480 dump_ir_data_edges(ir_node *n)  {
481   int i, max;
482
483   if ((get_irn_op(n) == op_End) && (!dump_keepalive))
484     return;
485
486   for (i = 0; i < get_irn_arity(n); i++) {
487     assert(get_irn_n(n, i));
488     fprintf (F, "edge: {sourcename: \"");
489     PRINT_NODEID(n);
490     fprintf (F, "\" targetname: \"");
491     PRINT_NODEID(get_irn_n(n, i));
492     fprintf (F, "\"");
493     fprintf (F, " label: \"%d\" ", i);
494     print_edge_vcgattr(n, i);
495     fprintf (F, "}\n");
496   }
497 }
498
499 /* dump out edges */
500 void
501 dump_out_edge (ir_node *n, void* env) {
502   int i;
503   for (i = 0; i < get_irn_n_outs(n); i++) {
504     assert(get_irn_out(n, i));
505     fprintf (F, "edge: {sourcename: \"");
506     PRINT_NODEID(n);
507     fprintf (F, "\" targetname: \"");
508     PRINT_NODEID(get_irn_out(n, i));
509     fprintf (F, "\" color: red linestyle: dashed");
510     fprintf (F, "}\n");
511   }
512 }
513
514
515 /* dumps the edges between nodes and their type or entity attributes. */
516 void dump_node2type_edges (ir_node *n, void *env)
517 {
518   assert(n);
519
520   switch (get_irn_opcode(n)) {
521   case iro_Const :
522     /* @@@ some consts have an entity */
523     break;
524   case iro_SymConst:
525     if (   (get_SymConst_kind(n) == type_tag)
526            || (get_SymConst_kind(n) == size)) {
527       xfprintf (F, "edge: { sourcename: \"");
528       PRINT_NODEID(n);
529       fprintf (F, "\" targetname: \"%p\" "
530                NODE2TYPE_EDGE_ATTR "}\n", get_SymConst_type(n));
531     }
532     break;
533   case iro_Sel: {
534     xfprintf (F, "edge: { sourcename: \"");
535     PRINT_NODEID(n);
536     fprintf (F, "\" targetname: \"%p\" "
537              NODE2TYPE_EDGE_ATTR "}\n", get_Sel_entity(n));
538     } break;
539   case iro_Call: {
540     xfprintf (F, "edge: { sourcename: \"");
541     PRINT_NODEID(n);
542     fprintf (F, "\" targetname: \"%p\" "
543              NODE2TYPE_EDGE_ATTR "}\n", get_Call_type(n));
544     } break;
545   case iro_Alloc: {
546     xfprintf (F, "edge: { sourcename: \"");
547     PRINT_NODEID(n);
548     fprintf (F, "\" targetname: \"%p\" "
549              NODE2TYPE_EDGE_ATTR "}\n", get_Alloc_type(n));
550     } break;
551   case iro_Free: {
552     xfprintf (F, "edge: { sourcename: \"");
553     PRINT_NODEID(n);
554     fprintf (F, "\" targetname: \"%p\" "
555              NODE2TYPE_EDGE_ATTR "}\n", get_Free_type(n));
556     } break;
557   default:
558     break;
559   }
560 }
561
562
563 void dump_const_expression(ir_node *value) {
564   ir_graph *rem = current_ir_graph;
565   current_ir_graph = get_const_code_irg();
566   irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
567   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
568   current_ir_graph = rem;
569 }
570
571
572 void print_type_info(type *tp) {
573   if (get_type_state(tp) == layout_undefined) {
574     xfprintf(F, "state: layout_undefined\n");
575   } else {
576     xfprintf(F, "state: layout_fixed,\n");
577   }
578   if (get_type_mode(tp))
579     xfprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
580   xfprintf(F, "size: %dB,\n", get_type_size(tp));
581 }
582
583
584 void print_typespecific_info(type *tp) {
585   switch (get_type_tpop_code(tp)) {
586   case tpo_class:
587     {
588            xfprintf (F, " " TYPE_CLASS_NODE_ATTR);
589     } break;
590   case tpo_struct:
591     {
592       xfprintf (F, " " TYPE_METH_NODE_ATTR);
593     } break;
594   case tpo_method:
595     {
596     } break;
597   case tpo_union:
598     {
599     } break;
600   case tpo_array:
601     {
602     } break;
603   case tpo_enumeration:
604     {
605     } break;
606   case tpo_pointer:
607     {
608     } break;
609   case tpo_primitive:
610     {
611     } break;
612   default: break;
613   } /* switch type */
614 }
615
616 void print_type_node(type *tp) {
617   xfprintf (F, "node: {title: \"%p\" ", tp);
618   xfprintf (F, "label: \"%I %I\"", get_type_tpop_nameid(tp), get_type_ident(tp));
619   xfprintf (F, "info1: \"");
620   print_type_info(tp);
621   xfprintf (F, "\"");
622   print_typespecific_info(tp);
623   xfprintf (F, "}\n");
624 }
625
626 /* dumps a type or entity and it's edges. */
627 void
628 dump_type_info (type_or_ent *tore, void *env) {
629   int i = 0;  /* to shutup gcc */
630
631   /* dump this type or entity */
632
633   switch (get_kind(tore)) {
634   case k_entity:
635     {
636       entity *ent = (entity *)tore;
637       ir_node *value;
638       /* The node */
639       xfprintf (F, "node: {title: \"%p\" ", tore);
640       xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
641       xfprintf (F, "label: ");
642       xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR , get_entity_ident(ent));
643       if(dynamic_allocated == get_entity_allocation(ent))
644         xfprintf (F, " info1:\"dynamic allocated\n");
645       else
646         xfprintf (F, " info1:\"static allocated\n");
647       switch (get_entity_visibility(ent)) {
648         case local:              fprintf (F, "local\n");             break;
649         case external_visible:   fprintf (F, "external_visible\n");  break;
650         case external_allocated: fprintf (F, "external_allocate\n");break;
651       }
652       switch (get_entity_variability(ent)) {
653         case uninitialized: fprintf (F, "uninitialized");break;
654         case initialized:   fprintf (F, "initialized");  break;
655         case part_constant: fprintf (F, "part_constant");break;
656         case constant:      fprintf (F, "constant");     break;
657       }
658       if (is_method_type(get_entity_type(ent)))
659         xfprintf (F, "\n irg = %p ", get_entity_irg(ent));
660       xfprintf(F, "\"}\n");
661       /* The Edges */
662       /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
663       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
664                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
665       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
666                 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
667       for(i = 0; i < get_entity_n_overwrites(ent); i++)
668         xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
669                   ENT_OVERWRITES_EDGE_ATTR "}\n", ent, get_entity_overwrites(ent, i));
670       /* attached subgraphs */
671       if (const_entities && (get_entity_variability(ent) != uninitialized)) {
672         if (is_atomic_entity(ent)) {
673           value = get_atomic_ent_value(ent);
674           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
675           PRINT_NODEID(value);
676           fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
677           dump_const_expression(value);
678         }
679         if (is_compound_entity(ent)) {
680           for (i = 0; i < get_compound_ent_n_values(ent); i++) {
681             value = get_compound_ent_value(ent, i);
682             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
683             PRINT_NODEID(value);
684             fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
685             dump_const_expression(value);
686             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
687                       ENT_CORR_EDGE_ATTR  "}\n", ent,
688                       get_compound_ent_value_member(ent, i), i);
689           }
690         }
691       }
692     } break;
693   case k_type:
694     {
695       type *tp = (type *)tore;
696       print_type_node(tp);
697       /* and now the edges */
698       switch (get_type_tpop_code(tp)) {
699       case tpo_class:
700         {
701           for (i=0; i < get_class_n_supertype(tp); i++)
702             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
703                       TYPE_SUPER_EDGE_ATTR "}\n",
704                       tp, get_class_supertype(tp, i));
705           for (i=0; i < get_class_n_member(tp); i++)
706             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
707                       TYPE_MEMBER_EDGE_ATTR "}\n",
708                       tp, get_class_member(tp, i));
709         } break;
710       case tpo_struct:
711         {
712           for (i=0; i < get_struct_n_member(tp); i++)
713             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
714                       TYPE_MEMBER_EDGE_ATTR "}\n",
715                       tp, get_struct_member(tp, i));
716         } break;
717       case tpo_method:
718         {
719           for (i = 0; i < get_method_n_params(tp); i++)
720             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
721                       METH_PAR_EDGE_ATTR "}\n",
722                       tp, get_method_param_type(tp, i), i);
723           for (i = 0; i < get_method_n_res(tp); i++)
724             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
725                       METH_RES_EDGE_ATTR "}\n",
726                       tp, get_method_res_type(tp, i), i);
727         } break;
728       case tpo_union:
729         {
730           for (i = 0; i < get_union_n_members(tp); i++)
731             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
732                       "label: \"\"f" UNION_EDGE_ATTR "}\n",
733                       tp, get_union_member(tp, i));
734         } break;
735       case tpo_array:
736         {
737           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
738                     ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
739           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
740                     ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
741         } break;
742       case tpo_enumeration:
743         {
744         } break;
745       case tpo_pointer:
746         {
747           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
748                     PTR_PTS_TO_EDGE_ATTR "}\n", tp,
749                     get_pointer_points_to_type(tp), i);
750         } break;
751       case tpo_primitive:
752         {
753         } break;
754       default: break;
755       } /* switch type */
756     }
757     break; /* case k_type */
758   default:
759     {
760       printf(" *** irdump,  %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
761     } break;
762   } /* switch kind_or_entity */
763 }
764
765 /************************************************************************/
766 /* open and close vcg file                                              */
767 /************************************************************************/
768
769 void vcg_open (ir_graph *irg, char *suffix) {
770   char *fname;  /* filename to put the vcg information in */
771   const char *cp;
772   ident *id;
773   int len;
774   char label[4];
775   entity *ent;
776
777   /** open file for vcg graph */
778   ent = get_irg_ent(irg);
779   id    = ent->ld_name ? ent->ld_name : ent->name;
780   /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
781   len   = id_to_strlen (id);
782   cp    = id_to_str (id);
783   if (dump_file_suffix)
784     fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
785   else
786     fname = malloc (len + 5 + strlen(suffix));
787   strncpy (fname, cp, len);      /* copy the filename */
788   fname[len] = '\0';
789   if (dump_file_suffix) strcat (fname, dump_file_suffix);  /* append file suffix */
790   strcat (fname, suffix);  /* append file suffix */
791   strcat (fname, ".vcg");   /* append the .vcg suffix */
792   F = fopen (fname, "w");   /* open file for writing */
793   if (!F) {
794     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
795   }
796
797   if (edge_label) {
798     strcpy(label, "yes");
799   } else {
800     strcpy (label, "no");
801   }
802
803   /* print header */
804   xfprintf (F,
805             "graph: { title: \"ir graph of %s\"\n"
806             "display_edge_labels: %s\n"
807             "layoutalgorithm: mindepth\n"
808             "manhattan_edges: yes\n"
809             "port_sharing: no\n"
810             "orientation: bottom_to_top\n"
811             "classname 1: \"Data\"\n"
812             "classname 2: \"Block\"\n"
813             "classname 3: \"Entity type\""
814             "classname 4: \"Entity owner\""
815             "classname 5: \"Method Param\""
816             "classname 6: \"Method Res\""
817             "classname 7: \"Super\""
818             "classname 8: \"Union\""
819             "classname 9: \"Points-to\""
820             "classname 10: \"Array Element Type\""
821             "classname 11: \"Overwrites\""
822             "classname 12: \"Member\""
823             , cp, label);
824
825   xfprintf (F, "\n");           /* a separator */
826 }
827
828 void vcg_open_name (const char *name) {
829   char *fname;  /* filename to put the vcg information in */
830   int len;
831   char label[4];
832
833   /** open file for vcg graph */
834   len   = strlen(name);
835   fname = malloc (len + 5);
836   strcpy (fname, name);    /* copy the filename */
837   strcat (fname, ".vcg");  /* append the .vcg suffix */
838   F = fopen (fname, "w");  /* open file for writing */
839   if (!F) {
840     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
841   }
842
843   if (edge_label) {
844     strcpy(label, "yes");
845   } else {
846     strcpy (label, "no");
847   }
848
849   /* print header */
850   xfprintf (F,
851             "graph: { title: \"ir graph of %s\"\n"
852             "display_edge_labels: %s\n"
853             "layoutalgorithm: mindepth\n"
854             "manhattan_edges: yes\n"
855             "port_sharing: no\n"
856             "orientation: bottom_to_top\n"
857             "classname 1: \"Data\"\n"
858             "classname 2: \"Block\"\n"
859             "classname 3: \"Entity type\"\n"
860             "classname 4: \"Entity owner\"\n"
861             "classname 5: \"Method Param\"\n"
862             "classname 6: \"Method Res\"\n"
863             "classname 7: \"Super\"\n"
864             "classname 8: \"Union\"\n"
865             "classname 9: \"Points-to\"\n"
866             "classname 10: \"Array Element Type\"\n"
867             "classname 11: \"Overwrites\"\n"
868             "classname 12: \"Member\"\n"
869             , name, label);
870
871   xfprintf (F, "\n");           /* a separator */
872 }
873
874 void
875 vcg_close () {
876   xfprintf (F, "}\n");  /* print footer */
877   fclose (F);           /* close vcg file */
878 }
879
880 /************************************************************************/
881 /* routines to dump a graph, blocks as conventional nodes.              */
882 /************************************************************************/
883
884 void
885 dump_whole_node (ir_node *n, void* env) {
886   dump_node(n);
887   if (!node_floats(n)) dump_ir_block_edge(n);
888   dump_ir_data_edges(n);
889 }
890
891 void
892 dump_ir_graph (ir_graph *irg)
893 {
894   ir_graph *rem;
895   rem = current_ir_graph;
896   current_ir_graph = irg;
897
898   vcg_open (irg, "");
899
900   /* walk over the graph */
901   irg_walk(irg->end, dump_whole_node, NULL, NULL);
902
903   /* dump the out edges in a separate walk */
904   if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
905     irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
906   }
907
908   vcg_close();
909
910   current_ir_graph = rem;
911 }
912
913 /***********************************************************************/
914 /* the following routines dump the nodes as attached to the blocks.    */
915 /***********************************************************************/
916
917 int node_floats(ir_node *n) {
918
919   return ((get_op_pinned(get_irn_op(n)) == floats) &&
920           (get_irg_pinned(current_ir_graph) == floats));
921 }
922
923 void
924 dump_ir_blocks_nodes (ir_node *n, void *env) {
925   ir_node *block = (ir_node *)env;
926
927   if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
928     dump_node(n);
929     dump_ir_data_edges(n);
930   }
931   if (get_irn_op(n) == op_Bad)
932     Bad_dumped = 1;
933 }
934
935 void
936 dump_ir_block (ir_node *block, void *env) {
937   ir_graph *irg = (ir_graph *)env;
938
939   if (get_irn_opcode(block) == iro_Block) {
940
941     /* This is a block. So dump the vcg information to make a block. */
942     xfprintf(F, "graph: { title: \""); PRINT_NODEID(block); fprintf(F, "\"  label: \"");
943 #ifdef DEBUG_libfirm
944     xfprintf (F, "%ld", get_irn_node_nr(block));
945 #else
946     xfprintf (F, "%I", block->op->name);
947 #endif
948     xfprintf(F, "\" status:clustered color:%s \n",
949                          get_Block_matured (block) ? "yellow" : "red");
950     /* dump the blocks edges */
951     dump_ir_data_edges(block);
952
953     /* dump the nodes that go into the block */
954     irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
955
956     /* Close the vcg information for the block */
957     xfprintf(F, "}\n\n");
958   }
959 }
960
961
962 void
963 dump_blockless_nodes (ir_node *n, void *env) {
964   if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
965     dump_node(n);
966     dump_ir_data_edges(n);
967     dump_ir_block_edge(n);
968     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
969     return;
970   }
971   if (node_floats(n)) {
972     dump_node(n);
973     dump_ir_data_edges(n);
974     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
975   }
976 }
977
978 void dump_ir_block_graph_2  (ir_graph *irg)
979 {
980   Bad_dumped = 0;
981   /* walk over the blocks in the graph */
982   irg_block_walk(irg->end, dump_ir_block, NULL, irg);
983
984   /* dump all nodes that are not in a Block */
985   irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
986
987   /* dump the Bad node */
988   if (!Bad_dumped)
989     dump_node(get_irg_bad(irg));
990 }
991
992 void
993 dump_ir_block_graph (ir_graph *irg)
994 {
995   ir_graph *rem;
996   rem = current_ir_graph;
997   current_ir_graph = irg;
998
999   vcg_open (irg, "");
1000
1001   dump_ir_block_graph_2 (irg);
1002
1003   vcg_close();
1004   current_ir_graph = rem;
1005 }
1006
1007
1008 /***********************************************************************/
1009 /* the following routines dump a control flow graph                    */
1010 /***********************************************************************/
1011
1012
1013 void
1014 dump_block_to_cfg (ir_node *block, void *env) {
1015   int i;
1016   ir_node *pred;
1017
1018   if (get_irn_opcode(block) == iro_Block) {
1019     /* This is a block. Dump a node for the block. */
1020     xfprintf (F, "node: {title:\""); PRINT_NODEID(block);
1021     xfprintf (F, "\" label: \"%I ", block->op->name); PRINT_NODEID(block);
1022     xfprintf (F, "\" ");
1023     if (dump_dominator_information_flag)
1024       xfprintf(F, "info1:\"dom depth %d\"", get_Block_dom_depth(block));
1025     xfprintf (F, "}\n");
1026     /* Dump the edges */
1027     for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1028       if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1029         pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1030         xfprintf (F, "edge: { sourcename: \"");
1031         PRINT_NODEID(block);
1032         fprintf (F, "\" targetname: \"");
1033         PRINT_NODEID(pred);
1034         fprintf (F, "\" }\n");
1035       }
1036
1037     /* Dump dominator edge */
1038     if (dump_dominator_information_flag && get_Block_idom(block)) {
1039       pred = get_Block_idom(block);
1040       xfprintf (F, "edge: { sourcename: \"");
1041       PRINT_NODEID(block);
1042       fprintf (F, "\" targetname: \"");
1043       PRINT_NODEID(pred);
1044       fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1045     }
1046   }
1047 }
1048
1049 void
1050 dump_cfg (ir_graph *irg)
1051 {
1052   ir_graph *rem = current_ir_graph;
1053   int ddif = dump_dominator_information_flag;
1054   current_ir_graph = irg;
1055   vcg_open (irg, "-cfg");
1056
1057   if (get_irg_dom_state(irg) != dom_consistent)
1058     dump_dominator_information_flag = 0;
1059
1060   /* walk over the blocks in the graph */
1061   irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1062
1063   dump_dominator_information_flag = ddif;
1064   vcg_close();
1065   current_ir_graph = rem;
1066 }
1067
1068
1069 /***********************************************************************/
1070 /* the following routine dumps all type information reachable from an  */
1071 /* irg                                                                 */
1072 /***********************************************************************/
1073
1074
1075 void
1076 dump_type_graph (ir_graph *irg)
1077 {
1078   ir_graph *rem;
1079   rem = current_ir_graph;
1080   current_ir_graph = irg;
1081
1082   vcg_open (irg, "-type");
1083
1084   /* walk over the blocks in the graph */
1085   type_walk_irg(irg, dump_type_info, NULL, NULL);
1086   /* The walker for the const code can be called several times for the
1087      same (sub) experssion.  So that no nodes are dumped several times
1088      we decrease the visited flag of the corresponding graph after each
1089      walk.  So now increase it finally. */
1090   inc_irg_visited(get_const_code_irg());
1091
1092   vcg_close();
1093   current_ir_graph = rem;
1094 }
1095
1096 /***********************************************************************/
1097 /* the following routine dumps all type information                    */
1098 /***********************************************************************/
1099
1100
1101 void
1102 dump_all_types (void)
1103 {
1104   vcg_open_name ("All_types");
1105   type_walk(dump_type_info, NULL, NULL);
1106   inc_irg_visited(get_const_code_irg());
1107   vcg_close();
1108 }
1109
1110 /***********************************************************************/
1111 /* dumps a graph with type information                                 */
1112 /***********************************************************************/
1113
1114
1115 void
1116 dump_ir_graph_w_types (ir_graph *irg)
1117 {
1118   ir_graph *rem;
1119   rem = current_ir_graph;
1120   current_ir_graph = irg;
1121
1122   vcg_open (irg, "-all");
1123
1124   /* dump common ir graph */
1125   irg_walk(irg->end, dump_whole_node, NULL, NULL);
1126   /* dump type info */
1127   type_walk_irg(irg, dump_type_info, NULL, NULL);
1128   inc_irg_visited(get_const_code_irg());
1129   /* dump edges from graph to type info */
1130   irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1131
1132   vcg_close();
1133   current_ir_graph = rem;
1134 }
1135
1136 void
1137 dump_ir_block_graph_w_types (ir_graph *irg)
1138 {
1139   ir_graph *rem;
1140   rem = current_ir_graph;
1141   current_ir_graph = irg;
1142
1143   vcg_open (irg, "-all");
1144
1145   /* dump common blocked ir graph */
1146   dump_ir_block_graph_2(irg);
1147   /* dump type info */
1148   type_walk_irg(irg, dump_type_info, NULL, NULL);
1149   inc_irg_visited(get_const_code_irg());
1150   /* dump edges from graph to type info */
1151   irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1152
1153   vcg_close();
1154   current_ir_graph = rem;
1155 }
1156
1157 /***********************************************************************/
1158 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
1159 /*  dump_ir_graph                                                      */
1160 /*  dump_ir_block_graph                                                */
1161 /*  dump_cfg                                                           */
1162 /*  dump_type_graph                                                    */
1163 /*  dump_ir_graph_w_types                                              */
1164 /***********************************************************************/
1165 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1166   int i;
1167   for (i=0; i < get_irp_n_irgs(); i++) {
1168     dump_graph(get_irp_irg(i));
1169   }
1170 }
1171
1172
1173 /* To turn off display of edge labels.  Edge labels offen cause xvcg to
1174    abort with a segmentation fault. */
1175 void turn_off_edge_labels() {
1176   edge_label = 0;
1177 }
1178
1179 void turn_off_constant_entity_values() {
1180   const_entities = 0;
1181 }
1182
1183 void dump_keepalive_edges() {
1184   dump_keepalive = 1;
1185 }
1186
1187 void dump_out_edges() {
1188   dump_out_edge_flag = 1;
1189 }
1190
1191 void dump_dominator_information() {
1192   dump_dominator_information_flag = 1;
1193 }