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