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