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