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