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