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