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