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