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