01b2d91d00af1325be5110cf4fb78bfe8b42d810
[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, "\nAnalysed type: %s", 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  */
1928 void
1929 dump_ir_graph (ir_graph *irg, const char *suffix )
1930 {
1931   FILE *f;
1932   ir_graph *rem;
1933   char *suffix1;
1934   rem = current_ir_graph;
1935
1936   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1937   current_ir_graph = irg;
1938   if (get_interprocedural_view()) suffix1 = "-pure-ip";
1939   else                            suffix1 = "-pure";
1940   f = vcg_open(irg, suffix, suffix1);
1941   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1942
1943   /* walk over the graph */
1944   /* dump_whole_node must be called in post visiting predecessors */
1945   irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1946
1947   /* dump the out edges in a separate walk */
1948   if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1949     irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1950   }
1951
1952   vcg_close(f);
1953
1954   current_ir_graph = rem;
1955 }
1956
1957
1958 void
1959 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1960 {
1961   FILE *f;
1962   int i;
1963   char *suffix1;
1964
1965   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1966     return;
1967
1968   if (get_interprocedural_view()) suffix1 = "-ip";
1969   else                            suffix1 = "";
1970   f = vcg_open(irg, suffix, suffix1);
1971   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1972
1973   construct_block_lists(irg);
1974
1975   for (i = 0; i < get_irp_n_irgs(); i++) {
1976     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1977     if (arr) {
1978       dump_graph(f, get_irp_irg(i));
1979       DEL_ARR_F(arr);
1980     }
1981   }
1982
1983   vcg_close(f);
1984 }
1985
1986 /** dumps a graph with type information
1987  */
1988 void
1989 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1990 {
1991   FILE *f;
1992   ir_graph *rem = current_ir_graph;
1993   char *suffix1;
1994
1995   /* if a filter is set, dump only the irg's that match the filter */
1996   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1997     return;
1998
1999   current_ir_graph = irg;
2000
2001   if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2002   else                            suffix1 = "-pure-wtypes";
2003   f = vcg_open(irg,suffix, suffix1);
2004   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2005
2006   /* dump common ir graph */
2007   irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2008   /* dump type info */
2009   type_walk_irg(irg, dump_type_info, NULL, f);
2010   inc_irg_visited(get_const_code_irg());
2011   /* dump edges from graph to type info */
2012   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2013
2014   vcg_close(f);
2015   current_ir_graph = rem;
2016 }
2017
2018 void
2019 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2020 {
2021   FILE *f;
2022   int i;
2023   char *suffix1;
2024   ir_graph *rem = current_ir_graph;
2025
2026   /* if a filter is set, dump only the irg's that match the filter */
2027   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2028     return;
2029
2030   if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2031   else                            suffix1 = "-wtypes";
2032   f = vcg_open(irg, suffix, suffix1);
2033   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2034
2035   /* dump common blocked ir graph */
2036   construct_block_lists(irg);
2037
2038   for (i = 0; i < get_irp_n_irgs(); i++) {
2039     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2040     if (arr) {
2041       dump_graph(f, get_irp_irg(i));
2042       DEL_ARR_F(arr);
2043     }
2044   }
2045
2046   /* dump type info */
2047   current_ir_graph = irg;
2048   type_walk_irg(irg, dump_type_info, NULL, f);
2049   inc_irg_visited(get_const_code_irg());
2050
2051   /* dump edges from graph to type info */
2052   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2053
2054   current_ir_graph = rem;
2055   vcg_close(f);
2056 }
2057
2058 /*---------------------------------------------------------------------*/
2059 /* The following routines dump a control flow graph.                   */
2060 /*---------------------------------------------------------------------*/
2061
2062 static void
2063 dump_block_to_cfg(ir_node *block, void *env) {
2064   FILE *F = env;
2065   int i, fl;
2066   ir_node *pred;
2067
2068   if (is_Block(block)) {
2069     /* This is a block. Dump a node for the block. */
2070     fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2071     fprintf (F, "\" label: \"");
2072     if (block == get_irg_start_block(get_irn_irg(block)))
2073       fprintf(F, "Start ");
2074     if (block == get_irg_end_block(get_irn_irg(block)))
2075       fprintf(F, "End ");
2076
2077     fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2078     PRINT_NODEID(block);
2079     fprintf (F, "\" ");
2080     fprintf(F, "info1:\"");
2081     if (dump_dominator_information_flag)
2082       fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2083
2084     /* show arity and possible Bad predecessors of the block */
2085     fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2086     for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2087       ir_node *pred = get_Block_cfgpred(block, i);
2088       if (is_Bad(pred)) {
2089     if (! fl)
2090       fprintf(F, "Bad pred at pos: ");
2091     fprintf(F, "%d ", i);
2092     fl = 1;
2093       }
2094     }
2095     if (fl)
2096       fprintf(F, "\n");
2097
2098     fprintf (F, "\"");  /* closing quote of info */
2099
2100     if ((block == get_irg_start_block(get_irn_irg(block))) ||
2101     (block == get_irg_end_block(get_irn_irg(block)))     )
2102       fprintf(F, " color:blue ");
2103     else if (fl)
2104       fprintf(F, " color:yellow ");
2105
2106     fprintf (F, "}\n");
2107     /* Dump the edges */
2108     for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2109       if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2110         pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2111         fprintf (F, "edge: { sourcename: \"");
2112         PRINT_NODEID(block);
2113         fprintf (F, "\" targetname: \"");
2114         PRINT_NODEID(pred);
2115         fprintf (F, "\"}\n");
2116       }
2117
2118     /* Dump dominator edge */
2119     if (dump_dominator_information_flag && get_Block_idom(block)) {
2120       pred = get_Block_idom(block);
2121       fprintf (F, "edge: { sourcename: \"");
2122       PRINT_NODEID(block);
2123       fprintf (F, "\" targetname: \"");
2124       PRINT_NODEID(pred);
2125       fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2126     }
2127   }
2128 }
2129
2130 void
2131 dump_cfg (ir_graph *irg, const char *suffix)
2132 {
2133   FILE *f;
2134   ir_graph *rem = current_ir_graph;
2135   int ddif = dump_dominator_information_flag;
2136   int ipv = get_interprocedural_view();
2137
2138   /* if a filter is set, dump only the irg's that match the filter */
2139   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2140     return;
2141
2142   current_ir_graph = irg;
2143
2144   f = vcg_open(irg, suffix, "-cfg");
2145   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2146
2147   if (ipv) {
2148     printf("Warning: dumping cfg not in interprocedural view!\n");
2149     set_interprocedural_view(false);
2150   }
2151
2152   if (get_irg_dom_state(irg) != dom_consistent)
2153     dump_dominator_information_flag = 0;
2154
2155   /* walk over the blocks in the graph */
2156   irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2157   dump_node(f, get_irg_bad(irg));
2158
2159   dump_dominator_information_flag = ddif;
2160   set_interprocedural_view(ipv);
2161   vcg_close(f);
2162   current_ir_graph = rem;
2163 }
2164
2165 static int weight_overall(int rec, int loop) {
2166   return 2*rec + loop;
2167 }
2168
2169 static int compute_color (int my, int max) {
2170   int color;
2171   if (!max) {
2172     color = 0;
2173   } else {
2174     /* if small, scale to the full color range. */
2175     if (max < n_colors)
2176       my = my * (n_colors/max);
2177
2178     int step = 1 + (max / n_colors);
2179
2180     color = my/step;
2181   }
2182   return base_color + n_colors - color;
2183 }
2184
2185 static int get_entity_color(entity *ent) {
2186   assert(get_entity_irg(ent));
2187   ir_graph *irg = get_entity_irg(ent);
2188
2189   int rec_depth     = get_irg_recursion_depth(irg);
2190   int loop_depth    = get_irg_loop_depth(irg);
2191   int overall_depth = weight_overall(rec_depth, loop_depth);
2192
2193   int max_rec_depth     = irp->max_callgraph_recursion_depth;
2194   int max_loop_depth    = irp->max_callgraph_loop_depth;
2195   int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2196
2197   /* int my_rec_color     = compute_color(rec_depth, max_rec_depth); */
2198   /* int my_loop_color    = compute_color(loop_depth, max_loop_depth); */
2199   int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2200
2201   return my_overall_color;
2202 }
2203
2204 void dump_callgraph(const char *suffix) {
2205   FILE *F;
2206   int i, n_irgs = get_irp_n_irgs();
2207   int rem = edge_label;
2208   edge_label = 1;
2209   //ident *prefix = new_id_from_str("java/");
2210
2211   F = vcg_open_name("Callgraph", suffix);
2212   dump_vcg_header(F, "Callgraph", NULL);
2213
2214   for (i = 0; i < n_irgs; ++i) {
2215     ir_graph *irg = get_irp_irg(i);
2216     entity *ent = get_irg_entity(irg);
2217     int j, n_callees = get_irg_n_callees(irg);
2218
2219     /* Do not dump runtime system. */
2220     //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2221
2222     dump_entity_node(F, ent, get_entity_color(ent));
2223     for (j = 0; j < n_callees; ++j) {
2224       entity *c = get_irg_entity(get_irg_callee(irg, j));
2225       //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2226       int be = is_irg_callee_backedge(irg, j);
2227       char *attr;
2228       attr = (be) ?
2229         "label:\"recursion %d\" color: %d" :
2230         "label:\"calls %d\" color: %d";
2231       print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2232     }
2233   }
2234
2235   edge_label = rem;
2236   vcg_close(F);
2237 }
2238
2239 /* Dump all irgs in interprocedural view to a single file. */
2240 void dump_all_cg_block_graph(const char *suffix) {
2241   FILE *f;
2242   int i;
2243   int rem_view = get_interprocedural_view();
2244   set_interprocedural_view(true);
2245
2246   f = vcg_open_name("All_graphs", suffix);
2247   dump_vcg_header(f, "All_graphs", NULL);
2248
2249   /* collect nodes in all irgs reachable in call graph*/
2250   for (i = 0; i < get_irp_n_irgs(); i++)
2251     ird_set_irg_link(get_irp_irg(i), NULL);
2252
2253   cg_walk(clear_link, collect_node, NULL);
2254
2255   /* dump all graphs */
2256   for (i = 0; i < get_irp_n_irgs(); i++) {
2257     current_ir_graph = get_irp_irg(i);
2258     assert(ird_get_irg_link(current_ir_graph));
2259     dump_graph(f, current_ir_graph);
2260     DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2261   }
2262
2263   vcg_close(f);
2264   set_interprocedural_view(rem_view);
2265 }
2266
2267 /*---------------------------------------------------------------------*/
2268 /* the following routines dumps type information without any ir nodes. */
2269 /*---------------------------------------------------------------------*/
2270
2271 void
2272 dump_type_graph (ir_graph *irg, const char *suffix)
2273 {
2274   FILE *f;
2275   ir_graph *rem;
2276   rem = current_ir_graph;
2277
2278   /* if a filter is set, dump only the irg's that match the filter */
2279   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2280
2281   current_ir_graph = irg;
2282
2283   f = vcg_open(irg, suffix, "-type");
2284   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2285
2286   /* walk over the blocks in the graph */
2287   type_walk_irg(irg, dump_type_info, NULL, f);
2288   /* The walker for the const code can be called several times for the
2289      same (sub) experssion.  So that no nodes are dumped several times
2290      we decrease the visited flag of the corresponding graph after each
2291      walk.  So now increase it finally. */
2292   inc_irg_visited(get_const_code_irg());
2293
2294   vcg_close(f);
2295   current_ir_graph = rem;
2296 }
2297
2298 void
2299 dump_all_types (const char *suffix)
2300 {
2301   FILE *f = vcg_open_name("All_types", suffix);
2302   dump_vcg_header(f, "All_types", NULL);
2303   type_walk(dump_type_info, NULL, f);
2304   inc_irg_visited(get_const_code_irg());
2305   vcg_close(f);
2306 }
2307
2308 void
2309 dump_class_hierarchy (bool entities, const char *suffix)
2310 {
2311   FILE *f = vcg_open_name("class_hierarchy", suffix);
2312   h_env_t env;
2313
2314   env.f = f;
2315   dump_vcg_header(f, "class_hierarchy", NULL);
2316   if (entities)
2317     env.dump_ent = 1;
2318   else
2319     env.dump_ent = 0;
2320   type_walk(dump_class_hierarchy_node, NULL, &env);
2321   vcg_close(f);
2322 }
2323
2324 /*---------------------------------------------------------------------*/
2325 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
2326 /*  dump_ir_graph                                                      */
2327 /*  dump_ir_block_graph                                                */
2328 /*  dump_cfg                                                           */
2329 /*  dump_type_graph                                                    */
2330 /*  dump_ir_graph_w_types                                              */
2331 /*---------------------------------------------------------------------*/
2332
2333 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2334   int i, n_irgs = get_irp_n_irgs();
2335   for (i = 0; i < n_irgs; ++i) {
2336     dmp_grph(get_irp_irg(i), suffix);
2337   }
2338 }
2339
2340
2341 /*--------------------------------------------------------------------------------*
2342  * Dumps a stand alone loop graph with firm nodes which belong to one loop node   *
2343  * packed together in one subgraph/box                                            *
2344  *--------------------------------------------------------------------------------*/
2345
2346 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2347   int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2348   loop_element le;
2349   ir_loop *son = NULL;
2350
2351   /* Dump a new loop node. */
2352   dump_loop_node(F, loop);
2353
2354   /* Dump the loop elements. */
2355
2356   for(i = 0; i < get_loop_n_elements(loop); i++) {
2357     le = get_loop_element(loop, i);
2358     son = le.son;
2359     if (get_kind(son) == k_ir_loop) {
2360
2361       /* We are a loop son -> Recurse */
2362
2363       if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2364         fprintf(F, "\" }\n");
2365         fprintf (F, "edge: {sourcename: \"");
2366         PRINT_LOOPID(loop);
2367         fprintf (F, "\" targetname: \"");
2368         PRINT_LOOPID(loop);
2369         fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2370         loop_node_started = 0;
2371       }
2372       dump_loop_son_edge(F, loop, son_number++);
2373       dump_loops_standalone(F, son);
2374     } else if (get_kind(son) == k_ir_node) {
2375       /* We are a loop node -> Collect firm nodes */
2376
2377       ir_node *n = le.node;
2378       int bad = 0;
2379
2380       if (!loop_node_started) {
2381         /* Start a new node which contains all firm nodes of the current loop */
2382         fprintf (F, "node: { title: \"");
2383         PRINT_LOOPID(loop);
2384         fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2385         loop_node_started = 1;
2386         first = i;
2387       }
2388       else
2389         fprintf(F, "\n");
2390
2391       bad |= dump_node_opcode(F, n);
2392       bad |= dump_node_mode(F, n);
2393       bad |= dump_node_typeinfo(F, n);
2394       fprintf (F, " ");
2395       bad |= dump_node_nodeattr(F, n);
2396       fprintf (F, " %ld", get_irn_node_nr(n));
2397       /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2398       if (has_backedges(n)) fprintf(F, "\t loop head!");
2399     } else { /* for callgraph loop tree */
2400       assert(get_kind(son) == k_ir_graph);
2401       /* We are a loop node -> Collect firm graphs */
2402       ir_graph *n = (ir_graph *)le.node;
2403       if (!loop_node_started) {
2404         /* Start a new node which contains all firm nodes of the current loop */
2405         fprintf (F, "node: { title: \"");
2406         PRINT_LOOPID(loop);
2407         fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2408         loop_node_started = 1;
2409         first = i;
2410       }
2411       else
2412     fprintf(F, "\n");
2413       fprintf (F, " %s", get_irg_dump_name(n));
2414       /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2415     }
2416   }
2417
2418   if (loop_node_started) {
2419     fprintf(F, "\" }\n");
2420     fprintf (F, "edge: {sourcename: \"");
2421     PRINT_LOOPID(loop);
2422     fprintf (F, "\" targetname: \"");
2423     PRINT_LOOPID(loop);
2424     fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2425     loop_node_started = 0;
2426   }
2427 }
2428
2429 void dump_loop_tree(ir_graph *irg, const char *suffix)
2430 {
2431   FILE *f;
2432   ir_graph *rem = current_ir_graph;
2433   int el_rem = edge_label;
2434   edge_label = 1;
2435
2436   /* if a filter is set, dump only the irg's that match the filter */
2437   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2438     return;
2439
2440   current_ir_graph = irg;
2441
2442   f = vcg_open(irg, suffix, "-looptree");
2443   dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2444
2445   if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2446
2447   vcg_close(f);
2448
2449   edge_label = el_rem;
2450   current_ir_graph = rem;
2451 }
2452
2453 void dump_callgraph_loop_tree(const char *suffix) {
2454   FILE *F;
2455   F = vcg_open_name("Callgraph_looptree", suffix);
2456   dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2457   dump_loops_standalone(F, irp->outermost_cg_loop);
2458   vcg_close(F);
2459 }
2460
2461
2462 /*-----------------------------------------------------------------------------*/
2463 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2464 /*-----------------------------------------------------------------------------*/
2465
2466 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2467   int i, son_number = 0, node_number = 0;
2468
2469   if (dump_loop_information_flag) dump_loop_node(F, loop);
2470
2471   for (i = 0; i < get_loop_n_elements(loop); i++) {
2472     loop_element le = get_loop_element(loop, i);
2473     if (*(le.kind) == k_ir_loop) {
2474       if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2475       /* Recur */
2476       collect_nodeloop(F, le.son, loopnodes);
2477     } else {
2478       if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2479       eset_insert(loopnodes, le.node);
2480     }
2481   }
2482 }
2483
2484 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2485   int i, j, start;
2486
2487   for(i = 0; i < get_loop_n_elements(loop); i++) {
2488     loop_element le = get_loop_element(loop, i);
2489     if (*(le.kind) == k_ir_loop) {
2490       /* Recur */
2491       collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2492     } else {
2493       if (is_Block(le.node)) start = 0; else start = -1;
2494       for (j = start; j < get_irn_arity(le.node); j++) {
2495         ir_node *pred = get_irn_n(le.node, j);
2496         if (!eset_contains(loopnodes, pred)) {
2497           eset_insert(extnodes, pred);
2498           if (!is_Block(pred)) {
2499             pred = get_nodes_block(pred);
2500             if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2501           }
2502         }
2503       }
2504     }
2505   }
2506 }
2507
2508 void dump_loop(ir_loop *l, const char *suffix) {
2509   FILE *F;
2510   char name[50];
2511   eset *loopnodes = eset_create();
2512   eset *extnodes = eset_create();
2513   ir_node *n, *b;
2514
2515   snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2516   F = vcg_open_name (name, suffix);
2517   dump_vcg_header(F, name, NULL);
2518
2519   /* collect all nodes to dump */
2520   collect_nodeloop(F, l, loopnodes);
2521   collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2522
2523   /* build block lists */
2524   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2525     set_irn_link(n, NULL);
2526   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2527     set_irn_link(n, NULL);
2528   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2529     if (!is_Block(n)) {
2530       b = get_nodes_block(n);
2531       set_irn_link(n, get_irn_link(b));
2532       set_irn_link(b, n);
2533     }
2534   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2535     if (!is_Block(n)) {
2536       b = get_nodes_block(n);
2537       set_irn_link(n, get_irn_link(b));
2538       set_irn_link(b, n);
2539     }
2540
2541   for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2542     if (is_Block(b)) {
2543       fprintf(F, "graph: { title: \"");
2544       PRINT_NODEID(b);
2545       fprintf(F, "\"  label: \"");
2546       dump_node_opcode(F, b);
2547       fprintf (F, " %ld", get_irn_node_nr(b));
2548       fprintf(F, "\" status:clustered color:yellow\n");
2549
2550       /* dump the blocks edges */
2551       dump_ir_data_edges(F, b);
2552
2553       /* dump the nodes that go into the block */
2554       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2555         if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2556         dump_node(F, n);
2557         overrule_nodecolor = NULL;
2558         if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2559       }
2560
2561       /* Close the vcg information for the block */
2562       fprintf(F, "}\n");
2563       dump_const_node_local(F, b);
2564       fprintf(F, "\n");
2565     }
2566   for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2567     if (is_Block(b)) {
2568       fprintf(F, "graph: { title: \"");
2569       PRINT_NODEID(b);
2570       fprintf(F, "\"  label: \"");
2571       dump_node_opcode(F, b);
2572       fprintf (F, " %ld", get_irn_node_nr(b));
2573       fprintf(F, "\" status:clustered color:lightblue\n");
2574
2575       /* dump the nodes that go into the block */
2576       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2577         if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2578         dump_node(F, n);
2579         overrule_nodecolor = NULL;
2580         if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2581       }
2582
2583       /* Close the vcg information for the block */
2584       fprintf(F, "}\n");
2585       dump_const_node_local(F, b);
2586       fprintf(F, "\n");
2587     }
2588
2589   eset_destroy(loopnodes);
2590   eset_destroy(extnodes);
2591   vcg_close(F);
2592 }