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