added info to type nodes
[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 void print_type_info(type *tp) {
535   if (get_type_state(tp) == layout_undefined) {
536     xfprintf(F, "state: layout_undefined\n");
537   } else {
538     xfprintf(F, "state: layout_fixed,\n");
539   }
540   if (get_type_mode(tp))
541     xfprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
542   xfprintf(F, "size: %dB,\n", get_type_size(tp));
543 }
544
545
546 void print_typespecific_info(type *tp) {
547   switch (get_type_tpop_code(tp)) {
548   case tpo_class:
549     {
550            xfprintf (F, " " TYPE_CLASS_NODE_ATTR);
551     } break;
552   case tpo_struct:
553     {
554       xfprintf (F, " " TYPE_METH_NODE_ATTR);
555     } break;
556   case tpo_method:
557     {
558     } break;
559   case tpo_union:
560     {
561     } break;
562   case tpo_array:
563     {
564     } break;
565   case tpo_enumeration:
566     {
567     } break;
568   case tpo_pointer:
569     {
570     } break;
571   case tpo_primitive:
572     {
573     } break;
574   default: break;
575   } /* switch type */
576 }
577
578 void print_type_node(type *tp) {
579   xfprintf (F, "node: {title: \"%p\" ", tp);
580   xfprintf (F, "label: \"%I %I\"", get_type_tpop_nameid(tp), get_type_ident(tp));
581   xfprintf (F, "info1: \"");
582   print_type_info(tp);
583   xfprintf (F, "\"");
584   print_typespecific_info(tp);
585   xfprintf (F, "}\n");
586 }
587
588 /* dumps a type or entity and it's edges. */
589 void
590 dump_type_info (type_or_ent *tore, void *env) {
591   int i = 0;  /* to shutup gcc */
592
593   /* dump this type or entity */
594
595   switch (get_kind(tore)) {
596   case k_entity:
597     {
598       entity *ent = (entity *)tore;
599       ir_node *value;
600       /* The node */
601       xfprintf (F, "node: {title: \"%p\" ", tore);
602       xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
603       xfprintf (F, "label: ");
604       xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR , get_entity_ident(ent));
605       if(dynamic_allocated == get_entity_allocation(ent))
606         xfprintf (F, " info1:\"dynamic allocated\n");
607       else
608         xfprintf (F, " info1:\"static allocated\n");
609       switch (get_entity_visibility(ent)) {
610         case local:              fprintf (F, "local\n");             break;
611         case external_visible:   fprintf (F, "external_visible\n");  break;
612         case external_allocated: fprintf (F, "external_allocate\nd");break;
613       }
614       switch (get_entity_variability(ent)) {
615         case uninitialized: fprintf (F, "uninitialized");break;
616         case initialized:   fprintf (F, "initialized");  break;
617         case part_constant: fprintf (F, "part_constant");break;
618         case constant:      fprintf (F, "constant");     break;
619       }
620       xfprintf(F, "\"}\n");
621       /* The Edges */
622       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
623                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));
624       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
625                 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
626       for(i = 0; i < get_entity_n_overwrites(ent); i++)
627         xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
628                   ENT_OVERWRITES_EDGE_ATTR "}\n", ent, get_entity_overwrites(ent, i));
629       /* attached subgraphs */
630       if (const_entities && (get_entity_variability(ent) != uninitialized)) {
631         if (is_atomic_entity(ent)) {
632           value = get_atomic_ent_value(ent);
633           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
634           PRINT_NODEID(value);
635           fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
636           dump_const_expression(value);
637         }
638         if (is_compound_entity(ent)) {
639           for (i = 0; i < get_compound_ent_n_values(ent); i++) {
640             value = get_compound_ent_value(ent, i);
641             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
642             PRINT_NODEID(value);
643             fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
644             dump_const_expression(value);
645             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
646                       ENT_CORR_EDGE_ATTR  "}\n", ent,
647                       get_compound_ent_value_member(ent, i), i);
648           }
649         }
650       }
651     } break;
652   case k_type:
653     {
654       type *tp = (type *)tore;
655       print_type_node(tp);
656       /* and now the edges */
657       switch (get_type_tpop_code(tp)) {
658       case tpo_class:
659         {
660           for (i=0; i < get_class_n_supertype(tp); i++)
661             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
662                       TYPE_SUPER_EDGE_ATTR "}\n",
663                       tp, get_class_supertype(tp, i));
664           for (i=0; i < get_class_n_member(tp); i++)
665             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
666                       TYPE_MEMBER_EDGE_ATTR "}\n",
667                       tp, get_class_member(tp, i));
668         } break;
669       case tpo_struct:
670         {
671           for (i=0; i < get_struct_n_member(tp); i++)
672             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
673                       TYPE_MEMBER_EDGE_ATTR "}\n",
674                       tp, get_struct_member(tp, i));
675         } break;
676       case tpo_method:
677         {
678           for (i = 0; i < get_method_n_params(tp); i++)
679             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
680                       METH_PAR_EDGE_ATTR "}\n",
681                       tp, get_method_param_type(tp, i), i);
682           for (i = 0; i < get_method_n_res(tp); i++)
683             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
684                       METH_RES_EDGE_ATTR "}\n",
685                       tp, get_method_res_type(tp, i), i);
686         } break;
687       case tpo_union:
688         {
689           for (i = 0; i < get_union_n_members(tp); i++)
690             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
691                       "label: \"\"f" UNION_EDGE_ATTR "}\n",
692                       tp, get_union_member(tp, i));
693         } break;
694       case tpo_array:
695         {
696           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
697                     ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
698           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
699                     ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
700         } break;
701       case tpo_enumeration:
702         {
703         } break;
704       case tpo_pointer:
705         {
706           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
707                     PTR_PTS_TO_EDGE_ATTR "}\n", tp,
708                     get_pointer_points_to_type(tp), i);
709         } break;
710       case tpo_primitive:
711         {
712         } break;
713       default: break;
714       } /* switch type */
715     }
716     break; /* case k_type */
717   default:
718     {
719       printf(" *** irdump,  %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
720     } break;
721   } /* switch kind_or_entity */
722 }
723
724 /************************************************************************/
725 /* open and close vcg file                                              */
726 /************************************************************************/
727
728 void vcg_open (ir_graph *irg, char *suffix) {
729   char *fname;  /* filename to put the vcg information in */
730   const char *cp;
731   ident *id;
732   int len;
733   char label[4];
734   entity *ent;
735
736   /** open file for vcg graph */
737   ent = get_irg_ent(irg);
738   id    = get_entity_ld_ident (ent);
739   len   = id_to_strlen (id);
740   cp    = id_to_str (id);
741   fname = malloc (len + 5 + strlen(suffix));
742   strncpy (fname, cp, len);      /* copy the filename */
743   fname[len] = '\0';
744   strcat (fname, suffix);  /* append file suffix */
745
746   fname = malloc (len + 5 + strlen(suffix));
747   strncpy (fname, cp, len); /* copy the filename */
748   fname[len] = '\0';        /* ensure string termination */
749   /*strcpy (fname, cp);      * copy the filename *
750     this produces wrong, too long strings in conjuction with the
751     jocca frontend.  The \0 seems to be missing. */
752   strcat (fname, suffix);   /* append file suffix */
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\""
776             "classname 4: \"Entity owner\""
777             "classname 5: \"Method Param\""
778             "classname 6: \"Method Res\""
779             "classname 7: \"Super\""
780             "classname 8: \"Union\""
781             "classname 9: \"Points-to\""
782             "classname 10: \"Array Element Type\""
783             "classname 11: \"Overwrites\""
784             "classname 12: \"Member\""
785             , cp, label);
786
787   xfprintf (F, "\n");           /* a separator */
788 }
789
790 void vcg_open_name (const char *name) {
791   char *fname;  /* filename to put the vcg information in */
792   int len;
793   char label[4];
794
795   /** open file for vcg graph */
796   len   = strlen(name);
797   fname = malloc (len + 5);
798   strcpy (fname, name);    /* copy the filename */
799   strcat (fname, ".vcg");  /* append the .vcg suffix */
800   F = fopen (fname, "w");  /* open file for writing */
801   if (!F) {
802     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
803   }
804
805   if (edge_label) {
806     strcpy(label, "yes");
807   } else {
808     strcpy (label, "no");
809   }
810
811   /* print header */
812   xfprintf (F,
813             "graph: { title: \"ir graph of %s\"\n"
814             "display_edge_labels: %s\n"
815             "layoutalgorithm: mindepth\n"
816             "manhattan_edges: yes\n"
817             "port_sharing: no\n"
818             "orientation: bottom_to_top\n"
819             "classname 1: \"Data\"\n"
820             "classname 2: \"Block\"\n"
821             "classname 3: \"Entity type\"\n"
822             "classname 4: \"Entity owner\"\n"
823             "classname 5: \"Method Param\"\n"
824             "classname 6: \"Method Res\"\n"
825             "classname 7: \"Super\"\n"
826             "classname 8: \"Union\"\n"
827             "classname 9: \"Points-to\"\n"
828             "classname 10: \"Array Element Type\"\n"
829             "classname 11: \"Overwrites\"\n"
830             "classname 12: \"Member\"\n"
831             , name, label);
832
833   xfprintf (F, "\n");           /* a separator */
834 }
835
836 void
837 vcg_close () {
838   xfprintf (F, "}\n");  /* print footer */
839   fclose (F);           /* close vcg file */
840 }
841
842 /************************************************************************/
843 /* routines to dump a graph, blocks as conventional nodes.              */
844 /************************************************************************/
845
846 void
847 dump_whole_node (ir_node *n, void* env) {
848   dump_node(n);
849   dump_ir_block_edge(n);
850   dump_ir_data_edges(n);
851 }
852
853 void
854 dump_ir_graph (ir_graph *irg)
855 {
856   ir_graph *rem;
857   rem = current_ir_graph;
858   current_ir_graph = irg;
859
860   vcg_open (irg, "");
861
862   /* walk over the graph */
863   irg_walk(irg->end, dump_whole_node, NULL, NULL);
864
865   vcg_close();
866
867   current_ir_graph = rem;
868 }
869
870 /***********************************************************************/
871 /* the following routines dump the nodes as attached to the blocks.    */
872 /***********************************************************************/
873
874 void
875 dump_ir_blocks_nodes (ir_node *n, void *env) {
876   ir_node *block = (ir_node *)env;
877
878   if (is_no_Block(n) && get_nodes_Block(n) == block) {
879     dump_node(n);
880     dump_ir_data_edges(n);
881   }
882   if (get_irn_op(n) == op_Bad)
883     Bad_dumped = 1;
884 }
885
886 void
887 dump_ir_block (ir_node *block, void *env) {
888   ir_graph *irg = (ir_graph *)env;
889
890   if (get_irn_opcode(block) == iro_Block) {
891
892     /* This is a block. So dump the vcg information to make a block. */
893     xfprintf(F, "graph: { title: \""); PRINT_NODEID(block); fprintf(F, "\"  label: \"");
894 #ifdef DEBUG_libfirm
895     xfprintf (F, "%ld", get_irn_node_nr(block));
896 #else
897     xfprintf (F, "%I", block->op->name);
898 #endif
899     xfprintf(F, "\" status:clustered color:lightyellow \n");
900     /* dump the blocks edges */
901     dump_ir_data_edges(block);
902
903     /* dump the nodes that go into the block */
904     irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
905
906     /* Close the vcg information for the block */
907     xfprintf(F, "}\n\n");
908   }
909 }
910
911
912 void
913 dump_blockless_nodes (ir_node *n, void *env) {
914   if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
915     dump_node(n);
916     dump_ir_data_edges(n);
917     dump_ir_block_edge(n);
918   }
919   if (get_irn_op(n) == op_Bad)
920     Bad_dumped = 1;
921 }
922
923 void dump_ir_block_graph_2  (ir_graph *irg)
924 {
925   Bad_dumped = 0;
926   /* walk over the blocks in the graph */
927   irg_block_walk(irg->end, dump_ir_block, NULL, irg);
928
929   /* dump all nodes that are not in a Block */
930   irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
931
932   /* dump the Bad node */
933   if (!Bad_dumped)
934     dump_node(get_irg_bad(irg));
935 }
936
937 void
938 dump_ir_block_graph (ir_graph *irg)
939 {
940   ir_graph *rem;
941   rem = current_ir_graph;
942   current_ir_graph = irg;
943
944   vcg_open (irg, "");
945
946   dump_ir_block_graph_2 (irg);
947
948   vcg_close();
949   current_ir_graph = rem;
950 }
951
952
953 /***********************************************************************/
954 /* the following routines dump a control flow graph                    */
955 /***********************************************************************/
956
957
958 void
959 dump_block_to_cfg (ir_node *block, void *env) {
960   int i;
961   ir_node *pred;
962
963   if (get_irn_opcode(block) == iro_Block) {
964     /* This is a block. Dump a node for the block. */
965     xfprintf (F, "node: {title: \"%p\" label: \"%I\"}", block,
966               block->op->name);
967     /* Dump the edges */
968     for ( i = 0; i < get_Block_n_cfgpreds(block); i++) {
969       pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
970       xfprintf (F, "edge: { sourcename: \"");
971       PRINT_NODEID(block);
972       fprintf (F, "\" targetname: \"");
973       PRINT_NODEID(pred);
974       fprintf (F, "\" }\n");
975     }
976   }
977 }
978
979 void
980 dump_cfg (ir_graph *irg)
981 {
982   vcg_open (irg, "-cfg");
983
984   /* walk over the blocks in the graph */
985   irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
986
987   vcg_close();
988 }
989
990
991 /***********************************************************************/
992 /* the following routine dumps all type information reachable from an  */
993 /* irg                                                                 */
994 /***********************************************************************/
995
996
997 void
998 dump_type_graph (ir_graph *irg)
999 {
1000   ir_graph *rem;
1001   rem = current_ir_graph;
1002   current_ir_graph = irg;
1003
1004   vcg_open (irg, "-type");
1005
1006   /* walk over the blocks in the graph */
1007   type_walk_irg(irg, dump_type_info, NULL, NULL);
1008   /* The walker for the const code can be called several times for the
1009      same (sub) experssion.  So that no nodes are dumped several times
1010      we decrease the visited flag of the corresponding graph after each
1011      walk.  So now increase it finally. */
1012   inc_irg_visited(get_const_code_irg());
1013
1014   vcg_close();
1015   current_ir_graph = rem;
1016 }
1017
1018 /***********************************************************************/
1019 /* the following routine dumps all type information                    */
1020 /***********************************************************************/
1021
1022
1023 void
1024 dump_all_types (void)
1025 {
1026   vcg_open_name ("All_types");
1027   type_walk(dump_type_info, NULL, NULL);
1028   inc_irg_visited(get_const_code_irg());
1029   vcg_close();
1030 }
1031
1032 /***********************************************************************/
1033 /* dumps a graph with type information                                 */
1034 /***********************************************************************/
1035
1036
1037 void
1038 dump_ir_graph_w_types (ir_graph *irg)
1039 {
1040   ir_graph *rem;
1041   rem = current_ir_graph;
1042   current_ir_graph = irg;
1043
1044   vcg_open (irg, "-all");
1045
1046   /* dump common ir graph */
1047   irg_walk(irg->end, dump_whole_node, NULL, NULL);
1048   /* dump type info */
1049   type_walk_irg(irg, dump_type_info, NULL, NULL);
1050   inc_irg_visited(get_const_code_irg());
1051   /* dump edges from graph to type info */
1052   irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1053
1054   vcg_close();
1055   current_ir_graph = rem;
1056 }
1057
1058 void
1059 dump_ir_block_graph_w_types (ir_graph *irg)
1060 {
1061   ir_graph *rem;
1062   rem = current_ir_graph;
1063   current_ir_graph = irg;
1064
1065   vcg_open (irg, "-all");
1066
1067   /* dump common blocked ir graph */
1068   dump_ir_block_graph_2(irg);
1069   /* dump type info */
1070   type_walk_irg(irg, dump_type_info, NULL, NULL);
1071   inc_irg_visited(get_const_code_irg());
1072   /* dump edges from graph to type info */
1073   irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1074
1075   vcg_close();
1076   current_ir_graph = rem;
1077 }
1078
1079 /***********************************************************************/
1080 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
1081 /*  dump_ir_graph                                                      */
1082 /*  dump_ir_block_graph                                                */
1083 /*  dump_cfg                                                           */
1084 /*  dump_type_graph                                                    */
1085 /*  dump_ir_graph_w_types                                              */
1086 /***********************************************************************/
1087 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1088   int i;
1089   for (i=0; i < get_irp_n_irgs(); i++) {
1090     dump_graph(get_irp_irg(i));
1091   }
1092 }
1093
1094
1095 /* To turn off display of edge labels.  Edge labels offen cause xvcg to
1096    abort with a segmentation fault. */
1097 void turn_of_edge_labels() {
1098   edge_label = 0;
1099 }
1100
1101 void dump_constant_entity_values() {
1102   const_entities = 0;
1103 }