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