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