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