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