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