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