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