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