4173b6e692bbdf692ed5b2630c9e2c3d790b3f22
[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_t.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, "SymC %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, "SymC %I ", 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       /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
648       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
649                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
650       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
651                 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
652       for(i = 0; i < get_entity_n_overwrites(ent); i++)
653         xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
654                   ENT_OVERWRITES_EDGE_ATTR "}\n", ent, get_entity_overwrites(ent, i));
655       /* attached subgraphs */
656       if (const_entities && (get_entity_variability(ent) != uninitialized)) {
657         if (is_atomic_entity(ent)) {
658           value = get_atomic_ent_value(ent);
659           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
660           PRINT_NODEID(value);
661           fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
662           dump_const_expression(value);
663         }
664         if (is_compound_entity(ent)) {
665           for (i = 0; i < get_compound_ent_n_values(ent); i++) {
666             value = get_compound_ent_value(ent, i);
667             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
668             PRINT_NODEID(value);
669             fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
670             dump_const_expression(value);
671             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
672                       ENT_CORR_EDGE_ATTR  "}\n", ent,
673                       get_compound_ent_value_member(ent, i), i);
674           }
675         }
676       }
677     } break;
678   case k_type:
679     {
680       type *tp = (type *)tore;
681       print_type_node(tp);
682       /* and now the edges */
683       switch (get_type_tpop_code(tp)) {
684       case tpo_class:
685         {
686           for (i=0; i < get_class_n_supertype(tp); i++)
687             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
688                       TYPE_SUPER_EDGE_ATTR "}\n",
689                       tp, get_class_supertype(tp, i));
690           for (i=0; i < get_class_n_member(tp); i++)
691             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
692                       TYPE_MEMBER_EDGE_ATTR "}\n",
693                       tp, get_class_member(tp, i));
694         } break;
695       case tpo_struct:
696         {
697           for (i=0; i < get_struct_n_member(tp); i++)
698             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
699                       TYPE_MEMBER_EDGE_ATTR "}\n",
700                       tp, get_struct_member(tp, i));
701         } break;
702       case tpo_method:
703         {
704           for (i = 0; i < get_method_n_params(tp); i++)
705             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
706                       METH_PAR_EDGE_ATTR "}\n",
707                       tp, get_method_param_type(tp, i), i);
708           for (i = 0; i < get_method_n_res(tp); i++)
709             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
710                       METH_RES_EDGE_ATTR "}\n",
711                       tp, get_method_res_type(tp, i), i);
712         } break;
713       case tpo_union:
714         {
715           for (i = 0; i < get_union_n_members(tp); i++)
716             xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
717                       "label: \"\"f" UNION_EDGE_ATTR "}\n",
718                       tp, get_union_member(tp, i));
719         } break;
720       case tpo_array:
721         {
722           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
723                     ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
724           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
725                     ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
726         } break;
727       case tpo_enumeration:
728         {
729         } break;
730       case tpo_pointer:
731         {
732           xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
733                     PTR_PTS_TO_EDGE_ATTR "}\n", tp,
734                     get_pointer_points_to_type(tp), i);
735         } break;
736       case tpo_primitive:
737         {
738         } break;
739       default: break;
740       } /* switch type */
741     }
742     break; /* case k_type */
743   default:
744     {
745       printf(" *** irdump,  %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
746     } break;
747   } /* switch kind_or_entity */
748 }
749
750 /************************************************************************/
751 /* open and close vcg file                                              */
752 /************************************************************************/
753
754 void vcg_open (ir_graph *irg, char *suffix) {
755   char *fname;  /* filename to put the vcg information in */
756   const char *cp;
757   ident *id;
758   int len;
759   char label[4];
760   entity *ent;
761
762   /** open file for vcg graph */
763   ent = get_irg_ent(irg);
764   id    = ent->ld_name ? ent->ld_name : ent->name;
765     /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
766   len   = id_to_strlen (id);
767   cp    = id_to_str (id);
768   fname = malloc (len + 5 + strlen(suffix));
769   strncpy (fname, cp, len);      /* copy the filename */
770   fname[len] = '\0';
771   strcat (fname, suffix);  /* append file suffix */
772
773   fname = malloc (len + 5 + strlen(suffix));
774   strncpy (fname, cp, len); /* copy the filename */
775   fname[len] = '\0';        /* ensure string termination */
776   /*strcpy (fname, cp);      * copy the filename *
777     this produces wrong, too long strings in conjuction with the
778     jocca frontend.  The \0 seems to be missing. */
779   strcat (fname, suffix);   /* append file suffix */
780   strcat (fname, ".vcg");   /* append the .vcg suffix */
781   F = fopen (fname, "w");   /* open file for writing */
782   if (!F) {
783     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
784   }
785
786   if (edge_label) {
787     strcpy(label, "yes");
788   } else {
789     strcpy (label, "no");
790   }
791
792   /* print header */
793   xfprintf (F,
794             "graph: { title: \"ir graph of %s\"\n"
795             "display_edge_labels: %s\n"
796             "layoutalgorithm: mindepth\n"
797             "manhattan_edges: yes\n"
798             "port_sharing: no\n"
799             "orientation: bottom_to_top\n"
800             "classname 1: \"Data\"\n"
801             "classname 2: \"Block\"\n"
802             "classname 3: \"Entity type\""
803             "classname 4: \"Entity owner\""
804             "classname 5: \"Method Param\""
805             "classname 6: \"Method Res\""
806             "classname 7: \"Super\""
807             "classname 8: \"Union\""
808             "classname 9: \"Points-to\""
809             "classname 10: \"Array Element Type\""
810             "classname 11: \"Overwrites\""
811             "classname 12: \"Member\""
812             , cp, label);
813
814   xfprintf (F, "\n");           /* a separator */
815 }
816
817 void vcg_open_name (const char *name) {
818   char *fname;  /* filename to put the vcg information in */
819   int len;
820   char label[4];
821
822   /** open file for vcg graph */
823   len   = strlen(name);
824   fname = malloc (len + 5);
825   strcpy (fname, name);    /* copy the filename */
826   strcat (fname, ".vcg");  /* append the .vcg suffix */
827   F = fopen (fname, "w");  /* open file for writing */
828   if (!F) {
829     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
830   }
831
832   if (edge_label) {
833     strcpy(label, "yes");
834   } else {
835     strcpy (label, "no");
836   }
837
838   /* print header */
839   xfprintf (F,
840             "graph: { title: \"ir graph of %s\"\n"
841             "display_edge_labels: %s\n"
842             "layoutalgorithm: mindepth\n"
843             "manhattan_edges: yes\n"
844             "port_sharing: no\n"
845             "orientation: bottom_to_top\n"
846             "classname 1: \"Data\"\n"
847             "classname 2: \"Block\"\n"
848             "classname 3: \"Entity type\"\n"
849             "classname 4: \"Entity owner\"\n"
850             "classname 5: \"Method Param\"\n"
851             "classname 6: \"Method Res\"\n"
852             "classname 7: \"Super\"\n"
853             "classname 8: \"Union\"\n"
854             "classname 9: \"Points-to\"\n"
855             "classname 10: \"Array Element Type\"\n"
856             "classname 11: \"Overwrites\"\n"
857             "classname 12: \"Member\"\n"
858             , name, label);
859
860   xfprintf (F, "\n");           /* a separator */
861 }
862
863 void
864 vcg_close () {
865   xfprintf (F, "}\n");  /* print footer */
866   fclose (F);           /* close vcg file */
867 }
868
869 /************************************************************************/
870 /* routines to dump a graph, blocks as conventional nodes.              */
871 /************************************************************************/
872
873 void
874 dump_whole_node (ir_node *n, void* env) {
875   dump_node(n);
876   if (!node_floats(n)) dump_ir_block_edge(n);
877   dump_ir_data_edges(n);
878 }
879
880 void
881 dump_ir_graph (ir_graph *irg)
882 {
883   ir_graph *rem;
884   rem = current_ir_graph;
885   current_ir_graph = irg;
886
887   vcg_open (irg, "");
888
889   /* walk over the graph */
890   irg_walk(irg->end, dump_whole_node, NULL, NULL);
891
892   /* dump the out edges in a separate walk */
893   if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
894     irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
895   }
896
897   vcg_close();
898
899   current_ir_graph = rem;
900 }
901
902 /***********************************************************************/
903 /* the following routines dump the nodes as attached to the blocks.    */
904 /***********************************************************************/
905
906 int node_floats(ir_node *n) {
907   return ((get_op_pinned(get_irn_op(n)) == floats) &&
908           (get_irg_pinned(current_ir_graph) == floats));
909 }
910
911 void
912 dump_ir_blocks_nodes (ir_node *n, void *env) {
913   ir_node *block = (ir_node *)env;
914
915   if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
916     dump_node(n);
917     dump_ir_data_edges(n);
918   }
919   if (get_irn_op(n) == op_Bad)
920     Bad_dumped = 1;
921 }
922
923 void
924 dump_ir_block (ir_node *block, void *env) {
925   ir_graph *irg = (ir_graph *)env;
926
927   if (get_irn_opcode(block) == iro_Block) {
928
929     /* This is a block. So dump the vcg information to make a block. */
930     xfprintf(F, "graph: { title: \""); PRINT_NODEID(block); fprintf(F, "\"  label: \"");
931 #ifdef DEBUG_libfirm
932     xfprintf (F, "%ld", get_irn_node_nr(block));
933 #else
934     xfprintf (F, "%I", block->op->name);
935 #endif
936     xfprintf(F, "\" status:clustered color:%s \n",
937                          get_Block_matured (block) ? "yellow" : "red");
938     /* dump the blocks edges */
939     dump_ir_data_edges(block);
940
941     /* dump the nodes that go into the block */
942     irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
943
944     /* Close the vcg information for the block */
945     xfprintf(F, "}\n\n");
946   }
947 }
948
949
950 void
951 dump_blockless_nodes (ir_node *n, void *env) {
952   if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
953     dump_node(n);
954     dump_ir_data_edges(n);
955     dump_ir_block_edge(n);
956     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
957     return;
958   }
959   if (node_floats(n)) {
960     dump_node(n);
961     dump_ir_data_edges(n);
962     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
963   }
964 }
965
966 void dump_ir_block_graph_2  (ir_graph *irg)
967 {
968   Bad_dumped = 0;
969   /* walk over the blocks in the graph */
970   irg_block_walk(irg->end, dump_ir_block, NULL, irg);
971
972   /* dump all nodes that are not in a Block */
973   irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
974
975   /* dump the Bad node */
976   if (!Bad_dumped)
977     dump_node(get_irg_bad(irg));
978 }
979
980 void
981 dump_ir_block_graph (ir_graph *irg)
982 {
983   ir_graph *rem;
984   rem = current_ir_graph;
985   current_ir_graph = irg;
986
987   vcg_open (irg, "");
988
989   dump_ir_block_graph_2 (irg);
990
991   vcg_close();
992   current_ir_graph = rem;
993 }
994
995
996 /***********************************************************************/
997 /* the following routines dump a control flow graph                    */
998 /***********************************************************************/
999
1000
1001 void
1002 dump_block_to_cfg (ir_node *block, void *env) {
1003   int i;
1004   ir_node *pred;
1005
1006   if (get_irn_opcode(block) == iro_Block) {
1007     /* This is a block. Dump a node for the block. */
1008     xfprintf (F, "node: {title: \"%p\" label: \"%I\"}", block,
1009               block->op->name);
1010     /* Dump the edges */
1011     for ( i = 0; i < get_Block_n_cfgpreds(block); i++) {
1012       pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1013       xfprintf (F, "edge: { sourcename: \"");
1014       PRINT_NODEID(block);
1015       fprintf (F, "\" targetname: \"");
1016       PRINT_NODEID(pred);
1017       fprintf (F, "\" }\n");
1018     }
1019   }
1020 }
1021
1022 void
1023 dump_cfg (ir_graph *irg)
1024 {
1025   vcg_open (irg, "-cfg");
1026
1027   /* walk over the blocks in the graph */
1028   irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1029
1030   vcg_close();
1031 }
1032
1033
1034 /***********************************************************************/
1035 /* the following routine dumps all type information reachable from an  */
1036 /* irg                                                                 */
1037 /***********************************************************************/
1038
1039
1040 void
1041 dump_type_graph (ir_graph *irg)
1042 {
1043   ir_graph *rem;
1044   rem = current_ir_graph;
1045   current_ir_graph = irg;
1046
1047   vcg_open (irg, "-type");
1048
1049   /* walk over the blocks in the graph */
1050   type_walk_irg(irg, dump_type_info, NULL, NULL);
1051   /* The walker for the const code can be called several times for the
1052      same (sub) experssion.  So that no nodes are dumped several times
1053      we decrease the visited flag of the corresponding graph after each
1054      walk.  So now increase it finally. */
1055   inc_irg_visited(get_const_code_irg());
1056
1057   vcg_close();
1058   current_ir_graph = rem;
1059 }
1060
1061 /***********************************************************************/
1062 /* the following routine dumps all type information                    */
1063 /***********************************************************************/
1064
1065
1066 void
1067 dump_all_types (void)
1068 {
1069   vcg_open_name ("All_types");
1070   type_walk(dump_type_info, NULL, NULL);
1071   inc_irg_visited(get_const_code_irg());
1072   vcg_close();
1073 }
1074
1075 /***********************************************************************/
1076 /* dumps a graph with type information                                 */
1077 /***********************************************************************/
1078
1079
1080 void
1081 dump_ir_graph_w_types (ir_graph *irg)
1082 {
1083   ir_graph *rem;
1084   rem = current_ir_graph;
1085   current_ir_graph = irg;
1086
1087   vcg_open (irg, "-all");
1088
1089   /* dump common ir graph */
1090   irg_walk(irg->end, dump_whole_node, NULL, NULL);
1091   /* dump type info */
1092   type_walk_irg(irg, dump_type_info, NULL, NULL);
1093   inc_irg_visited(get_const_code_irg());
1094   /* dump edges from graph to type info */
1095   irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1096
1097   vcg_close();
1098   current_ir_graph = rem;
1099 }
1100
1101 void
1102 dump_ir_block_graph_w_types (ir_graph *irg)
1103 {
1104   ir_graph *rem;
1105   rem = current_ir_graph;
1106   current_ir_graph = irg;
1107
1108   vcg_open (irg, "-all");
1109
1110   /* dump common blocked ir graph */
1111   dump_ir_block_graph_2(irg);
1112   /* dump type info */
1113   type_walk_irg(irg, dump_type_info, NULL, NULL);
1114   inc_irg_visited(get_const_code_irg());
1115   /* dump edges from graph to type info */
1116   irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1117
1118   vcg_close();
1119   current_ir_graph = rem;
1120 }
1121
1122 /***********************************************************************/
1123 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
1124 /*  dump_ir_graph                                                      */
1125 /*  dump_ir_block_graph                                                */
1126 /*  dump_cfg                                                           */
1127 /*  dump_type_graph                                                    */
1128 /*  dump_ir_graph_w_types                                              */
1129 /***********************************************************************/
1130 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1131   int i;
1132   for (i=0; i < get_irp_n_irgs(); i++) {
1133     dump_graph(get_irp_irg(i));
1134   }
1135 }
1136
1137
1138 /* To turn off display of edge labels.  Edge labels offen cause xvcg to
1139    abort with a segmentation fault. */
1140 void turn_off_edge_labels() {
1141   edge_label = 0;
1142 }
1143
1144 void turn_off_constant_entity_values() {
1145   const_entities = 0;
1146 }
1147
1148 void dump_keepalive_edges() {
1149   dump_keepalive = 1;
1150 }
1151
1152 void dump_out_edges() {
1153   dump_out_edge_flag = 1;
1154 }