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