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