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