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