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