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