autoconf stuff
[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 #ifdef HAVE_CONFIG_H
10 # include <config.h>
11 #endif
12
13 # include "irnode_t.h"
14 # include "irgraph_t.h"
15 # include "irprog.h"
16 # include "irdump.h"
17 # include "panic.h"
18 # include <string.h>
19 # include "entity.h"
20 # include <stdlib.h>
21 # include "array.h"
22 # include "irop_t.h"
23 # include "tv.h"
24 # include "type_or_entity.h"
25 # include "irgwalk.h"
26 # include "typewalk.h"
27
28 /* Attributes of nodes */
29 #define DEFAULT_NODE_ATTR ""
30 #define DEFAULT_TYPE_ATTRIBUTE ""
31
32 /* Attributes of edges between Firm nodes */
33 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
34 #define CF_EDGE_ATTR    "color: red"
35 #define MEM_EDGE_ATTR   "color: blue"
36
37 /* Attributes of edges between Firm nodes and type/entity nodes */
38 #define NODE2TYPE_EDGE_ATTR ""
39
40 /* Attributes of edges in type/entity graphs. */
41 #define TYPE_METH_NODE_ATTR  "color: lightyellow"
42 #define TYPE_CLASS_NODE_ATTR "color: green"
43 #define ENTITY_NODE_ATTR     "color: yellow"
44 #define ENT_TYPE_EDGE_ATTR   "label: \"type\" color: red"
45 #define ENT_OWN_EDGE_ATTR    "label: \"owner\" color: black"
46 #define METH_PAR_EDGE_ATTR   "label: \"param %d\" color: green"
47 #define METH_RES_EDGE_ATTR   "label: \"res %d\" color: green"
48 #define TYPE_SUPER_EDGE_ATTR "label: \"supertype\" color: blue"
49 #define PTR_PTS_TO_EDGE_ATTR "label: \"points to\" color:green"
50 #define ARR_ELT_TYPE_EDGE_ATTR "label: \"arr elt\" color:green"
51
52 #define PRINT_NODEID(X) fprintf(F, "%p", X)
53
54 /* file to dump to */
55 static FILE *F;
56
57
58 /*******************************************************************/
59 /* routines to dump information about a single node                */
60 /*******************************************************************/
61
62
63
64 inline void
65 dump_node_opcode (ir_node *n)
66 {
67   /* Const */
68   if (n->op->code == iro_Const) {
69     xfprintf (F, "%v", n->attr.con);
70   /* SymConst */
71   } else if (n->op->code == iro_SymConst) {
72     if (get_SymConst_kind(n) == linkage_ptr_info) {
73       xfprintf (F, "%I", get_SymConst_ptrinfo(n));
74     } else {
75       assert(get_kind(get_SymConst_type(n)) == k_type_class);
76       assert(get_class_ident((type_class *)get_SymConst_type(n)));
77       xfprintf (F, "%s ", id_to_str(get_class_ident((type_class *)get_SymConst_type(n))));
78       if (get_SymConst_kind == type_tag)
79         xfprintf (F, "tag");
80       else
81         xfprintf (F, "size");
82     }
83   /* all others */
84   } else {
85     xfprintf (F, "%I", get_irn_opident(n));
86   }
87 }
88
89 inline void
90 dump_node_mode (ir_node *n)
91 {
92   switch (n->op->code) {
93   case iro_Phi:
94   case iro_Const:
95   case iro_Id:
96   case iro_Proj:
97   case iro_Conv:
98   case iro_Tuple:
99   case iro_Add:
100   case iro_Sub:
101   case iro_Mul:
102   case iro_And:
103   case iro_Or:
104   case iro_Eor:
105   case iro_Shl:
106   case iro_Shr:
107   case iro_Abs:
108   case iro_Cmp:
109     xfprintf (F, "%I", get_mode_ident(n->mode));
110     break;
111   default:
112   }
113 }
114
115 inline void
116 dump_node_nodeattr (ir_node *n)
117 {
118   switch (n->op->code) {
119   case iro_Proj:
120     if (n->in[1]->op->code == iro_Cmp) {
121       xfprintf (F, "%s", get_pnc_string(n->attr.proj));
122     } else {
123       xfprintf (F, "%ld", n->attr.proj);
124     }
125     break;
126   case iro_Sel: {
127     assert(get_kind(get_Sel_entity(n)) == k_entity);
128     xfprintf (F, "%s", id_to_str(get_entity_ident(get_Sel_entity(n))));
129     } break;
130   default:
131   } /* end switch */
132 }
133
134 inline void
135 dump_node_vcgattr (ir_node *n)
136 {
137   switch (n->op->code) {
138   case iro_Start:
139   case iro_End:
140     xfprintf (F, "color: blue");
141     break;
142   case iro_Block:
143     xfprintf (F, "color: lightyellow");
144     break;
145   case iro_Phi:
146     xfprintf (F, "color: green");
147     break;
148   case iro_Const:
149   case iro_Proj:
150   case iro_Tuple:
151     xfprintf (F, "color: yellow");
152     break;
153   default:
154     xfprintf (F, DEFAULT_NODE_ATTR);
155   }
156 }
157
158 void
159 dump_node (ir_node *n) {
160
161   /* dump this node */
162   xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
163
164   dump_node_opcode(n);
165   dump_node_mode (n);
166   xfprintf (F, " ");
167   dump_node_nodeattr(n);
168 #ifdef DEBUG_libfirm
169   xfprintf (F, " %ld", get_irn_node_nr(n));
170 #endif
171   xfprintf (F, "\" ");
172   dump_node_vcgattr(n);
173   xfprintf (F, "}\n");
174 }
175
176 void
177 dump_ir_node (ir_node *n)
178 {
179   /* dump this node */
180   fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: ");
181
182   switch (n->op->code) {  /* node label */
183   case iro_Start:
184     xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
185     xfprintf (F, DEFAULT_NODE_ATTR);
186      break;
187   case iro_End:
188     xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
189     xfprintf (F, DEFAULT_NODE_ATTR);
190     break;
191   case iro_Block:
192     xfprintf (F, "\"%I\" color: lightyellow ", get_irn_opident(n));
193     xfprintf (F, DEFAULT_NODE_ATTR);
194     break;
195   case iro_Phi:
196     xfprintf (F, "\"%I%I\" color: green", get_irn_opident(n), get_irn_modeident(n));
197     if (get_irn_modecode(n) == irm_M)
198       xfprintf (F, DEFAULT_NODE_ATTR " color: green");
199     else
200       xfprintf (F, DEFAULT_NODE_ATTR);
201     break;
202   case iro_Const:
203     xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, get_irn_modeident(n));
204     xfprintf (F, DEFAULT_NODE_ATTR);
205     break;
206   case iro_Id:
207     xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
208     xfprintf (F, DEFAULT_NODE_ATTR);
209     break;
210   case iro_Proj:
211     if (n->in[1]->op->code == iro_Cmp) {
212       xfprintf (F, "\"%I%I %s\" color: yellow", get_irn_opident(n), get_irn_modeident(n),
213                 get_pnc_string(n->attr.proj));
214     } else {
215       xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.proj);
216     }
217     xfprintf (F, DEFAULT_NODE_ATTR);
218     break;
219   case iro_Conv:
220     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
221     xfprintf (F, DEFAULT_NODE_ATTR);
222     break;
223   case iro_Tuple:
224     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
225     xfprintf (F, DEFAULT_NODE_ATTR);
226     break;
227   case iro_Add:
228     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
229     xfprintf (F, DEFAULT_NODE_ATTR);
230     break;
231   case iro_Sub:
232     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
233     xfprintf (F, DEFAULT_NODE_ATTR);
234     break;
235   case iro_Mul:
236     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
237     xfprintf (F, DEFAULT_NODE_ATTR);
238     break;
239   case iro_Quot:
240     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
241     xfprintf (F, DEFAULT_NODE_ATTR);
242     break;
243   case iro_DivMod:
244     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
245     xfprintf (F, DEFAULT_NODE_ATTR);
246     break;
247   case iro_Div:
248     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
249     xfprintf (F, DEFAULT_NODE_ATTR);
250     break;
251   case iro_Mod:
252     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
253     xfprintf (F, DEFAULT_NODE_ATTR);
254     break;
255   case iro_And:
256     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
257     xfprintf (F, DEFAULT_NODE_ATTR);
258     break;
259   case iro_Or:
260     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
261     xfprintf (F, DEFAULT_NODE_ATTR);
262     break;
263   case iro_Eor:
264     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
265     xfprintf (F, DEFAULT_NODE_ATTR);
266     break;
267   case iro_Shl:
268     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
269     xfprintf (F, DEFAULT_NODE_ATTR);
270     break;
271   case iro_Shr:
272     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
273     xfprintf (F, DEFAULT_NODE_ATTR);
274     break;
275   case iro_Abs:
276     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
277     xfprintf (F, DEFAULT_NODE_ATTR);
278     break;
279   case iro_Cmp:
280     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
281     xfprintf (F, DEFAULT_NODE_ATTR);
282     break;
283   case iro_Jmp:
284     xfprintf (F, "\"%I\"", get_irn_opident(n));
285     xfprintf (F, DEFAULT_NODE_ATTR);
286     break;
287   case iro_Cond:
288     xfprintf (F, "\"%I\"", get_irn_opident(n));
289     xfprintf (F, DEFAULT_NODE_ATTR);
290     break;
291   case iro_Call:
292     xfprintf (F, "\"%I\"", get_irn_opident(n));
293     xfprintf (F, DEFAULT_NODE_ATTR);
294     break;
295   case iro_Return:
296     xfprintf (F, "\"%I\"", get_irn_opident(n));
297     xfprintf (F, DEFAULT_NODE_ATTR);
298     break;
299   case iro_Raise:
300     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
301     xfprintf (F, DEFAULT_NODE_ATTR);
302     break;
303   case iro_Load:
304   case iro_Store:
305     xfprintf (F, "\"%R\"", n);
306     xfprintf (F, DEFAULT_NODE_ATTR);
307     break;
308   case iro_Alloc:
309     xfprintf (F, "\"%I\" ", get_irn_opident(n));
310     xfprintf (F, DEFAULT_NODE_ATTR);
311     break;
312   case iro_Sel:
313     assert(get_kind(get_Sel_entity(n)) == k_entity);
314     xfprintf (F, "\"%I ", get_irn_opident(n));
315     xfprintf (F, "%s", id_to_str(get_entity_ident(get_Sel_entity(n))));
316     xfprintf (F, DEFAULT_NODE_ATTR);
317     break;
318   case iro_SymConst:
319     assert(get_kind(get_SymConst_type(n)) == k_type_class);
320     assert(get_class_ident((type_class *)get_SymConst_type(n)));
321     xfprintf (F, "\"%s ",
322               id_to_str(get_class_ident((type_class *)get_SymConst_type(n))));
323     switch (n->attr.i.num){
324     case type_tag:
325       xfprintf (F, "tag\" ");
326       break;
327     case size:
328       xfprintf (F, "size\" ");
329       break;
330     default:
331       assert(0);
332       break;
333     }
334     xfprintf (F, DEFAULT_NODE_ATTR);
335     break;
336   case iro_Sync:
337     xfprintf (F, "\"%I\" ", get_irn_opident(n));
338     xfprintf (F, DEFAULT_NODE_ATTR " color: green");
339     break;
340   case iro_Bad:
341     xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
342     xfprintf (F, DEFAULT_NODE_ATTR);
343     break;
344   default:
345     xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
346   }
347   xfprintf (F, "}\n");          /* footer */
348 }
349
350
351 /* dump the edge to the block this node belongs to */
352 void
353 dump_ir_block_edge(ir_node *n)  {
354   if (is_no_Block(n))
355     xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
356                 BLOCK_EDGE_ATTR "}\n", n, get_nodes_Block(n));
357 }
358
359 void print_edge_vcgattr(ir_node *from, int to) {
360   assert(from);
361
362   switch (get_irn_opcode(from)) {
363   case iro_Block:
364     xfprintf (F, CF_EDGE_ATTR);
365     break;
366   case iro_Start:   break;
367   case iro_End:     break;
368   case iro_Jmp:     break;
369   case iro_Cond:    break;
370   case iro_Return:
371   case iro_Raise:
372     if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
373     break;
374   case iro_Const:   break;
375   case iro_SymConst:break;
376   case iro_Sel:
377   case iro_Call:
378     if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
379     break;
380   case iro_Add:     break;
381   case iro_Sub:     break;
382   case iro_Minus:   break;
383   case iro_Mul:     break;
384   case iro_Quot:
385   case iro_DivMod:
386   case iro_Div:
387   case iro_Mod:
388     if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
389     break;
390   case iro_Abs:    break;
391   case iro_And:    break;
392   case iro_Or:     break;
393   case iro_Eor:    break;
394   case iro_Shl:    break;
395   case iro_Shr:    break;
396   case iro_Shrs:   break;
397   case iro_Rot:    break;
398   case iro_Cmp:    break;
399   case iro_Conv:   break;
400   case iro_Phi:
401     if (get_irn_modecode(from) == irm_M) xfprintf (F, MEM_EDGE_ATTR);
402     break;
403   case iro_Load:
404   case iro_Store:
405   case iro_Alloc:
406   case iro_Free:
407     if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
408     break;
409   case iro_Sync:
410     xfprintf (F, MEM_EDGE_ATTR);
411     break;
412   case iro_Tuple:  break;
413   case iro_Proj:
414     switch (get_irn_modecode(from)) {
415     case irm_X:
416       xfprintf (F, CF_EDGE_ATTR);
417       break;
418     case irm_M:
419       xfprintf (F, MEM_EDGE_ATTR);
420       break;
421     default: break;
422     }
423     break;
424   case iro_Bad:    break;
425   case iro_Id:     break;
426   default:
427   }
428 }
429
430 /* dump edges to our inputs */
431 void
432 dump_ir_data_edges(ir_node *n)  {
433   int i;
434
435   for (i = 0; i < get_irn_arity(n); i++) {
436     assert(get_irn_n(n, i));
437     xfprintf (F, "edge: {sourcename: \"%p\" targetname: \"%p\"",
438               n, get_irn_n(n, i));
439     fprintf (F, " label: \"%d\" ", i+1);
440     print_edge_vcgattr(n, i);
441     fprintf (F, "}\n");
442   }
443 }
444
445 /* dumps the edges between nodes and their type or entity attributes. */
446 void dump_node2type_edges (ir_node *n, void *env)
447 {
448   assert(n);
449
450   switch (get_irn_opcode(n)) {
451   case iro_SymConst:
452     if (   (get_SymConst_kind(n) == type_tag)
453         || (get_SymConst_kind(n) == size))
454       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
455                 NODE2TYPE_EDGE_ATTR "}\n", n, get_SymConst_type(n));
456     break;
457   case iro_Sel:
458     xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
459               NODE2TYPE_EDGE_ATTR "}\n", n, get_Sel_entity(n));
460     break;
461   case iro_Call:
462     xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
463               NODE2TYPE_EDGE_ATTR "}\n", n, get_Call_type(n));
464     break;
465   case iro_Alloc:
466     xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
467               NODE2TYPE_EDGE_ATTR "}\n", n, get_Alloc_type(n));
468     break;
469   case iro_Free:
470     xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
471               NODE2TYPE_EDGE_ATTR "}\n", n, get_Free_type(n));
472     break;
473   default:
474     break;
475   }
476 }
477
478
479 /* dumps a type or entity and it's edges. */
480 void
481 dump_type_info (type_or_ent *tore, void *env) {
482   int i = 0;  /* to shutup gcc */
483
484   /* dump this type or entity */
485   xfprintf (F, "node: {title: \"%p\" ", tore);
486   xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
487   xfprintf (F, "label: ");
488
489   switch (get_kind(tore)) {
490   case k_entity:
491     {
492       entity *ent = (entity *)tore;
493       xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR "}\n", get_entity_ident(ent));
494       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
495                 ENT_OWN_EDGE_ATTR "}\n", tore, get_entity_owner(ent));
496       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
497                 ENT_TYPE_EDGE_ATTR "}\n", tore, get_entity_type(ent));
498     } break;
499   case k_type_class:
500     {
501       type_class *type = (type_class *)tore;
502       xfprintf (F, "\"class %I\" " TYPE_CLASS_NODE_ATTR "}\n", get_class_ident(type));
503       for (i=0; i < get_class_n_supertype(type); i++)
504         xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
505                   TYPE_SUPER_EDGE_ATTR "}\n",
506                   type, get_class_supertype(type, i));
507     } break;
508   case k_type_strct:
509     {
510       type_strct *type = (type_strct *)tore;
511       xfprintf (F, "\"strct %I\"}\n", get_strct_ident(type));
512       /* edges !!!??? */
513     } break;
514   case k_type_method:
515     {
516       type_method *type = (type_method *)tore;
517       xfprintf (F, "\"meth %I\" " TYPE_METH_NODE_ATTR "}\n", get_method_ident(type));
518       for (i = 0; i < get_method_arity(type); i++)
519         xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
520                   METH_PAR_EDGE_ATTR "}\n",
521                   tore, get_method_param_type(type, i), i);
522       for (i = 0; i < get_method_n_res(type); i++)
523         xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
524                   METH_RES_EDGE_ATTR "}\n",
525                   tore, get_method_res_type(type, i), i);
526     } break;
527   case k_type_union:
528     {
529       type_union *type = (type_union *)tore;
530       xfprintf (F, "\"union %I\"}\n", get_union_ident(type));
531       /* edges !!!??? */
532     } break;
533   case k_type_array:
534     {
535       type_array *type = (type_array *)tore;
536       xfprintf (F, "\"array %I\"}\n", get_array_ident(type));
537       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
538                 ARR_ELT_TYPE_EDGE_ATTR "}\n", tore, get_array_element_type(type), i);
539       /* edges !!!??? */
540     } break;
541   case k_type_enumeration:
542     {
543       type_enumeration *type = (type_enumeration *)tore;
544       xfprintf (F, "\"enum %I\"}\n", get_enumeration_ident(type));
545     } break;
546   case k_type_pointer:
547     {
548       type_pointer *type = (type_pointer *)tore;
549       xfprintf (F, "\"ptr %I\"}\n", get_pointer_ident(type));
550       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
551                 PTR_PTS_TO_EDGE_ATTR "}\n", tore,
552                 get_pointer_points_to_type(type), i);
553     } break;
554   case k_type_primitive:
555     {
556       type_primitive *type = (type_primitive *)tore;
557       xfprintf (F, "\"prim %I, mode %I\"}\n", get_primitive_ident(type),
558                 get_mode_ident(get_primitive_mode(type)));
559     } break;
560   default:
561     {
562       xfprintf (F, "\" faulty type \"}\n");
563       printf(" *** irdump,  %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
564     } break;
565   }
566 }
567
568 /************************************************************************/
569 /* open and close vcg file                                              */
570 /************************************************************************/
571
572 void vcg_open (ir_graph *irg, char *suffix) {
573   char *fname;  /* filename to put the vcg information in */
574   const char *cp;
575   ident *id;
576   int len;
577
578   /** open file for vcg graph */
579   id    = get_entity_ld_name (get_irg_ent(irg));
580   len   = id_to_strlen (id);
581   cp    = id_to_str (id);
582
583   fname = malloc (len + 5 + strlen(suffix));
584   strncpy (fname, cp, len);      /* copy the filename */
585   fname[len] = '\0';
586   strcat (fname, suffix);  /* append file suffix */
587
588   fname = malloc (len + 5 + strlen(suffix));
589   strncpy (fname, cp, len); /* copy the filename */
590   fname[len] = '\0';        /* ensure string termination */
591   /*strcpy (fname, cp);      * copy the filename *
592     this produces wrong, too long strings in conjuction with the
593     jocca frontend.  The \0 seems to be missing. */
594   strcat (fname, suffix);   /* append file suffix */
595   strcat (fname, ".vcg");   /* append the .vcg suffix */
596   F = fopen (fname, "w");   /* open file for writing */
597   if (!F) {
598     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
599   }
600
601   /* print header */
602   xfprintf (F,
603             "graph: { title: \"ir graph of %s\"\n"
604             "display_edge_labels: yes\n"
605             "layoutalgorithm: mindepth\n"
606             "manhattan_edges: yes\n"
607             "port_sharing: no\n"
608             "orientation: bottom_to_top\n"
609             "classname 1: \"Data\"\n"
610             "classname 2: \"Block\"\n", cp);
611
612   xfprintf (F, "\n");           /* a separator */
613 }
614
615 void vcg_open_name (const char *name) {
616   char *fname;  /* filename to put the vcg information in */
617   int len;
618
619   /** open file for vcg graph */
620   len   = strlen(name);
621   fname = malloc (len + 5);
622   strcpy (fname, name);    /* copy the filename */
623   strcat (fname, ".vcg");  /* append the .vcg suffix */
624   F = fopen (fname, "w");  /* open file for writing */
625   if (!F) {
626     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
627   }
628
629   /* print header */
630   xfprintf (F,
631             "graph: { title: \"ir graph of %s\"\n"
632             "display_edge_labels: yes\n"
633             "layoutalgorithm: mindepth\n"
634             "manhattan_edges: yes\n"
635             "port_sharing: no\n"
636             "orientation: bottom_to_top\n"
637             "classname 1: \"Data\"\n"
638             "classname 2: \"Block\"\n", name);
639
640   xfprintf (F, "\n");           /* a separator */
641 }
642
643 void
644 vcg_close () {
645   xfprintf (F, "}\n");  /* print footer */
646   fclose (F);           /* close vcg file */
647 }
648
649 /************************************************************************/
650 /* routines to dump a graph, blocks as conventional nodes.              */
651 /************************************************************************/
652
653 void
654 dump_whole_node (ir_node *n, void* env) {
655   dump_node(n);
656   dump_ir_block_edge(n);
657   dump_ir_data_edges(n);
658 }
659
660 void
661 dump_ir_graph (ir_graph *irg)
662 {
663   ir_graph *rem;
664   rem = current_ir_graph;
665   current_ir_graph = irg;
666
667   vcg_open (irg, "");
668
669   /* walk over the graph */
670   irg_walk(irg->end, dump_whole_node, NULL, NULL);
671
672   vcg_close();
673
674   current_ir_graph = rem;
675 }
676
677 /***********************************************************************/
678 /* the following routines dump the nodes as attached to the blocks.    */
679 /***********************************************************************/
680
681 void
682 dump_ir_blocks_nodes (ir_node *n, void *env) {
683   ir_node *block = (ir_node *)env;
684
685   if (is_no_Block(n) && get_nodes_Block(n) == block) {
686     dump_node(n);
687     dump_ir_data_edges(n);
688   }
689 }
690
691 void
692 dump_ir_block (ir_node *block, void *env) {
693   ir_graph *irg = (ir_graph *)env;
694
695   if (get_irn_opcode(block) == iro_Block) {
696
697     /* This is a block. So dump the vcg information to make a block. */
698     xfprintf(F, "graph: { title: \""); PRINT_NODEID(block); fprintf(F, "\"  label: \"");
699 #ifdef DEBUG_libfirm
700     xfprintf (F, "%ld", get_irn_node_nr(block));
701 #else
702     xfprintf (F, "%I", block->op->name);
703 #endif
704     xfprintf(F, "\" status:clustered color:lightyellow \n");
705     /* dump the blocks edges */
706     dump_ir_data_edges(block);
707
708     /* dump the nodes that go into the block */
709     irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
710
711     /* Close the vcg information for the block */
712     xfprintf(F, "}\n\n");
713   }
714 }
715
716 void
717 dump_ir_block_graph (ir_graph *irg)
718 {
719   ir_graph *rem;
720   rem = current_ir_graph;
721   current_ir_graph = irg;
722
723   vcg_open (irg, "");
724
725   /* walk over the blocks in the graph */
726   irg_block_walk(irg->end, dump_ir_block, NULL, irg);
727
728   vcg_close();
729   current_ir_graph = rem;
730 }
731
732
733 /***********************************************************************/
734 /* the following routines dump a control flow graph                    */
735 /***********************************************************************/
736
737
738 void
739 dump_block_to_cfg (ir_node *block, void *env) {
740   int i;
741   ir_node *pred;
742
743   if (get_irn_opcode(block) == iro_Block) {
744     /* This is a block. Dump a node for the block. */
745     xfprintf (F, "node: {title: \"%p\" label: \"%I\"}", block,
746               block->op->name);
747     /* Dump the edges */
748     for ( i = 0; i < get_Block_n_cfgpreds(block); i++) {
749       pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
750       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" }\n",
751                 block, pred);
752     }
753   }
754 }
755
756 void
757 dump_cfg (ir_graph *irg)
758 {
759   vcg_open (irg, "-cfg");
760
761   /* walk over the blocks in the graph */
762   irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
763
764   vcg_close();
765 }
766
767
768 /***********************************************************************/
769 /* the following routine dumps all type information reachable from an  */
770 /* irg                                                                 */
771 /***********************************************************************/
772
773
774 void
775 dump_type_graph (ir_graph *irg)
776 {
777   ir_graph *rem;
778   rem = current_ir_graph;
779   current_ir_graph = irg;
780
781   vcg_open (irg, "-type");
782
783   /* walk over the blocks in the graph */
784   type_walk_irg(irg, dump_type_info, NULL, NULL);
785
786   vcg_close();
787   current_ir_graph = rem;
788 }
789
790 /***********************************************************************/
791 /* the following routine dumps all type information                    */
792 /***********************************************************************/
793
794
795 void
796 dump_all_types (void)
797 {
798   vcg_open_name ("All_types");
799   type_walk(dump_type_info, NULL, NULL);
800   vcg_close();
801 }
802
803 /***********************************************************************/
804 /* dumps a graph with type information                                 */
805 /***********************************************************************/
806
807
808 void
809 dump_ir_graph_w_types (ir_graph *irg)
810 {
811   ir_graph *rem;
812   rem = current_ir_graph;
813   current_ir_graph = irg;
814
815   vcg_open (irg, "-all");
816
817   /* dump common ir graph */
818   /*  irg_block_walk(irg->end, dump_ir_block, NULL, irg); */
819   irg_walk(irg->end, dump_whole_node, NULL, NULL);
820   /* dump type info */
821   type_walk_irg(irg, dump_type_info, NULL, NULL);
822   /* dump edges from graph to type info */
823   irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
824
825   vcg_close();
826   current_ir_graph = rem;
827 }
828
829 /***********************************************************************/
830 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
831 /*  dump_ir_graph                                                      */
832 /*  dump_ir_block_graph                                                */
833 /*  dump_cfg                                                           */
834 /*  dump_type_graph                                                    */
835 /*  dump_ir_graph_w_types                                              */
836 /***********************************************************************/
837 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
838   int i;
839   for (i=0; i < get_irp_n_irgs(); i++) {
840     dump_graph(get_irp_irg(i));
841   }
842 }