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