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