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