Fixed Proj(Cond(mode_int))
[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 #include "callgraph.h"
39
40 #include "irvrfy.h"
41
42 #include "panic.h"
43 #include "array.h"
44 #include "pmap.h"
45 #include "eset.h"
46
47 #if DO_HEAPANALYSIS
48 void dump_chi_term(FILE *FL, ir_node *n);
49 void dump_state(FILE *FL, ir_node *n);
50 int  get_opt_dump_abstvals(void);
51 typedef unsigned long SeqNo;
52 SeqNo get_Block_seqno(ir_node *n);
53 #endif
54
55 /* Attributes of nodes */
56 #define PRINT_DEFAULT_NODE_ATTR
57 #define DEFAULT_NODE_ATTR " "
58 #define DEFAULT_TYPE_ATTRIBUTE " "
59 #define DEFAULT_ENUM_ITEM_ATTRIBUTE " "
60
61 /* Attributes of edges between Firm nodes */
62 #define INTRA_DATA_EDGE_ATTR "class:1  priority:50"
63 #define INTER_DATA_EDGE_ATTR "class:16 priority:10"
64 #define BLOCK_EDGE_ATTR      "class:2  priority:50 linestyle:dotted"
65 #define CF_EDGE_ATTR         "class:13 priority:60 color:red"
66 #define INTRA_MEM_EDGE_ATTR  "class:14 priority:50 color:blue"
67 #define INTER_MEM_EDGE_ATTR  "class:17 priority:10 color:blue"
68 #define DOMINATOR_EDGE_ATTR  "class:15 color:red"
69
70 #define BACK_EDGE_ATTR "linestyle:dashed "
71
72 /* Attributes of edges between Firm nodes and type/entity nodes */
73 #define NODE2TYPE_EDGE_ATTR "class:2 priority:2 linestyle:dotted"
74
75 /* Attributes of edges in type/entity graphs. */
76 #define TYPE_METH_NODE_ATTR      "color: lightyellow"
77 #define TYPE_CLASS_NODE_ATTR     "color: green"
78 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
79 #define ENTITY_NODE_ATTR         "color: yellow"
80 #define ENT_TYPE_EDGE_ATTR       "class: 3 label: \"type\" color: red"
81 #define ENT_OWN_EDGE_ATTR        "class: 4 label: \"owner\" color: black"
82 #define METH_PAR_EDGE_ATTR       "class: 5 label: \"param %d\" color: green"
83 #define METH_RES_EDGE_ATTR       "class: 6 label: \"res %d\" color: green"
84 #define TYPE_SUPER_EDGE_ATTR     "class: 7 label: \"supertype\" color: red"
85 #define UNION_EDGE_ATTR          "class: 8 label: \"component\" color: blue"
86 #define PTR_PTS_TO_EDGE_ATTR     "class: 9 label: \"points to\" color:green"
87 #define ARR_ELT_TYPE_EDGE_ATTR   "class: 10 label: \"arr elt tp\" color:green"
88 #define ARR_ENT_EDGE_ATTR        "class: 10 label: \"arr ent\" color: green"
89 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
90 #define ENT_VALUE_EDGE_ATTR      "label: \"value %d\""
91 #define ENT_CORR_EDGE_ATTR       "label: \"value %d corresponds to \" "
92 #define TYPE_MEMBER_EDGE_ATTR    "class: 12 label: \"member\" color:blue"
93 #define ENUM_ITEM_NODE_ATTR      "color: green"
94 #define CALLGRAPH_EDGE_ATTR      "calls"
95
96 #if DEBUG_libfirm && NODEID_AS_LABEL
97 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
98 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
99 #define PRINT_ENTID(X)  fprintf(F, "e%ld", get_entity_nr(X))
100 #define PRINT_IRGID(X)  fprintf(F, "g%ld", get_irg_graph_nr(X))
101 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
102 #define PRINT_LOOPID(X) fprintf(F, "l%d", get_loop_loop_nr(X))
103 #define PRINT_ITEMID(X,Y)  fprintf(F, "i%ldT%d", get_type_nr(X), (Y))
104
105 #else
106 #define PRINT_NODEID(X) fprintf(F, "n%p", (void *)(X))
107 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *)(X))
108 #define PRINT_ENTID(X)  fprintf(F, "e%p", (void *)(X))
109 #define PRINT_IRGID(X)  fprintf(F, "g%p",(void *)(X))
110 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%pn%p\"", (void*)(X), (void*)(Y))
111 #define PRINT_LOOPID(X) fprintf(F, "l%p", (void *)(X))
112 #define PRINT_ITEMID(X,Y)  fprintf(F, "i%pT%d", (void *) (X), (Y))
113 #endif
114
115 static const char *get_mode_name_ex(ir_mode *mode, int *bad)
116 {
117   if (is_mode(mode))
118     return get_mode_name(mode);
119   *bad |= 1;
120   return "<ERROR>";
121 }
122
123 static const char *get_type_name_ex(type *tp, int *bad)
124 {
125   if (is_type(tp))
126     return get_type_name(tp);
127   *bad |= 1;
128   return "<ERROR>";
129 }
130
131 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
132 {
133   va_list ap;
134
135   va_start(ap, fmt);
136   fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
137   fprintf(F, " targetname: "); PRINT_TYPEID(T);
138   vfprintf(F, fmt, ap);
139   fprintf(F,"}\n");
140   va_end(ap);
141 }
142
143 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
144 {
145   va_list ap;
146
147   va_start(ap, fmt);
148   fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
149   fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
150   vfprintf(F, fmt, ap);
151   fprintf(F, "}\n");
152   va_end(ap);
153 }
154
155 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
156 {
157   va_list ap;
158
159   va_start(ap, fmt);
160   if (backedge)
161     fprintf(F, "backedge: { sourcename: \"");
162    else
163     fprintf(F, "edge: { sourcename: \"");
164   PRINT_ENTID(E);
165   fprintf(F, "\" targetname: \""); PRINT_ENTID(T);  fprintf(F, "\"");
166   vfprintf(F, fmt, ap);
167   fprintf(F, "}\n");
168   va_end(ap);
169 }
170
171 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
172 {
173   va_list ap;
174
175   va_start(ap, fmt);
176   fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
177   fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
178   vfprintf(F, fmt, ap);
179   fprintf(F,"}\n");
180   va_end(ap);
181 }
182
183 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
184 {
185   va_list ap;
186
187   va_start(ap, fmt);
188   fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
189   fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
190   vfprintf(F, fmt, ap);
191   fprintf(F,"}\n");
192   va_end(ap);
193 }
194
195 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
196 {
197   va_list ap;
198
199   va_start(ap, fmt);
200   fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
201   fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
202   fprintf(F, "\"");
203   vfprintf(F, fmt, ap);
204   fprintf(F,"}\n");
205   va_end(ap);
206 }
207
208 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
209 {
210   va_list ap;
211
212   va_start(ap, fmt);
213   fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
214   fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
215   vfprintf(F, fmt, ap);
216   fprintf(F,"}\n");
217   va_end(ap);
218 }
219
220 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
221 {
222   va_list ap;
223
224   va_start(ap, fmt);
225   fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
226   fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
227   vfprintf(F, fmt, ap);
228   fprintf(F,"}\n");
229   va_end(ap);
230 }
231
232 /*******************************************************************/
233 /* global and ahead declarations                                   */
234 /*******************************************************************/
235
236 /* A suffix to manipulate the file name. */
237 char *dump_file_suffix = "";
238
239 char *dump_file_filter = "";
240
241 /* file to dump to */
242 static FILE *F;
243
244 static void dump_whole_node(ir_node *n, void* env);
245 static INLINE void dump_loop_nodes_into_graph(ir_graph *irg);
246
247 /*******************************************************************/
248 /* Helper functions.                                                */
249 /*******************************************************************/
250
251 /* Use private link attr to be able to call dumper anywhere without
252    destroying link fields. */
253
254 static pmap *irdump_link_map = NULL;
255
256 static void init_irdump(void) {
257   /* We need a new, empty map. */
258   if (irdump_link_map) pmap_destroy(irdump_link_map);
259   irdump_link_map = pmap_create();
260 }
261
262
263 void *ird_get_irn_link(ir_node *n) {
264   void *res = NULL;
265   if (!irdump_link_map) return NULL;
266
267   if (pmap_contains(irdump_link_map, (void *)n))
268     res = pmap_get(irdump_link_map, (void *)n);
269   return res;
270 }
271
272 void ird_set_irn_link(ir_node *n, void *x) {
273   if (!irdump_link_map) init_irdump();
274   pmap_insert(irdump_link_map, (void *)n, x);
275 }
276
277 void *ird_get_irg_link(ir_graph *irg) {
278   void *res = NULL;
279   if (!irdump_link_map) return NULL;
280
281   if (pmap_contains(irdump_link_map, (void *)irg))
282     res = pmap_get(irdump_link_map, (void *)irg);
283   return res;
284 }
285
286 void ird_set_irg_link(ir_graph *irg, void *x) {
287   if (!irdump_link_map) init_irdump();
288   pmap_insert(irdump_link_map, (void *)irg, x);
289 }
290
291 static void clear_link(ir_node * node, void * env) {
292   ird_set_irn_link(node, NULL);
293 }
294
295
296 static int node_floats(ir_node *n) {
297   return ((get_op_pinned(get_irn_op(n)) == floats) &&
298       (get_irg_pinned(current_ir_graph) == floats));
299 }
300
301 static const char *get_ent_dump_name(entity *ent) {
302   if (! ent)
303     return "<NULL entity>";
304   /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
305   if (ent->ld_name) return get_id_str(ent->ld_name);
306   return get_id_str(ent->name);
307 }
308
309 static const char *get_irg_dump_name(ir_graph *irg) {
310   /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
311   entity *ent = get_irg_ent(irg);
312   return get_ent_dump_name(ent);
313 }
314
315 static void collect_node(ir_node * node, void *env) {
316   if (is_Block(node)
317       || node_floats(node)
318       || get_irn_op(node) == op_Bad
319       || get_irn_op(node) == op_Unknown) {
320     ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
321     if (!arr) arr = NEW_ARR_F(ir_node *, 0);
322     ARR_APP1(ir_node *, arr, node);
323     ird_set_irg_link(get_irn_irg(node), arr);    /* arr is an l-value, APP_ARR might change it! */
324   } else {
325     ir_node * block = get_nodes_block(node);
326     ird_set_irn_link(node, ird_get_irn_link(block));
327     ird_set_irn_link(block, node);
328   }
329 }
330
331 /** Construct lists to walk ir block-wise.
332  *
333  * Collects all blocks, nodes not pinned,
334  * Bad and Unknown into a flexible array in link field of
335  * irg they belong to.  Sets the irg link field to NULL in all
336  * graphs not visited.
337  * Free the list with DEL_ARR_F.  */
338 static ir_node ** construct_block_lists(ir_graph *irg) {
339   int i, rem_view = interprocedural_view;
340   ir_graph *rem = current_ir_graph;
341   current_ir_graph = irg;
342
343   for (i = 0; i < get_irp_n_irgs(); i++)
344     ird_set_irg_link(get_irp_irg(i), NULL);
345
346   irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
347
348   /* Collect also EndReg and EndExcept. We do not want to change the walker. */
349   interprocedural_view = 0;
350   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
351   irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
352   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
353   irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
354   interprocedural_view = rem_view;
355
356   current_ir_graph = rem;
357   return ird_get_irg_link(irg);
358 }
359
360 /*******************************************************************/
361 /* flags to steer output                                           */
362 /*******************************************************************/
363
364 /* A compiler option to turn off edge labels */
365 int edge_label = 1;
366 /* A compiler option to turn off dumping values of constant entities */
367 int const_entities = 1;
368 /* A compiler option to dump the keep alive edges */
369 int dump_keepalive = 0;
370 /* Compiler options to dump analysis information in dump_ir_graph */
371 int dump_out_edge_flag = 0;
372 int dump_dominator_information_flag = 0;
373 int dump_loop_information_flag = 0;
374 int dump_backedge_information_flag = 1;
375 int dump_const_local = 0;
376 bool opt_dump_analysed_type_info = 1;
377 bool opt_dump_pointer_values_to_info = 0;  /* default off: for test compares!! */
378
379 char* overrule_nodecolor = NULL;
380
381 INLINE bool get_opt_dump_const_local(void) {
382   if (!dump_out_edge_flag && !dump_loop_information_flag)
383     return dump_const_local;
384   else
385     return false;
386 }
387
388 /* To turn off display of edge labels.  Edge labels offen cause xvcg to
389    abort with a segmentation fault. */
390 void turn_off_edge_labels(void) {
391   edge_label = 0;
392 }
393
394 void dump_consts_local(bool b) {
395   dump_const_local = b;
396 }
397
398 void turn_off_constant_entity_values(void) {
399   const_entities = 0;
400 }
401
402 void dump_keepalive_edges(bool b) {
403   dump_keepalive = b;
404 }
405
406 bool get_opt_dump_keepalive_edges(void) {
407   return dump_keepalive;
408 }
409
410 void dump_out_edges(void) {
411   dump_out_edge_flag = 1;
412 }
413
414 void dump_dominator_information(void) {
415   dump_dominator_information_flag = 1;
416 }
417
418 void dump_loop_information(void) {
419   dump_loop_information_flag = 1;
420 }
421
422 void dont_dump_loop_information(void) {
423   dump_loop_information_flag = 0;
424 }
425
426 void dump_backedge_information(bool b) {
427   dump_backedge_information_flag = b;
428 }
429
430 /* Dump the information of type field specified in ana/irtypeinfo.h.
431  * If the flag is set, the type name is output in [] in the node label,
432  * else it is output as info.
433  */
434 void dump_analysed_type_info(bool b) {
435   opt_dump_analysed_type_info = b;
436 }
437
438 void dump_pointer_values_to_info(bool b) {
439   opt_dump_pointer_values_to_info = b;
440 }
441
442 /*******************************************************************/
443 /* Routines to dump information about a single ir node.            */
444 /*******************************************************************/
445
446 INLINE int
447 dump_node_opcode(FILE *F, ir_node *n)
448 {
449   int bad = 0;
450
451   switch(get_irn_opcode(n)) {
452
453   case iro_Const: {
454     int res;
455     char buf[1024];
456     res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
457     assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
458     fprintf(F, buf);
459   } break;
460
461   case iro_SymConst: {
462     if (get_SymConst_kind(n) == symconst_addr_name) {
463       /* don't use get_SymConst_ptr_info as it mangles the name. */
464       fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
465     } else if (get_SymConst_kind(n) == symconst_addr_ent) {
466       assert(get_SymConst_entity(n));
467       assert(is_entity(get_SymConst_entity(n)));
468       fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
469     } else {
470       assert(get_kind(get_SymConst_type(n)) == k_type);
471       assert(get_type_ident(get_SymConst_type(n)));
472       fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
473       if (get_SymConst_kind(n) == symconst_type_tag)
474         fprintf (F, "tag");
475       else
476         fprintf (F, "size");
477     }
478   } break;
479
480   case iro_Filter: {
481     if (!interprocedural_view) fprintf(F, "Proj'");
482     else                       fprintf(F, "%s", get_irn_opname(n));
483   } break;
484
485   case iro_Proj: {
486     ir_node *cond = get_Proj_pred(n);
487
488     if (get_irn_opcode(cond) == iro_Cond
489         && get_Proj_proj(n) == get_Cond_defaultProj(cond)
490         && get_irn_mode(get_Cond_selector(cond)) != mode_b)
491       fprintf (F, "defProj");
492     else
493       fprintf (F, "%s", get_irn_opname(n));
494   } break;
495
496   case iro_Start: {
497     if (interprocedural_view) {
498       fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_ent(get_irn_irg(n))));
499       break;
500     }
501   } /* fall through */
502
503   default: {
504     fprintf (F, "%s", get_irn_opname(n));
505   }
506
507   }  /* end switch */
508   return bad;
509 }
510
511 static INLINE int
512 dump_node_mode (ir_node *n)
513 {
514   int bad = 0;
515
516   switch (get_irn_opcode(n)) {
517   case iro_Phi:
518   case iro_Const:
519   case iro_Id:
520   case iro_Proj:
521   case iro_Filter:
522   case iro_Conv:
523   case iro_Tuple:
524   case iro_Add:
525   case iro_Sub:
526   case iro_Mul:
527   case iro_And:
528   case iro_Or:
529   case iro_Eor:
530   case iro_Shl:
531   case iro_Shr:
532   case iro_Abs:
533   case iro_Cmp:
534   case iro_Confirm:
535     fprintf (F, "%s", get_mode_name_ex(get_irn_mode(n), &bad));
536     break;
537   default:
538     ;
539   }
540   return bad;
541 }
542
543 static int dump_node_typeinfo(ir_node *n) {
544   int bad = 0;
545
546   if (opt_dump_analysed_type_info) {
547     if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent  ||
548     get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent  ) {
549       type *tp = get_irn_type(n);
550       if (tp != none_type)
551     fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
552       else
553     fprintf(F, " []");
554     }
555   }
556   return bad;
557 }
558
559 static INLINE int
560 dump_node_nodeattr (ir_node *n)
561 {
562   int bad = 0;
563
564   switch (get_irn_opcode(n)) {
565   case iro_Start:
566     if (false && interprocedural_view) {
567       fprintf (F, "%s", get_ent_dump_name(get_irg_ent(current_ir_graph)));
568     }
569     break;
570   case iro_Proj:
571     if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
572       fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
573     } else {
574       fprintf (F, "%ld", get_Proj_proj(n));
575     }
576     break;
577   case iro_Filter:
578     fprintf (F, "%ld", get_Filter_proj(n));
579     break;
580   case iro_Sel: {
581     fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
582     } break;
583   case iro_Cast: {
584     fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
585     } break;
586   case iro_Confirm: {
587     fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
588     } break;
589
590   default:
591     ;
592   } /* end switch */
593
594   return bad;
595 }
596
597 static INLINE void dump_node_vcgattr(ir_node *n, int bad)
598 {
599   if (bad) {
600     fprintf(F, "color: red");
601     return;
602   }
603   switch (get_irn_opcode(n)) {
604   case iro_Start:
605   case iro_EndReg:
606     /* fall through */
607   case iro_EndExcept:
608     /* fall through */
609   case iro_End:
610     fprintf (F, "color: blue");
611     break;
612   case iro_Block:
613     fprintf (F, "color: lightyellow");
614     break;
615   case iro_Phi:
616     fprintf (F, "color: green");
617     break;
618   case iro_Const:
619   case iro_Proj:
620   case iro_Filter:
621   case iro_Tuple:
622     fprintf (F, "color: yellow");
623     break;
624   default:
625     PRINT_DEFAULT_NODE_ATTR;
626   }
627
628   if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
629 }
630
631 static INLINE int dump_node_info(ir_node *n)
632 {
633   int i, bad = 0;
634   char comma;
635   ir_graph *irg;
636
637   fprintf (F, " info1: \"");
638   if (opt_dump_pointer_values_to_info)
639     fprintf (F, "addr:    %p \n", (void *)n);
640   fprintf (F, "mode:    %s\n", get_mode_name(get_irn_mode(n)));
641   fprintf (F, "visited: %ld \n", get_irn_visited(n));
642   irg = get_irn_irg(n);
643   if (irg != get_const_code_irg())
644     fprintf (F, "irg:     %s\n", get_ent_dump_name(get_irg_entity(irg)));
645
646   fprintf(F, "arity: %d", get_irn_arity(n));
647   if ((get_irn_op(n) == op_Block) ||
648       (get_irn_op(n) == op_Phi) ||
649       ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
650     fprintf(F, " backedges:");
651     comma = ' ';
652     for (i = 0; i < get_irn_arity(n); i++)
653       if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
654   }
655   fprintf(F, "\n");
656
657   /* Loop node   Someone else please tell me what's wrong ...
658   if (get_irn_loop(n)) {
659     ir_loop *loop = get_irn_loop(n);
660     assert(loop);
661     fprintf(F, " in loop %d with depth %d\n",
662         get_loop_loop_nr(loop), get_loop_depth(loop));
663   }
664   */
665
666   /* Source types */
667   switch (get_irn_opcode(n)) {
668   case iro_Start: {
669     type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
670     fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
671     for (i = 0; i < get_method_n_params(tp); ++i)
672       fprintf(F, "  param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
673   } break;
674   case iro_Alloc: {
675     fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
676   } break;
677   case iro_Free: {
678     fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
679   } break;
680   case iro_Sel: {
681     entity *ent = get_Sel_entity(n);
682
683     if (ent) {
684       fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
685       fprintf(F, "  from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
686     }
687     else {
688       fprintf(F, "<NULL entity>\n");
689       bad = 1;
690     }
691   } break;
692   case iro_Call: {
693     type *tp = get_Call_type(n);
694     fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
695     for (i = 0; i < get_method_n_params(tp); ++i)
696       fprintf(F, "  param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
697     for (i = 0; i < get_method_n_ress(tp); ++i)
698       fprintf(F, "  resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
699     if (Call_has_callees(n)) {
700       fprintf(F, "possible callees: \n");
701       for (i = 0; i < get_Call_n_callees(n); i++) {
702     if (!get_Call_callee(n, i)) {
703       fprintf(F, "  %d external method\n", i);
704     } else {
705       fprintf(F, "  %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
706     }
707       }
708     }
709   } break;
710   case iro_CallBegin: {
711     ir_node *call = get_CallBegin_call(n);
712     if (Call_has_callees(call)) {
713       fprintf(F, "possible callees: \n");
714       for (i = 0; i < get_Call_n_callees(call); i++) {
715     if (!get_Call_callee(call, i)) {
716       fprintf(F, "  %d external method\n", i);
717     } else {
718       fprintf(F, "  %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
719     }
720       }
721     }
722   } break;
723   case iro_Return: {
724     if (!interprocedural_view) {
725       type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
726       fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
727       for (i = 0; i < get_method_n_ress(tp); ++i)
728     fprintf(F, "  res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
729     }
730     } break;
731   case iro_Const: {
732     type *tp = get_Const_type(n);
733     assert(tp != none_type);
734     fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
735   } break;
736   case iro_Filter: {
737     int i;
738     if (interprocedural_view) {
739       fprintf(F, "intra predecessor nodes:\n");
740       for (i = 0; i < get_irn_intra_arity(n); i++) {
741     ir_node *pred = get_irn_intra_n(n, i);
742     fprintf(F, "  %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
743       }
744     } else {
745       fprintf(F, "inter predecessor nodes:\n");
746       for (i = 0; i < get_irn_inter_arity(n); i++) {
747     ir_node *pred = get_irn_inter_n(n, i);
748     fprintf(F, "  %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
749         get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
750       }
751     }
752   } break;
753   default: ;
754   }
755
756   if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent  ||
757       get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent  )
758     if (get_irn_type(n) != none_type)
759       fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
760
761   fprintf (F, "\"");
762
763   return bad;
764 }
765
766
767 static INLINE
768 bool is_constlike_node(ir_node *n) {
769   ir_op *op = get_irn_op(n);
770   return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
771 }
772
773
774 /* outputs the predecessors of n, that are constants, local.  I.e.,
775    generates a copy of the constant predecessors for each node called with. */
776 static void dump_const_node_local(ir_node *n) {
777   int i;
778   if (!get_opt_dump_const_local()) return;
779
780   /* Use visited flag to avoid outputting nodes twice.
781      initialize it first. */
782   for (i = 0; i < get_irn_arity(n); i++) {
783     ir_node *con = get_irn_n(n, i);
784     if (is_constlike_node(con)) {
785       set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
786     }
787   }
788
789   for (i = 0; i < get_irn_arity(n); i++) {
790     ir_node *con = get_irn_n(n, i);
791     if (is_constlike_node(con) && irn_not_visited(con)) {
792       int bad = 0;
793
794       mark_irn_visited(con);
795       /* Generate a new name for the node by appending the names of
796      n and const. */
797       fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
798       fprintf(F, " label: \"");
799       bad |= dump_node_opcode(F, con);
800       bad |= dump_node_mode (con);
801       bad |= dump_node_typeinfo(con);
802       fprintf (F, " ");
803       bad |= dump_node_nodeattr(con);
804       fprintf(F, " %ld", get_irn_node_nr(con));
805       fprintf(F, "\" ");
806       bad |= dump_node_info(con);
807       dump_node_vcgattr(con, bad);
808       fprintf(F, "}\n");
809     }
810   }
811 }
812
813 static void print_node_error(const char *p)
814 {
815   if (! p)
816     return;
817
818   fprintf (F, " info2: \"%s\"", p);
819 }
820
821 static void dump_node(ir_node *n)
822 {
823   int bad = 0;
824   const char *p;
825
826   if (get_opt_dump_const_local() && is_constlike_node(n)) return;
827   /* dump this node */
828   fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
829
830   bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
831   bad |= dump_node_opcode(F, n);
832   bad |= dump_node_mode (n);
833   bad |= dump_node_typeinfo(n);
834   fprintf(F, " ");
835   bad |= dump_node_nodeattr(n);
836   fprintf(F, " %ld", get_irn_node_nr(n));
837   fprintf(F, "\" ");
838   bad |= dump_node_info(n);
839   print_node_error(p);
840   dump_node_vcgattr(n, bad);
841   fprintf(F, "}\n");
842   dump_const_node_local(n);
843 #if DO_HEAPANALYSIS
844   dump_chi_term(F, n);
845   dump_state(F, n);
846 #endif
847 }
848
849 /* dump the edge to the block this node belongs to */
850 static void
851 dump_ir_block_edge(ir_node *n)  {
852   if (get_opt_dump_const_local() && is_constlike_node(n)) return;
853   if (is_no_Block(n)) {
854     fprintf (F, "edge: { sourcename: \"");
855     PRINT_NODEID(n);
856     fprintf (F, "\" targetname: \"");
857     PRINT_NODEID(get_nodes_block(n));
858     fprintf (F, "\" "   BLOCK_EDGE_ATTR "}\n");
859   }
860 }
861
862 static void
863 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
864   if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
865     fprintf (F, INTRA_DATA_EDGE_ATTR);
866   else
867     fprintf (F, INTER_DATA_EDGE_ATTR);
868 }
869
870 static void
871 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
872   if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
873     fprintf (F, INTRA_MEM_EDGE_ATTR);
874   else
875     fprintf (F, INTER_MEM_EDGE_ATTR);
876 }
877
878 static void
879 print_edge_vcgattr(ir_node *from, int to) {
880   assert(from);
881
882   if (dump_backedge_information_flag && is_backedge(from, to))
883     fprintf (F, BACK_EDGE_ATTR);
884
885   switch (get_irn_opcode(from)) {
886   case iro_Block:
887     fprintf (F, CF_EDGE_ATTR);
888     break;
889   case iro_Start:   break;
890   case iro_End:
891     if (to >= 0) {
892       if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
893     fprintf (F, CF_EDGE_ATTR);
894       if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
895     fprintf (F, INTER_MEM_EDGE_ATTR);
896     }
897     break;
898   case iro_EndReg:
899   case iro_EndExcept:
900   case iro_Jmp:
901   case iro_Break:
902   case iro_Cond:
903     print_data_edge_vcgattr(F, from, to);
904     break;
905   case iro_Return:
906   case iro_Raise:
907     if (to == 0)
908       print_mem_edge_vcgattr(F, from, to);
909     else
910       print_data_edge_vcgattr(F, from, to);
911     break;
912   case iro_Const:
913   case iro_SymConst:
914     print_data_edge_vcgattr(F, from, to);
915     break;
916   case iro_Sel:
917   case iro_Call:
918     if (to == 0)
919       print_mem_edge_vcgattr(F, from, to);
920     else
921       print_data_edge_vcgattr(F, from, to);
922     break;
923   case iro_CallBegin:
924   case iro_Add:
925   case iro_Sub:
926   case iro_Minus:
927   case iro_Mul:
928     print_data_edge_vcgattr(F, from, to);
929     break;
930   case iro_Quot:
931   case iro_DivMod:
932   case iro_Div:
933   case iro_Mod:
934     if (to == 0)
935       print_mem_edge_vcgattr(F, from, to);
936     else
937       print_data_edge_vcgattr(F, from, to);
938     break;
939   case iro_Abs:
940   case iro_And:
941   case iro_Or:
942   case iro_Eor:
943   case iro_Shl:
944   case iro_Shr:
945   case iro_Shrs:
946   case iro_Rot:
947   case iro_Cmp:
948   case iro_Conv:
949       print_data_edge_vcgattr(F, from, to);
950     break;
951   case iro_Phi:
952     if (get_irn_modecode(from) == irm_M)
953       fprintf (F, INTER_MEM_EDGE_ATTR);
954     else
955       print_data_edge_vcgattr(F, from, to);
956     break;
957   case iro_Load:
958   case iro_Store:
959   case iro_Alloc:
960   case iro_Free:
961     if (to == 0)
962       print_mem_edge_vcgattr(F, from, to);
963     else
964       print_data_edge_vcgattr(F, from, to);
965     break;
966   case iro_Sync:
967     print_mem_edge_vcgattr(F, from, to);
968     break;
969   case iro_Tuple:  break;
970   case iro_Proj:
971   case iro_Filter:
972     switch (get_irn_modecode(from)) {
973     case irm_X:
974       fprintf (F, CF_EDGE_ATTR);
975       break;
976     case irm_M:
977       fprintf (F, INTER_MEM_EDGE_ATTR);
978       break;
979     default:
980       print_data_edge_vcgattr(F, from, to);
981       break;
982     }
983     break;
984   case iro_Bad:     break;
985   case iro_Unknown: break;
986   case iro_Id:
987     switch (get_irn_modecode(from)) {
988     case irm_M:
989       fprintf (F, INTRA_MEM_EDGE_ATTR);
990       break;
991     case irm_X:
992       fprintf (F, CF_EDGE_ATTR);
993       break;
994     default:
995       print_data_edge_vcgattr(F, from, to);
996       break;
997     } break;
998   default:
999     ;
1000   }
1001 }
1002
1003 /* dump edges to our inputs */
1004 static void
1005 dump_ir_data_edges(ir_node *n)  {
1006   int i, visited = get_irn_visited(n);
1007
1008   if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1009     return;
1010
1011   for (i = 0; i < get_irn_arity(n); i++) {
1012     ir_node * pred = get_irn_n(n, i);
1013     assert(pred);
1014
1015     if ((interprocedural_view && get_irn_visited(pred) < visited))
1016       continue; /* pred not dumped */
1017
1018     if (dump_backedge_information_flag && is_backedge(n, i))
1019       fprintf (F, "backedge: {sourcename: \"");
1020     else
1021       fprintf (F, "edge: {sourcename: \"");
1022     PRINT_NODEID(n);
1023     fprintf (F, "\" targetname: ");
1024     if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1025       PRINT_CONSTID(n, pred);
1026     } else {
1027       fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1028     }
1029     fprintf (F, " label: \"%d\" ", i);
1030     print_edge_vcgattr(n, i);
1031     fprintf (F, "}\n");
1032   }
1033 }
1034
1035 /** Dumps a node and its edges but not the block edge
1036  */
1037 static INLINE void
1038 dump_node_wo_blockedge (ir_node *n, void* env) {
1039   dump_node(n);
1040   dump_ir_data_edges(n);
1041 }
1042
1043 /** Dumps a node and its edges.
1044  */
1045 static void
1046 dump_whole_node (ir_node *n, void* env) {
1047   dump_node_wo_blockedge(n, env);
1048   if (!node_floats(n)) dump_ir_block_edge(n);
1049 }
1050
1051 static void
1052 dump_const_node(ir_node *n, void *env) {
1053   if (is_Block(n)) return;
1054   dump_node_wo_blockedge(n, env);
1055 }
1056
1057 /***********************************************************************/
1058 /* the following routines dump the nodes/irgs bracketed to graphs.     */
1059 /***********************************************************************/
1060
1061 /** Dumps a constant expression as entity initializer, array bound ...
1062  */
1063 static void dump_const_expression(ir_node *value) {
1064   ir_graph *rem = current_ir_graph;
1065   int rem_dump_const_local = dump_const_local;
1066   dump_const_local = 0;
1067   current_ir_graph = get_const_code_irg();
1068   irg_walk(value, dump_const_node, NULL, NULL);
1069   /* Decrease visited flag so that we walk with the same flag for the next
1070      expresssion.  This guarantees that we don't dump the same node twice,
1071      as for const expressions cse is performed to save memory. */
1072   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1073   current_ir_graph = rem;
1074   dump_const_local = rem_dump_const_local;
1075 }
1076
1077 /** Dump a block as graph containing its nodes.
1078  *
1079  *  Expects to find nodes belonging to the block as list in its
1080  *  link field.
1081  *  Dumps the edges of all nodes including itself. */
1082 static void
1083 dump_whole_block(ir_node *block) {
1084   ir_node *node;
1085   assert(is_Block(block));
1086
1087   fprintf(F, "graph: { title: \"");
1088   PRINT_NODEID(block);
1089   fprintf(F, "\"  label: \"");
1090   dump_node_opcode(F, block);
1091   fprintf (F, " %ld", get_irn_node_nr(block));
1092 #if DO_HEAPANALYSIS
1093   if (get_opt_dump_abstvals())
1094     fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1095 #endif
1096   fprintf(F, "\" status:clustered color:%s \n",
1097        get_Block_matured(block) ? "yellow" : "red");
1098
1099   /* dump the blocks edges */
1100   dump_ir_data_edges(block);
1101
1102   /* dump the nodes that go into the block */
1103   for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1104     dump_node(node);
1105     dump_ir_data_edges(node);
1106   }
1107
1108   /* Close the vcg information for the block */
1109   fprintf(F, "}\n");
1110   dump_const_node_local(block);
1111 #if DO_HEAPANALYSIS
1112   dump_chi_term(F, block);
1113 #endif
1114   fprintf(F, "\n");
1115 }
1116
1117 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1118  *  The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
1119 static void
1120 dump_block_graph(ir_graph *irg) {
1121   int i;
1122   ir_graph *rem = current_ir_graph;
1123   ir_node **arr = ird_get_irg_link(irg);
1124   current_ir_graph = irg;
1125
1126   for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1127     ir_node * node = arr[i];
1128     if (is_Block(node)) {
1129       /* Dumps the block and all the nodes in the block, which are to
1130      be found in Block->link. */
1131       dump_whole_block(node);
1132     } else {
1133       /* Nodes that are not in a Block. */
1134       dump_node(node);
1135       dump_ir_data_edges(node);
1136     }
1137   }
1138
1139   if (dump_loop_information_flag) dump_loop_nodes_into_graph(irg);
1140
1141   current_ir_graph = rem;
1142 }
1143
1144 /** Dumps an irg as a graph.
1145  *  If interprocedural view edges can point to nodes out of this graph.
1146  */
1147 static void dump_graph(ir_graph *irg) {
1148
1149   fprintf(F, "graph: { title: \"");
1150   PRINT_IRGID(irg);
1151   fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1152       get_ent_dump_name(get_irg_ent(irg)));
1153
1154   dump_block_graph (irg);
1155
1156   /* Close the vcg information for the irg */
1157   fprintf(F, "}\n\n");
1158 }
1159
1160 /*******************************************************************/
1161 /* Basic type and entity nodes and edges.                          */
1162 /*******************************************************************/
1163
1164 /* dumps the edges between nodes and their type or entity attributes. */
1165 static void dump_node2type_edges (ir_node *n, void *env)
1166 {
1167   assert(n);
1168
1169   switch (get_irn_opcode(n)) {
1170   case iro_Const :
1171     /* @@@ some consts have an entity */
1172     break;
1173   case iro_SymConst:
1174     if (   (get_SymConst_kind(n) ==symconst_type_tag)
1175        || (get_SymConst_kind(n) ==symconst_size))
1176       {
1177     print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1178       }
1179     break;
1180   case iro_Sel: {
1181       print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1182     } break;
1183   case iro_Call: {
1184       print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1185     } break;
1186   case iro_Alloc: {
1187       print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1188     } break;
1189   case iro_Free: {
1190       print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1191     } break;
1192   case iro_Cast: {
1193       print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1194     } break;
1195   default:
1196     break;
1197   }
1198 }
1199
1200
1201 static int print_type_info(type *tp) {
1202   int bad = 0;
1203
1204   if (get_type_state(tp) == layout_undefined) {
1205     fprintf(F, "state: layout_undefined\n");
1206   } else {
1207     fprintf(F, "state: layout_fixed,\n");
1208   }
1209   if (get_type_mode(tp))
1210     fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1211   fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1212
1213   return bad;
1214 }
1215
1216 static void print_typespecific_info(type *tp) {
1217   switch (get_type_tpop_code(tp)) {
1218   case tpo_class:
1219     {
1220       fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1221     } break;
1222   case tpo_struct:
1223     {
1224     } break;
1225   case tpo_method:
1226     {
1227       fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1228       fprintf(F, "params: %d\n", get_method_n_params(tp));
1229       fprintf(F, "results: %d\n", get_method_n_ress(tp));
1230     } break;
1231   case tpo_union:
1232     {
1233     } break;
1234   case tpo_array:
1235     {
1236     } break;
1237   case tpo_enumeration:
1238     {
1239     } break;
1240   case tpo_pointer:
1241     {
1242     } break;
1243   case tpo_primitive:
1244     {
1245     } break;
1246   default: break;
1247   } /* switch type */
1248 }
1249
1250
1251 static void print_typespecific_vcgattr(type *tp) {
1252   switch (get_type_tpop_code(tp)) {
1253   case tpo_class:
1254     {
1255       if (peculiarity_existent == get_class_peculiarity(tp))
1256     fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1257       else
1258     fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1259     } break;
1260   case tpo_struct:
1261     {
1262       fprintf (F, " " TYPE_METH_NODE_ATTR);
1263     } break;
1264   case tpo_method:
1265     {
1266     } break;
1267   case tpo_union:
1268     {
1269     } break;
1270   case tpo_array:
1271     {
1272     } break;
1273   case tpo_enumeration:
1274     {
1275     } break;
1276   case tpo_pointer:
1277     {
1278     } break;
1279   case tpo_primitive:
1280     {
1281     } break;
1282   default: break;
1283   } /* switch type */
1284 }
1285
1286 static int print_type_node(type *tp)
1287 {
1288   int bad = 0;
1289
1290   fprintf (F, "node: {title: ");
1291   PRINT_TYPEID(tp);
1292   fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1293   fprintf (F, " info1: \"");
1294   bad |= print_type_info(tp);
1295   print_typespecific_info(tp);
1296   fprintf (F, "\"");
1297   print_typespecific_vcgattr(tp);
1298   fprintf (F, "}\n");
1299
1300   return bad;
1301 }
1302
1303 #define X(a)    case a: fprintf(F, #a); break
1304 void dump_entity_node(entity *ent)
1305 {
1306   fprintf (F, "node: {title: \"");
1307   PRINT_ENTID(ent); fprintf(F, "\"");
1308   fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1309   fprintf (F, "label: ");
1310   fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1311   fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1312
1313   fprintf (F, "\nallocation:  ");
1314   switch (get_entity_allocation(ent)) {
1315     X(allocation_dynamic);
1316     X(allocation_automatic);
1317     X(allocation_static);
1318     X(allocation_parameter);
1319   }
1320
1321   fprintf (F, "\nvisibility:  ");
1322   switch (get_entity_visibility(ent)) {
1323     X(visibility_local);
1324     X(visibility_external_visible);
1325     X(visibility_external_allocated);
1326   }
1327
1328   fprintf (F, "\nvariability: ");
1329   switch (get_entity_variability(ent)) {
1330     X(variability_uninitialized);
1331     X(variability_initialized);
1332     X(variability_part_constant);
1333     X(variability_constant);
1334   }
1335
1336   fprintf (F, "\nvolatility:  ");
1337   switch (get_entity_volatility(ent)) {
1338     X(volatility_non_volatile);
1339     X(volatility_is_volatile);
1340   }
1341
1342   fprintf(F, "\npeculiarity:  %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1343   fprintf(F, "\nname:         %s\nld_name:      %s",
1344       get_entity_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1345   fprintf(F, "\noffset(bits): %d", get_entity_offset_bits(ent));
1346   if (is_method_type(get_entity_type(ent))) {
1347     if (get_entity_irg(ent))   /* can be null */
1348       { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1349     else
1350       { fprintf (F, "\nirg = NULL"); }
1351   }
1352   fprintf(F, "\"\n}\n");
1353 }
1354 #undef X
1355
1356 static void dump_enum_item(type *tp, int pos)
1357 {
1358   char buf[1024];
1359   ident *id  = get_enumeration_nameid(tp, pos);
1360   tarval *tv = get_enumeration_enum(tp, pos);
1361
1362   tarval_snprintf(buf, sizeof(buf), tv);
1363   fprintf (F, "node: {title: \"");
1364   PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1365   fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1366   fprintf (F, "label: ");
1367   fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1368   fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1369 }
1370
1371 /* dumps a type or entity and it's edges. */
1372 static void
1373 dump_type_info (type_or_ent *tore, void *env) {
1374   int i = 0;  /* to shutup gcc */
1375
1376   /* dump this type or entity */
1377
1378   switch (get_kind(tore)) {
1379   case k_entity:
1380     {
1381       entity *ent = (entity *)tore;
1382       ir_node *value;
1383       /* The node */
1384       dump_entity_node(ent);
1385       /* The Edges */
1386       /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
1387       fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1388                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1389       print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1390       if(is_class_type(get_entity_owner(ent))) {
1391     for(i = 0; i < get_entity_n_overwrites(ent); i++){
1392       print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1393     }
1394       }
1395       /* attached subgraphs */
1396       if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1397     if (is_atomic_entity(ent)) {
1398       value = get_atomic_ent_value(ent);
1399       if (value) {
1400             print_ent_node_edge(F,ent, value, ENT_VALUE_EDGE_ATTR, i);
1401         /* DDMN(value);  $$$ */
1402         dump_const_expression(value);
1403       }
1404     }
1405     if (is_compound_entity(ent)) {
1406       for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1407         value = get_compound_ent_value(ent, i);
1408         if (value) {
1409               print_ent_node_edge(F,ent,value,ENT_VALUE_EDGE_ATTR,i);
1410           dump_const_expression(value);
1411           print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1412           /*
1413         fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1414         ENT_CORR_EDGE_ATTR  "}\n", GET_ENTID(ent),
1415         get_compound_ent_value_member(ent, i), i);
1416           */
1417         }
1418       }
1419     }
1420       }
1421     } break;
1422   case k_type:
1423     {
1424       type *tp = (type *)tore;
1425       print_type_node(tp);
1426       /* and now the edges */
1427       switch (get_type_tpop_code(tp)) {
1428       case tpo_class:
1429     {
1430       for (i=0; i < get_class_n_supertypes(tp); i++) {
1431         print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1432       }
1433
1434       for (i=0; i < get_class_n_members(tp); i++) {
1435         print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1436       }
1437     } break;
1438       case tpo_struct:
1439     {
1440       for (i=0; i < get_struct_n_members(tp); i++) {
1441         print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1442       }
1443     } break;
1444       case tpo_method:
1445     {
1446       for (i = 0; i < get_method_n_params(tp); i++)
1447       {
1448              print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1449       }
1450       for (i = 0; i < get_method_n_ress(tp); i++)
1451       {
1452              print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1453       }
1454     } break;
1455       case tpo_union:
1456     {
1457       for (i = 0; i < get_union_n_members(tp); i++)
1458       {
1459             print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1460       }
1461     } break;
1462       case tpo_array:
1463     {
1464       print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1465       print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1466       for (i = 0; i < get_array_n_dimensions(tp); i++) {
1467         ir_node *upper = get_array_upper_bound(tp, i);
1468         ir_node *lower = get_array_lower_bound(tp, i);
1469         print_node_type_edge(F,upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1470         print_node_type_edge(F,lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1471         dump_const_expression(upper);
1472         dump_const_expression(lower);
1473       }
1474
1475     } break;
1476       case tpo_enumeration:
1477     {
1478       for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1479         dump_enum_item(tp, i);
1480         print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1481       }
1482     } break;
1483       case tpo_pointer:
1484     {
1485           print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1486     } break;
1487       case tpo_primitive:
1488     {
1489     } break;
1490       default: break;
1491       } /* switch type */
1492     }
1493     break; /* case k_type */
1494   default:
1495     {
1496       printf(" *** irdump,  dump_type_info(l.%i), faulty type.\n", __LINE__);
1497     } break;
1498   } /* switch kind_or_entity */
1499 }
1500
1501 /** For dumping class hierarchies.
1502  * Dumps a class type node and a superclass edge.
1503  * If env != null dumps entities of classes and overwrites edges.
1504  */
1505 static void
1506 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1507   int i = 0;  /* to shutup gcc */
1508
1509   /* dump this type or entity */
1510   switch (get_kind(tore)) {
1511   case k_entity: {
1512     entity *ent = (entity *)tore;
1513     if (get_entity_owner(ent) == get_glob_type()) break;
1514     if ((env) && is_class_type(get_entity_owner(ent))) {
1515       /* The node */
1516       dump_entity_node(ent);
1517       /* The edges */
1518       print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1519       for(i = 0; i < get_entity_n_overwrites(ent); i++)
1520       {
1521       print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1522       }
1523     }
1524   } break; /* case k_entity */
1525   case k_type:
1526     {
1527       type *tp = (type *)tore;
1528       if (tp == get_glob_type()) break;
1529       switch (get_type_tpop_code(tp)) {
1530         case tpo_class: {
1531       print_type_node(tp);
1532       /* and now the edges */
1533       for (i=0; i < get_class_n_supertypes(tp); i++)
1534       {
1535           print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1536       }
1537         } break;
1538         default: break;
1539       } /* switch type */
1540     }
1541     break; /* case k_type */
1542   default:
1543     {
1544       printf(" *** irdump,  dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1545     } break;
1546   } /* switch kind_or_entity */
1547 }
1548
1549 /*******************************************************************/
1550 /* dump analysis information that is expressed in graph terms.     */
1551 /*******************************************************************/
1552
1553 /* dump out edges */
1554 static void
1555 dump_out_edge (ir_node *n, void* env) {
1556   int i;
1557   for (i = 0; i < get_irn_n_outs(n); i++) {
1558     assert(get_irn_out(n, i));
1559     fprintf (F, "edge: {sourcename: \"");
1560     PRINT_NODEID(n);
1561     fprintf (F, "\" targetname: \"");
1562     PRINT_NODEID(get_irn_out(n, i));
1563     fprintf (F, "\" color: red linestyle: dashed");
1564     fprintf (F, "}\n");
1565   }
1566 }
1567
1568 static INLINE void
1569 dump_loop_label(ir_loop *loop) {
1570   fprintf (F, "loop %d, %d sons, %d nodes",
1571        get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1572 }
1573
1574 static INLINE void dump_loop_info(ir_loop *loop) {
1575   fprintf (F, " info1: \"");
1576   fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1577 #if DEBUG_libfirm   /* GL @@@ debug analyses */
1578   fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1579 #endif
1580   fprintf (F, "\"");
1581 }
1582
1583 static INLINE void
1584 dump_loop_node(ir_loop *loop) {
1585   fprintf (F, "node: {title: \"");
1586   PRINT_LOOPID(loop);
1587   fprintf (F, "\" label: \"");
1588   dump_loop_label(loop);
1589   fprintf (F, "\" ");
1590   dump_loop_info(loop);
1591   fprintf (F, "}\n");
1592
1593 }
1594
1595 static INLINE void
1596 dump_loop_node_edge (ir_loop *loop, int i) {
1597   assert(loop);
1598   fprintf (F, "edge: {sourcename: \"");
1599   PRINT_LOOPID(loop);
1600   fprintf (F, "\" targetname: \"");
1601   PRINT_NODEID(get_loop_node(loop, i));
1602   fprintf (F, "\" color: green");
1603   fprintf (F, "}\n");
1604 }
1605
1606 static INLINE void
1607 dump_loop_son_edge (ir_loop *loop, int i) {
1608   assert(loop);
1609   fprintf (F, "edge: {sourcename: \"");
1610   PRINT_LOOPID(loop);
1611   fprintf (F, "\" targetname: \"");
1612   PRINT_LOOPID(get_loop_son(loop, i));
1613   fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1614        get_loop_element_pos(loop, get_loop_son(loop, i)));
1615 }
1616
1617 static
1618 void dump_loops (ir_loop *loop) {
1619   int i;
1620   /* dump this loop node */
1621   dump_loop_node(loop);
1622
1623   /* dump edges to nodes in loop -- only if it is a real loop */
1624   if (get_loop_depth(loop) != 0) {
1625     for (i = 0; i < get_loop_n_nodes(loop); i++) {
1626       dump_loop_node_edge(loop, i);
1627     }
1628   }
1629   for (i = 0; i < get_loop_n_sons(loop); i++) {
1630     dump_loops(get_loop_son(loop, i));
1631     dump_loop_son_edge(loop, i);
1632   }
1633 }
1634
1635 static INLINE
1636 void dump_loop_nodes_into_graph(ir_graph *irg) {
1637   ir_graph *rem = current_ir_graph;
1638   current_ir_graph = irg;
1639
1640   if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1641
1642   current_ir_graph = rem;
1643 }
1644
1645
1646 /************************************************************************/
1647 /* open and close vcg file                                              */
1648 /************************************************************************/
1649
1650 static INLINE void
1651 dump_vcg_header(const char *name, const char *orientation) {
1652   char *label;
1653
1654   if (edge_label) {
1655     label = "yes";
1656   } else {
1657     label = "no";
1658   }
1659
1660   if (!orientation) orientation = "bottom_to_top";
1661
1662   /* print header */
1663   fprintf (F,
1664        "graph: { title: \"ir graph of %s\"\n"
1665        "display_edge_labels: %s\n"
1666        "layoutalgorithm: mindepth\n"
1667        "manhattan_edges: yes\n"
1668        "port_sharing: no\n"
1669        "orientation: %s\n"
1670        "classname 1:  \"intrablock Data\"\n"
1671        "classname 16: \"interblock Data\"\n"
1672        "classname 2:  \"Block\"\n"
1673        "classname 13: \"Control Flow\"\n"
1674        "classname 14: \"intrablock Memory\"\n"
1675        "classname 17: \"interblock Memory\"\n"
1676        "classname 15: \"Dominators\"\n"
1677        "classname 3:  \"Entity type\"\n"
1678        "classname 4:  \"Entity owner\"\n"
1679        "classname 5:  \"Method Param\"\n"
1680        "classname 6:  \"Method Res\"\n"
1681        "classname 7:  \"Super\"\n"
1682        "classname 8:  \"Union\"\n"
1683        "classname 9:  \"Points-to\"\n"
1684        "classname 10: \"Array Element Type\"\n"
1685        "classname 11: \"Overwrites\"\n"
1686        "classname 12: \"Member\"\n"
1687        "infoname 1: \"Attribute\"\n"
1688        "infoname 2: \"Verification errors\"\n",
1689        name, label, orientation);
1690
1691   fprintf (F, "\n");        /* a separator */
1692 }
1693
1694 static void vcg_open (ir_graph *irg, char * suffix1, char *suffix2) {
1695   const char *nm = get_irg_dump_name(irg);
1696   int len = strlen(nm), i, j;
1697   char *fname;  /* filename to put the vcg information in */
1698
1699   if (!suffix1) suffix1 = "";
1700   if (!suffix2) suffix2 = "";
1701
1702   /** open file for vcg graph */
1703   fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1704
1705   /* strncpy (fname, nm, len); */     /* copy the filename */
1706   j = 0;
1707   for (i = 0; i < len; ++i) {  /* replase '/' in the name: escape by @. */
1708     if (nm[i] == '/') {
1709       fname[j] = '@'; j++; fname[j] = '1'; j++;
1710     } else if (nm[i] == '@') {
1711       fname[j] = '@'; j++; fname[j] = '2'; j++;
1712     } else {
1713       fname[j] = nm[i]; j++;
1714     }
1715   }
1716   fname[j] = '\0';
1717   strcat (fname, suffix1);  /* append file suffix */
1718   strcat (fname, suffix2);  /* append file suffix */
1719   strcat (fname, ".vcg");   /* append the .vcg suffix */
1720   F = fopen (fname, "w");   /* open file for writing */
1721   if (!F) {
1722     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
1723   }
1724   free(fname);
1725 }
1726
1727 static void vcg_open_name (const char *name, char *suffix) {
1728   char *fname;  /* filename to put the vcg information in */
1729   int i, j, len = strlen(name);
1730
1731   if (!suffix) suffix = "";
1732
1733   /** open file for vcg graph */
1734   fname = malloc (len * 2 + 5 + strlen(suffix));
1735   /* strcpy (fname, name);*/    /* copy the filename */
1736   j = 0;
1737   for (i = 0; i < len; ++i) {  /* replase '/' in the name: escape by @. */
1738     if (name[i] == '/') {
1739       fname[j] = '@'; j++; fname[j] = '1'; j++;
1740     } else if (name[i] == '@') {
1741       fname[j] = '@'; j++; fname[j] = '2'; j++;
1742     } else {
1743       fname[j] = name[i]; j++;
1744     }
1745   }
1746   fname[j] = '\0';
1747   strcat (fname, suffix);
1748   strcat (fname, ".vcg");  /* append the .vcg suffix */
1749   F = fopen (fname, "w");  /* open file for writing */
1750   if (!F) {
1751     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
1752   }
1753   free(fname);
1754 }
1755
1756 static INLINE void dump_vcg_footer (void) {
1757   fprintf (F, "}\n");
1758 }
1759
1760 static void
1761 vcg_close (void) {
1762   dump_vcg_footer();    /* print footer */
1763   fclose (F);           /* close vcg file */
1764 }
1765
1766 /************************************************************************/
1767 /************************************************************************/
1768 /* Routines that dump all or parts of the firm representation to a file */
1769 /************************************************************************/
1770 /************************************************************************/
1771
1772 /************************************************************************/
1773 /* Dump ir graphs, differnt formats and additional information.         */
1774 /************************************************************************/
1775
1776 /** Routine to dump a graph, blocks as conventional nodes.
1777  */
1778 void
1779 dump_ir_graph (ir_graph *irg)
1780 {
1781   ir_graph *rem;
1782   char *suffix;
1783   rem = current_ir_graph;
1784
1785   if(strncmp(get_entity_name(get_irg_ent(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1786
1787   current_ir_graph = irg;
1788   if (interprocedural_view) suffix = "-pure-ip";
1789   else                      suffix = "-pure";
1790   vcg_open (irg, dump_file_suffix, suffix);
1791   dump_vcg_header(get_irg_dump_name(irg), NULL);
1792
1793   /* walk over the graph */
1794   /* dump_whole_node must be called in post visiting predecessors */
1795   irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1796
1797   /* dump the out edges in a separate walk */
1798   if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1799     irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1800   }
1801
1802   vcg_close();
1803
1804   current_ir_graph = rem;
1805 }
1806
1807
1808 void
1809 dump_ir_block_graph (ir_graph *irg)
1810 {
1811   int i;
1812   char *suffix;
1813
1814   if(strncmp(get_entity_name(get_irg_ent(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1815
1816   if (interprocedural_view) suffix = "-ip";
1817   else                      suffix = "";
1818   vcg_open (irg, dump_file_suffix, suffix);
1819   dump_vcg_header(get_irg_dump_name(irg), NULL);
1820
1821   construct_block_lists(irg);
1822
1823   for (i = 0; i < get_irp_n_irgs(); i++) {
1824     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1825     if (arr) {
1826       dump_graph(get_irp_irg(i));
1827       DEL_ARR_F(arr);
1828     }
1829   }
1830
1831   vcg_close();
1832 }
1833
1834 /** dumps a graph with type information
1835  */
1836 void
1837 dump_ir_graph_w_types (ir_graph *irg)
1838 {
1839   ir_graph *rem = current_ir_graph;
1840   char *suffix;
1841
1842   if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1843
1844   current_ir_graph = irg;
1845
1846   if (interprocedural_view) suffix = "-pure-wtypes-ip";
1847   else                      suffix = "-pure-wtypes";
1848   vcg_open (irg, dump_file_suffix, suffix);
1849   dump_vcg_header(get_irg_dump_name(irg), NULL);
1850
1851   /* dump common ir graph */
1852   irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1853   /* dump type info */
1854   type_walk_irg(irg, dump_type_info, NULL, NULL);
1855   inc_irg_visited(get_const_code_irg());
1856   /* dump edges from graph to type info */
1857   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1858
1859   vcg_close();
1860   current_ir_graph = rem;
1861 }
1862
1863 void
1864 dump_ir_block_graph_w_types (ir_graph *irg)
1865 {
1866   int i;
1867   char *suffix;
1868   ir_graph *rem = current_ir_graph;
1869
1870   if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1871
1872   if (interprocedural_view) suffix = "-wtypes-ip";
1873   else                      suffix = "-wtypes";
1874   vcg_open (irg, dump_file_suffix, suffix);
1875   dump_vcg_header(get_irg_dump_name(irg), NULL);
1876
1877   /* dump common blocked ir graph */
1878   construct_block_lists(irg);
1879
1880   for (i = 0; i < get_irp_n_irgs(); i++) {
1881     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1882     if (arr) {
1883       dump_graph(get_irp_irg(i));
1884       DEL_ARR_F(arr);
1885     }
1886   }
1887
1888   /* dump type info */
1889   current_ir_graph = irg;
1890   type_walk_irg(irg, dump_type_info, NULL, NULL);
1891   inc_irg_visited(get_const_code_irg());
1892
1893   /* dump edges from graph to type info */
1894   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1895
1896   current_ir_graph = rem;
1897   vcg_close();
1898 }
1899
1900 /***********************************************************************/
1901 /* The following routines dump a control flow graph.                   */
1902 /***********************************************************************/
1903
1904 static void
1905 dump_block_to_cfg (ir_node *block, void *env) {
1906   int i;
1907   ir_node *pred;
1908
1909   if (is_Block(block)) {
1910     /* This is a block. Dump a node for the block. */
1911     fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1912     fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1913     PRINT_NODEID(block);
1914     fprintf (F, "\" ");
1915     if (dump_dominator_information_flag)
1916       fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1917     fprintf (F, "}\n");
1918     /* Dump the edges */
1919     for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1920       if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1921     pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1922     fprintf (F, "edge: { sourcename: \"");
1923     PRINT_NODEID(block);
1924     fprintf (F, "\" targetname: \"");
1925     PRINT_NODEID(pred);
1926     fprintf (F, "\"}\n");
1927       }
1928
1929     /* Dump dominator edge */
1930     if (dump_dominator_information_flag && get_Block_idom(block)) {
1931       pred = get_Block_idom(block);
1932       fprintf (F, "edge: { sourcename: \"");
1933       PRINT_NODEID(block);
1934       fprintf (F, "\" targetname: \"");
1935       PRINT_NODEID(pred);
1936       fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1937     }
1938   }
1939 }
1940
1941 void
1942 dump_cfg (ir_graph *irg)
1943 {
1944   ir_graph *rem = current_ir_graph;
1945   int ddif = dump_dominator_information_flag;
1946   int ipv = interprocedural_view;
1947
1948   if(strncmp(get_irg_dump_name(irg), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1949
1950   current_ir_graph = irg;
1951
1952   vcg_open (irg, dump_file_suffix, "-cfg");
1953   dump_vcg_header(get_irg_dump_name(irg), NULL);
1954
1955   if (interprocedural_view) {
1956     printf("Warning: dumping cfg not in interprocedural view!\n");
1957     interprocedural_view = 0;
1958   }
1959
1960   if (get_irg_dom_state(irg) != dom_consistent)
1961     dump_dominator_information_flag = 0;
1962
1963   /* walk over the blocks in the graph */
1964   irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1965   dump_node (get_irg_bad(irg));
1966
1967   dump_dominator_information_flag = ddif;
1968   interprocedural_view = ipv;
1969   vcg_close();
1970   current_ir_graph = rem;
1971 }
1972
1973
1974
1975 void dump_callgraph(char *filesuffix) {
1976   int i, n_irgs = get_irp_n_irgs();
1977
1978   vcg_open_name  ("Callgraph", filesuffix);
1979   dump_vcg_header("Callgraph", NULL);
1980
1981   for (i = 0; i < n_irgs; ++i) {
1982     ir_graph *irg = get_irp_irg(i);
1983     entity *ent = get_irg_ent(irg);
1984     int j, n_callees = get_irg_n_callees(irg);
1985
1986     dump_entity_node(ent);
1987     for (j = 0; j < n_callees; ++j) {
1988       entity *c = get_irg_entity(get_irg_callee(irg, j));
1989       int be = is_irg_callee_backedge(irg, j);
1990       char *attr;
1991       attr = (be) ?
1992         "label:\"recursion\" color:red" :
1993         "label:\"calls\"";
1994       print_ent_ent_edge(F, ent, c, be, attr);
1995     }
1996   }
1997
1998   vcg_close();
1999 }
2000
2001
2002 /* Dump all irgs in interprocedural view to a single file. */
2003 void dump_all_cg_block_graph(void) {
2004   int i;
2005   int rem_view = interprocedural_view;
2006   interprocedural_view = 1;
2007
2008   vcg_open_name ("All_graphs", dump_file_suffix);
2009   dump_vcg_header("All_graphs", NULL);
2010
2011   /* collect nodes in all irgs reachable in call graph*/
2012   for (i = 0; i < get_irp_n_irgs(); i++)
2013     ird_set_irg_link(get_irp_irg(i), NULL);
2014
2015   cg_walk(clear_link, collect_node, NULL);
2016
2017   /* dump all graphs */
2018   for (i = 0; i < get_irp_n_irgs(); i++) {
2019     current_ir_graph = get_irp_irg(i);
2020     assert(ird_get_irg_link(current_ir_graph));
2021     dump_graph(current_ir_graph);
2022     DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2023   }
2024
2025   vcg_close();
2026   interprocedural_view = rem_view;
2027 }
2028
2029 /***********************************************************************/
2030 /* the following routines dumps type information without any ir nodes. */
2031 /***********************************************************************/
2032
2033 void
2034 dump_type_graph (ir_graph *irg)
2035 {
2036   ir_graph *rem;
2037   rem = current_ir_graph;
2038
2039   if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
2040
2041   current_ir_graph = irg;
2042
2043   vcg_open (irg, dump_file_suffix, "-type");
2044   dump_vcg_header(get_irg_dump_name(irg), NULL);
2045
2046   /* walk over the blocks in the graph */
2047   type_walk_irg(irg, dump_type_info, NULL, NULL);
2048   /* The walker for the const code can be called several times for the
2049      same (sub) experssion.  So that no nodes are dumped several times
2050      we decrease the visited flag of the corresponding graph after each
2051      walk.  So now increase it finally. */
2052   inc_irg_visited(get_const_code_irg());
2053
2054   vcg_close();
2055   current_ir_graph = rem;
2056 }
2057
2058 void
2059 dump_all_types (void)
2060 {
2061   vcg_open_name ("All_types", dump_file_suffix);
2062   dump_vcg_header("All_types", NULL);
2063   type_walk(dump_type_info, NULL, NULL);
2064   inc_irg_visited(get_const_code_irg());
2065   vcg_close();
2066 }
2067
2068 void
2069 dump_class_hierarchy (bool entities)
2070 {
2071   vcg_open_name ("class_hierarchy", dump_file_suffix);
2072   dump_vcg_header("class_hierarchy", NULL);
2073   if (entities)
2074     type_walk(dump_class_hierarchy_node, NULL, (void *)1);
2075   else
2076     type_walk(dump_class_hierarchy_node, NULL, NULL);
2077   vcg_close();
2078 }
2079
2080 /***********************************************************************/
2081 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
2082 /*  dump_ir_graph                                                      */
2083 /*  dump_ir_block_graph                                                */
2084 /*  dump_cfg                                                           */
2085 /*  dump_type_graph                                                    */
2086 /*  dump_ir_graph_w_types                                              */
2087 /***********************************************************************/
2088
2089 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
2090   int i;
2091   for (i=0; i < get_irp_n_irgs(); i++) {
2092     dmp_grph(get_irp_irg(i));
2093   }
2094 }
2095
2096
2097 /**********************************************************************************
2098  * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes  *
2099  * packed together in one subgraph                                                *
2100  **********************************************************************************/
2101
2102
2103
2104 void dump_loops_standalone (ir_loop *loop) {
2105   int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2106   loop_element le;
2107   ir_loop *son = NULL;
2108
2109   /* Dump a new loop node. */
2110   dump_loop_node(loop);
2111
2112   /* Dump the loop elements. */
2113
2114   for(i = 0; i < get_loop_n_elements(loop); i++)
2115     {
2116       le = get_loop_element(loop, i);
2117       son = le.son;
2118       if (get_kind(son) == k_ir_loop) {
2119
2120         /* We are a loop son -> Recurse */
2121
2122         if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2123           fprintf(F, "\" }\n");
2124           fprintf (F, "edge: {sourcename: \"");
2125           PRINT_LOOPID(loop);
2126           fprintf (F, "\" targetname: \"");
2127           PRINT_LOOPID(loop);
2128           fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2129           loop_node_started = 0;
2130         }
2131         dump_loop_son_edge(loop, son_number++);
2132         dump_loops_standalone(son);
2133       }
2134       else if (get_kind(son) == k_ir_node) {
2135         /* We are a loop node -> Collect firm nodes */
2136
2137         ir_node *n = le.node;
2138         int bad = 0;
2139
2140         if (!loop_node_started) {
2141           /* Start a new node which contains all firm nodes of the current loop */
2142           fprintf (F, "node: { title: \"");
2143           PRINT_LOOPID(loop);
2144           fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2145           loop_node_started = 1;
2146           first = i;
2147         }
2148         else
2149           fprintf(F, "\n");
2150
2151         bad |= dump_node_opcode(F, n);
2152         bad |= dump_node_mode (n);
2153         bad |= dump_node_typeinfo(n);
2154         fprintf (F, " ");
2155         bad |= dump_node_nodeattr(n);
2156         fprintf (F, " %ld", get_irn_node_nr(n));
2157       }
2158 #if CALLGRAPH_LOOP_TREE
2159       else {
2160         assert(get_kind(son) == k_ir_graph);
2161         /* We are a loop node -> Collect firm graphs */
2162
2163         ir_graph *n = (ir_graph *)le.node;
2164
2165         if (!loop_node_started) {
2166           /* Start a new node which contains all firm nodes of the current loop */
2167           fprintf (F, "node: { title: \"");
2168           PRINT_LOOPID(loop);
2169           fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2170           loop_node_started = 1;
2171           first = i;
2172         }
2173         else
2174           fprintf(F, "\n");
2175
2176         fprintf (F, " %s", get_irg_dump_name(n));
2177       }
2178 #endif
2179     }
2180
2181   if (loop_node_started) {
2182     fprintf(F, "\" }\n");
2183     fprintf (F, "edge: {sourcename: \"");
2184     PRINT_LOOPID(loop);
2185     fprintf (F, "\" targetname: \"");
2186     PRINT_LOOPID(loop);
2187     fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2188     loop_node_started = 0;
2189   }
2190 }
2191
2192 void dump_loop_tree(ir_graph *irg, char *suffix)
2193 {
2194   ir_graph *rem = current_ir_graph;
2195   int el_rem = edge_label;
2196   edge_label = 1;
2197
2198   /* @@@ AS: What does that do? */
2199   if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
2200
2201   current_ir_graph = irg;
2202
2203   vcg_open(irg, suffix, "-looptree");
2204   dump_vcg_header(get_irg_dump_name(irg), "top_to_bottom");
2205
2206   if (get_irg_loop(irg)) dump_loops_standalone(get_irg_loop(irg));
2207
2208   vcg_close();
2209
2210   edge_label = el_rem;
2211   current_ir_graph = rem;
2212 }
2213
2214 #if CALLGRAPH_LOOP_TREE
2215 /* works, but the tree is meaningless. */
2216 void dump_callgraph_loop_tree(ir_loop *l, char *suffix) {
2217   vcg_open_name("callgraph_looptree", suffix);
2218   dump_vcg_header("callgraph_looptree", "top_to_bottom");
2219   dump_loops_standalone(l);
2220   vcg_close();
2221 }
2222 #endif
2223
2224
2225 /*******************************************************************************/
2226 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2227 /*******************************************************************************/
2228
2229 void collect_nodeloop(ir_loop *loop, eset *loopnodes) {
2230   int i, son_number = 0, node_number = 0;
2231
2232   if (dump_loop_information_flag) dump_loop_node(loop);
2233
2234   for (i = 0; i < get_loop_n_elements(loop); i++) {
2235     loop_element le = get_loop_element(loop, i);
2236     if (*(le.kind) == k_ir_loop) {
2237       if (dump_loop_information_flag) dump_loop_son_edge(loop, son_number++);
2238       /* Recur */
2239       collect_nodeloop(le.son, loopnodes);
2240     } else {
2241       if (dump_loop_information_flag) dump_loop_node_edge(loop, node_number++);
2242       eset_insert(loopnodes, le.node);
2243     }
2244   }
2245 }
2246
2247 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2248   int i, j, start;
2249
2250   for(i = 0; i < get_loop_n_elements(loop); i++) {
2251     loop_element le = get_loop_element(loop, i);
2252     if (*(le.kind) == k_ir_loop) {
2253       /* Recur */
2254       collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2255     } else {
2256       if (is_Block(le.node)) start = 0; else start = -1;
2257       for (j = start; j < get_irn_arity(le.node); j++) {
2258     ir_node *pred = get_irn_n(le.node, j);
2259     if (!eset_contains(loopnodes, pred)) {
2260       eset_insert(extnodes, pred);
2261       if (!is_Block(pred)) {
2262         pred = get_nodes_block(pred);
2263         if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2264           }
2265     }
2266       }
2267     }
2268   }
2269 }
2270
2271 void dump_loop (ir_loop *l, char *suffix) {
2272   char name[50];
2273   eset *loopnodes = eset_create();
2274   eset *extnodes = eset_create();
2275   ir_node *n, *b;
2276
2277   sprintf(name, "loop_%d", get_loop_loop_nr(l));
2278   vcg_open_name (name, suffix);
2279   dump_vcg_header(name, NULL);
2280
2281   /* collect all nodes to dump */
2282   collect_nodeloop(l, loopnodes);
2283   collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2284
2285   /* build block lists */
2286   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2287     set_irn_link(n, NULL);
2288   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2289     set_irn_link(n, NULL);
2290   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2291     if (!is_Block(n)) {
2292       b = get_nodes_block(n);
2293       set_irn_link(n, get_irn_link(b));
2294       set_irn_link(b, n);
2295     }
2296   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2297     if (!is_Block(n)) {
2298       b = get_nodes_block(n);
2299       set_irn_link(n, get_irn_link(b));
2300       set_irn_link(b, n);
2301     }
2302
2303   for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2304     if (is_Block(b)) {
2305       fprintf(F, "graph: { title: \"");
2306       PRINT_NODEID(b);
2307       fprintf(F, "\"  label: \"");
2308       dump_node_opcode(F, b);
2309       fprintf (F, " %ld", get_irn_node_nr(b));
2310       fprintf(F, "\" status:clustered color:yellow\n");
2311
2312       /* dump the blocks edges */
2313       dump_ir_data_edges(b);
2314
2315       /* dump the nodes that go into the block */
2316       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2317     if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2318     dump_node(n);
2319     overrule_nodecolor = NULL;
2320     if (!eset_contains(extnodes, n)) dump_ir_data_edges(n);
2321       }
2322
2323       /* Close the vcg information for the block */
2324       fprintf(F, "}\n");
2325       dump_const_node_local(b);
2326       fprintf(F, "\n");
2327     }
2328   for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2329     if (is_Block(b)) {
2330       fprintf(F, "graph: { title: \"");
2331       PRINT_NODEID(b);
2332       fprintf(F, "\"  label: \"");
2333       dump_node_opcode(F, b);
2334       fprintf (F, " %ld", get_irn_node_nr(b));
2335       fprintf(F, "\" status:clustered color:lightblue\n");
2336
2337       /* dump the nodes that go into the block */
2338       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2339     if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2340     dump_node(n);
2341     overrule_nodecolor = NULL;
2342     if (eset_contains(loopnodes, n)) dump_ir_data_edges(n);
2343       }
2344
2345       /* Close the vcg information for the block */
2346       fprintf(F, "}\n");
2347       dump_const_node_local(b);
2348       fprintf(F, "\n");
2349     }
2350
2351   eset_destroy(loopnodes);
2352   eset_destroy(extnodes);
2353   vcg_close();
2354 }