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