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