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