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