129d25623c061071e95cf5de2e6804d653fd00b8
[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 UNION_EDGE_ATTR      "label: \"component\" color: blue"
50 #define PTR_PTS_TO_EDGE_ATTR "label: \"points to\" color:green"
51 #define ARR_ELT_TYPE_EDGE_ATTR "label: \"arr elt\" color:green"
52
53 #define PRINT_NODEID(X) fprintf(F, "%p", X)
54
55 /* file to dump to */
56 static FILE *F;
57
58 int edge_label = 1;
59
60 /*******************************************************************/
61 /* routines to dump information about a single node                */
62 /*******************************************************************/
63
64
65
66 inline void
67 dump_node_opcode (ir_node *n)
68 {
69   /* Const */
70   if (n->op->code == iro_Const) {
71     xfprintf (F, "%v", n->attr.con);
72   /* SymConst */
73   } else if (n->op->code == iro_SymConst) {
74     if (get_SymConst_kind(n) == linkage_ptr_info) {
75       xfprintf (F, "%I", get_SymConst_ptrinfo(n));
76     } else {
77       assert(get_kind(get_SymConst_type(n)) == k_type);
78       assert(get_type_nameid(get_SymConst_type(n)));
79       xfprintf (F, "%s ", id_to_str(get_type_nameid(get_SymConst_type(n))));
80       if (get_SymConst_kind == type_tag)
81         xfprintf (F, "tag");
82       else
83         xfprintf (F, "size");
84     }
85   /* all others */
86   } else {
87     xfprintf (F, "%I", get_irn_opident(n));
88   }
89 }
90
91 inline void
92 dump_node_mode (ir_node *n)
93 {
94   switch (n->op->code) {
95   case iro_Phi:
96   case iro_Const:
97   case iro_Id:
98   case iro_Proj:
99   case iro_Conv:
100   case iro_Tuple:
101   case iro_Add:
102   case iro_Sub:
103   case iro_Mul:
104   case iro_And:
105   case iro_Or:
106   case iro_Eor:
107   case iro_Shl:
108   case iro_Shr:
109   case iro_Abs:
110   case iro_Cmp:
111     xfprintf (F, "%I", get_mode_ident(n->mode));
112     break;
113   default:
114   }
115 }
116
117 inline void
118 dump_node_nodeattr (ir_node *n)
119 {
120   switch (n->op->code) {
121   case iro_Proj:
122     if (n->in[1]->op->code == iro_Cmp) {
123       xfprintf (F, "%s", get_pnc_string(n->attr.proj));
124     } else {
125       xfprintf (F, "%ld", n->attr.proj);
126     }
127     break;
128   case iro_Sel: {
129     assert(get_kind(get_Sel_entity(n)) == k_entity);
130     xfprintf (F, "%s", id_to_str(get_entity_ident(get_Sel_entity(n))));
131     } break;
132   default:
133   } /* end switch */
134 }
135
136 inline void
137 dump_node_vcgattr (ir_node *n)
138 {
139   switch (n->op->code) {
140   case iro_Start:
141   case iro_End:
142     xfprintf (F, "color: blue");
143     break;
144   case iro_Block:
145     xfprintf (F, "color: lightyellow");
146     break;
147   case iro_Phi:
148     xfprintf (F, "color: green");
149     break;
150   case iro_Const:
151   case iro_Proj:
152   case iro_Tuple:
153     xfprintf (F, "color: yellow");
154     break;
155   default:
156     xfprintf (F, DEFAULT_NODE_ATTR);
157   }
158 }
159
160 void
161 dump_node (ir_node *n) {
162
163   /* dump this node */
164   xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
165
166   dump_node_opcode(n);
167   dump_node_mode (n);
168   xfprintf (F, " ");
169   dump_node_nodeattr(n);
170 #ifdef DEBUG_libfirm
171   xfprintf (F, " %ld", get_irn_node_nr(n));
172 #endif
173   xfprintf (F, "\" ");
174   dump_node_vcgattr(n);
175   xfprintf (F, "}\n");
176 }
177
178 void
179 dump_ir_node (ir_node *n)
180 {
181   /* dump this node */
182   fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: ");
183
184   switch (n->op->code) {  /* node label */
185   case iro_Start:
186     xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
187     xfprintf (F, DEFAULT_NODE_ATTR);
188      break;
189   case iro_End:
190     xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
191     xfprintf (F, DEFAULT_NODE_ATTR);
192     break;
193   case iro_Block:
194     xfprintf (F, "\"%I\" color: lightyellow ", get_irn_opident(n));
195     xfprintf (F, DEFAULT_NODE_ATTR);
196     break;
197   case iro_Phi:
198     xfprintf (F, "\"%I%I\" color: green", get_irn_opident(n), get_irn_modeident(n));
199     if (get_irn_modecode(n) == irm_M)
200       xfprintf (F, DEFAULT_NODE_ATTR " color: green");
201     else
202       xfprintf (F, DEFAULT_NODE_ATTR);
203     break;
204   case iro_Const:
205     xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, get_irn_modeident(n));
206     xfprintf (F, DEFAULT_NODE_ATTR);
207     break;
208   case iro_Id:
209     xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
210     xfprintf (F, DEFAULT_NODE_ATTR);
211     break;
212   case iro_Proj:
213     if (n->in[1]->op->code == iro_Cmp) {
214       xfprintf (F, "\"%I%I %s\" color: yellow", get_irn_opident(n), get_irn_modeident(n),
215                 get_pnc_string(n->attr.proj));
216     } else {
217       xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.proj);
218     }
219     xfprintf (F, DEFAULT_NODE_ATTR);
220     break;
221   case iro_Conv:
222     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
223     xfprintf (F, DEFAULT_NODE_ATTR);
224     break;
225   case iro_Tuple:
226     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
227     xfprintf (F, DEFAULT_NODE_ATTR);
228     break;
229   case iro_Add:
230     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
231     xfprintf (F, DEFAULT_NODE_ATTR);
232     break;
233   case iro_Sub:
234     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
235     xfprintf (F, DEFAULT_NODE_ATTR);
236     break;
237   case iro_Mul:
238     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
239     xfprintf (F, DEFAULT_NODE_ATTR);
240     break;
241   case iro_Quot:
242     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
243     xfprintf (F, DEFAULT_NODE_ATTR);
244     break;
245   case iro_DivMod:
246     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
247     xfprintf (F, DEFAULT_NODE_ATTR);
248     break;
249   case iro_Div:
250     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
251     xfprintf (F, DEFAULT_NODE_ATTR);
252     break;
253   case iro_Mod:
254     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
255     xfprintf (F, DEFAULT_NODE_ATTR);
256     break;
257   case iro_And:
258     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
259     xfprintf (F, DEFAULT_NODE_ATTR);
260     break;
261   case iro_Or:
262     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
263     xfprintf (F, DEFAULT_NODE_ATTR);
264     break;
265   case iro_Eor:
266     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
267     xfprintf (F, DEFAULT_NODE_ATTR);
268     break;
269   case iro_Shl:
270     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
271     xfprintf (F, DEFAULT_NODE_ATTR);
272     break;
273   case iro_Shr:
274     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
275     xfprintf (F, DEFAULT_NODE_ATTR);
276     break;
277   case iro_Abs:
278     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
279     xfprintf (F, DEFAULT_NODE_ATTR);
280     break;
281   case iro_Cmp:
282     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
283     xfprintf (F, DEFAULT_NODE_ATTR);
284     break;
285   case iro_Jmp:
286     xfprintf (F, "\"%I\"", get_irn_opident(n));
287     xfprintf (F, DEFAULT_NODE_ATTR);
288     break;
289   case iro_Cond:
290     xfprintf (F, "\"%I\"", get_irn_opident(n));
291     xfprintf (F, DEFAULT_NODE_ATTR);
292     break;
293   case iro_Call:
294     xfprintf (F, "\"%I\"", get_irn_opident(n));
295     xfprintf (F, DEFAULT_NODE_ATTR);
296     break;
297   case iro_Return:
298     xfprintf (F, "\"%I\"", get_irn_opident(n));
299     xfprintf (F, DEFAULT_NODE_ATTR);
300     break;
301   case iro_Raise:
302     xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
303     xfprintf (F, DEFAULT_NODE_ATTR);
304     break;
305   case iro_Load:
306   case iro_Store:
307     xfprintf (F, "\"%R\"", n);
308     xfprintf (F, DEFAULT_NODE_ATTR);
309     break;
310   case iro_Alloc:
311     xfprintf (F, "\"%I\" ", get_irn_opident(n));
312     xfprintf (F, DEFAULT_NODE_ATTR);
313     break;
314   case iro_Sel:
315     assert(get_kind(get_Sel_entity(n)) == k_entity);
316     xfprintf (F, "\"%I ", get_irn_opident(n));
317     xfprintf (F, "%s", id_to_str(get_entity_ident(get_Sel_entity(n))));
318     xfprintf (F, DEFAULT_NODE_ATTR);
319     break;
320   case iro_SymConst:
321     assert(get_kind(get_SymConst_type(n)) == k_type);
322     assert(get_type_nameid(get_SymConst_type(n)));
323     xfprintf (F, "\"%s ", get_type_name(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:
501     {
502       /* why can't I cast here??? @@@ */
503       type *type = tore;
504       xfprintf (F, "\"%I %I", get_type_tpop_nameid(type), get_type_nameid(type));
505
506       switch (get_type_tpop_code(type)) {
507       case tpo_class:
508         {
509           xfprintf (F, "\" " TYPE_CLASS_NODE_ATTR "}\n");
510           for (i=0; i < get_class_n_supertype(type); i++)
511             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
512                       TYPE_SUPER_EDGE_ATTR "}\n",
513                       type, get_class_supertype(type, i));
514         } break;
515       case tpo_struct:
516         {
517           xfprintf (F, "\"}\n");
518         } break;
519       case tpo_method:
520         {
521           xfprintf (F, "\" " TYPE_METH_NODE_ATTR "}\n");
522           for (i = 0; i < get_method_n_params(type); i++)
523             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
524                       METH_PAR_EDGE_ATTR "}\n",
525                       type, get_method_param_type(type, i), i);
526           for (i = 0; i < get_method_n_res(type); i++)
527             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
528                       METH_RES_EDGE_ATTR "}\n",
529                       type, get_method_res_type(type, i), i);
530         } break;
531       case tpo_union:
532         {
533           xfprintf (F, "\"}\n");
534           for (i = 0; i < get_union_n_members(type); i++)
535             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
536                       "label: \"\"f" UNION_EDGE_ATTR "}\n",
537                       type, get_union_member(type, i));
538         } break;
539       case tpo_array:
540         {
541           xfprintf (F, "\"}\n");
542           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
543                     ARR_ELT_TYPE_EDGE_ATTR "}\n", type, get_array_element_type(type), i);
544         } break;
545       case tpo_enumeration:
546         {
547           xfprintf (F, "\"}\n");
548         } break;
549       case tpo_pointer:
550         {
551           xfprintf (F, "\"}\n");
552           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
553                     PTR_PTS_TO_EDGE_ATTR "}\n", type,
554                     get_pointer_points_to_type(type), i);
555         } break;
556       case tpo_primitive:
557         {
558           xfprintf (F, "mode %I\"}\n", get_mode_ident(get_type_mode(type)));
559         } break;
560       default: break;
561       } /* switch type */
562
563     } break; /* case k_type */
564   default:
565     {
566       xfprintf (F, "\" faulty type \"}\n");
567       printf(" *** irdump,  %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
568     } break;
569   } /* switch kind_or_entity */
570 }
571
572 /************************************************************************/
573 /* open and close vcg file                                              */
574 /************************************************************************/
575
576 void vcg_open (ir_graph *irg, char *suffix) {
577   char *fname;  /* filename to put the vcg information in */
578   const char *cp;
579   ident *id;
580   int len;
581   char label[4];
582
583   /** open file for vcg graph */
584   id    = get_entity_ld_name (get_irg_ent(irg));
585   len   = id_to_strlen (id);
586   cp    = id_to_str (id);
587
588   fname = malloc (len + 5 + strlen(suffix));
589   strncpy (fname, cp, len);      /* copy the filename */
590   fname[len] = '\0';
591   strcat (fname, suffix);  /* append file suffix */
592
593   fname = malloc (len + 5 + strlen(suffix));
594   strncpy (fname, cp, len); /* copy the filename */
595   fname[len] = '\0';        /* ensure string termination */
596   /*strcpy (fname, cp);      * copy the filename *
597     this produces wrong, too long strings in conjuction with the
598     jocca frontend.  The \0 seems to be missing. */
599   strcat (fname, suffix);   /* append file suffix */
600   strcat (fname, ".vcg");   /* append the .vcg suffix */
601   F = fopen (fname, "w");   /* open file for writing */
602   if (!F) {
603     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
604   }
605
606   if (edge_label) {
607     strcpy(label, "yes");
608   } else {
609     strcpy (label, "no");
610   }
611
612   /* print header */
613   xfprintf (F,
614             "graph: { title: \"ir graph of %s\"\n"
615             "display_edge_labels: %s\n"
616             "layoutalgorithm: mindepth\n"
617             "manhattan_edges: yes\n"
618             "port_sharing: no\n"
619             "orientation: bottom_to_top\n"
620             "classname 1: \"Data\"\n"
621             "classname 2: \"Block\"\n", cp, label);
622
623   xfprintf (F, "\n");           /* a separator */
624 }
625
626 void vcg_open_name (const char *name) {
627   char *fname;  /* filename to put the vcg information in */
628   int len;
629   char label[4];
630
631   /** open file for vcg graph */
632   len   = strlen(name);
633   fname = malloc (len + 5);
634   strcpy (fname, name);    /* copy the filename */
635   strcat (fname, ".vcg");  /* append the .vcg suffix */
636   F = fopen (fname, "w");  /* open file for writing */
637   if (!F) {
638     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
639   }
640
641   if (edge_label) {
642     strcpy(label, "yes");
643   } else {
644     strcpy (label, "no");
645   }
646
647   /* print header */
648   xfprintf (F,
649             "graph: { title: \"ir graph of %s\"\n"
650             "display_edge_labels: %s\n"
651             "layoutalgorithm: mindepth\n"
652             "manhattan_edges: yes\n"
653             "port_sharing: no\n"
654             "orientation: bottom_to_top\n"
655             "classname 1: \"Data\"\n"
656             "classname 2: \"Block\"\n", name, label);
657
658   xfprintf (F, "\n");           /* a separator */
659 }
660
661 void
662 vcg_close () {
663   xfprintf (F, "}\n");  /* print footer */
664   fclose (F);           /* close vcg file */
665 }
666
667 /************************************************************************/
668 /* routines to dump a graph, blocks as conventional nodes.              */
669 /************************************************************************/
670
671 void
672 dump_whole_node (ir_node *n, void* env) {
673   dump_node(n);
674   dump_ir_block_edge(n);
675   dump_ir_data_edges(n);
676 }
677
678 void
679 dump_ir_graph (ir_graph *irg)
680 {
681   ir_graph *rem;
682   rem = current_ir_graph;
683   current_ir_graph = irg;
684
685   vcg_open (irg, "");
686
687   /* walk over the graph */
688   irg_walk(irg->end, dump_whole_node, NULL, NULL);
689
690   vcg_close();
691
692   current_ir_graph = rem;
693 }
694
695 /***********************************************************************/
696 /* the following routines dump the nodes as attached to the blocks.    */
697 /***********************************************************************/
698
699 void
700 dump_ir_blocks_nodes (ir_node *n, void *env) {
701   ir_node *block = (ir_node *)env;
702
703   if (is_no_Block(n) && get_nodes_Block(n) == block) {
704     dump_node(n);
705     dump_ir_data_edges(n);
706   }
707 }
708
709 void
710 dump_ir_block (ir_node *block, void *env) {
711   ir_graph *irg = (ir_graph *)env;
712
713   if (get_irn_opcode(block) == iro_Block) {
714
715     /* This is a block. So dump the vcg information to make a block. */
716     xfprintf(F, "graph: { title: \""); PRINT_NODEID(block); fprintf(F, "\"  label: \"");
717 #ifdef DEBUG_libfirm
718     xfprintf (F, "%ld", get_irn_node_nr(block));
719 #else
720     xfprintf (F, "%I", block->op->name);
721 #endif
722     xfprintf(F, "\" status:clustered color:lightyellow \n");
723     /* dump the blocks edges */
724     dump_ir_data_edges(block);
725
726     /* dump the nodes that go into the block */
727     irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
728
729     /* Close the vcg information for the block */
730     xfprintf(F, "}\n\n");
731   }
732 }
733
734 void
735 dump_ir_block_graph (ir_graph *irg)
736 {
737   ir_graph *rem;
738   rem = current_ir_graph;
739   current_ir_graph = irg;
740
741   vcg_open (irg, "");
742
743   /* walk over the blocks in the graph */
744   irg_block_walk(irg->end, dump_ir_block, NULL, irg);
745
746   vcg_close();
747   current_ir_graph = rem;
748 }
749
750
751 /***********************************************************************/
752 /* the following routines dump a control flow graph                    */
753 /***********************************************************************/
754
755
756 void
757 dump_block_to_cfg (ir_node *block, void *env) {
758   int i;
759   ir_node *pred;
760
761   if (get_irn_opcode(block) == iro_Block) {
762     /* This is a block. Dump a node for the block. */
763     xfprintf (F, "node: {title: \"%p\" label: \"%I\"}", block,
764               block->op->name);
765     /* Dump the edges */
766     for ( i = 0; i < get_Block_n_cfgpreds(block); i++) {
767       pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
768       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" }\n",
769                 block, pred);
770     }
771   }
772 }
773
774 void
775 dump_cfg (ir_graph *irg)
776 {
777   vcg_open (irg, "-cfg");
778
779   /* walk over the blocks in the graph */
780   irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
781
782   vcg_close();
783 }
784
785
786 /***********************************************************************/
787 /* the following routine dumps all type information reachable from an  */
788 /* irg                                                                 */
789 /***********************************************************************/
790
791
792 void
793 dump_type_graph (ir_graph *irg)
794 {
795   ir_graph *rem;
796   rem = current_ir_graph;
797   current_ir_graph = irg;
798
799   vcg_open (irg, "-type");
800
801   /* walk over the blocks in the graph */
802   type_walk_irg(irg, dump_type_info, NULL, NULL);
803
804   vcg_close();
805   current_ir_graph = rem;
806 }
807
808 /***********************************************************************/
809 /* the following routine dumps all type information                    */
810 /***********************************************************************/
811
812
813 void
814 dump_all_types (void)
815 {
816   vcg_open_name ("All_types");
817   type_walk(dump_type_info, NULL, NULL);
818   vcg_close();
819 }
820
821 /***********************************************************************/
822 /* dumps a graph with type information                                 */
823 /***********************************************************************/
824
825
826 void
827 dump_ir_graph_w_types (ir_graph *irg)
828 {
829   ir_graph *rem;
830   rem = current_ir_graph;
831   current_ir_graph = irg;
832
833   vcg_open (irg, "-all");
834
835   /* dump common ir graph */
836   /*  irg_block_walk(irg->end, dump_ir_block, NULL, irg); */
837   irg_walk(irg->end, dump_whole_node, NULL, NULL);
838   /* dump type info */
839   type_walk_irg(irg, dump_type_info, NULL, NULL);
840   /* dump edges from graph to type info */
841   irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
842
843   vcg_close();
844   current_ir_graph = rem;
845 }
846
847 /***********************************************************************/
848 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
849 /*  dump_ir_graph                                                      */
850 /*  dump_ir_block_graph                                                */
851 /*  dump_cfg                                                           */
852 /*  dump_type_graph                                                    */
853 /*  dump_ir_graph_w_types                                              */
854 /***********************************************************************/
855 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
856   int i;
857   for (i=0; i < get_irp_n_irgs(); i++) {
858     dump_graph(get_irp_irg(i));
859   }
860 }
861
862
863 /* To turn off display of edge labels.  Edge labels offen cause xvcg to
864    abort with a segmentation fault. */
865 void turn_of_edge_labels() {
866   edge_label = 0;
867 }