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