fixed file dump filter stuff
[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   if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
965     fprintf (F, INTRA_DATA_EDGE_ATTR);
966   else
967     fprintf (F, INTER_DATA_EDGE_ATTR);
968 }
969
970 static void
971 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
972   if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
973     fprintf (F, INTRA_MEM_EDGE_ATTR);
974   else
975     fprintf (F, INTER_MEM_EDGE_ATTR);
976 }
977
978 static void
979 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
980   assert(from);
981
982   if (dump_backedge_information_flag && is_backedge(from, to))
983     fprintf (F, BACK_EDGE_ATTR);
984
985   switch (get_irn_opcode(from)) {
986   case iro_Block:
987     fprintf (F, CF_EDGE_ATTR);
988     break;
989   case iro_Start:   break;
990   case iro_End:
991     if (to >= 0) {
992       if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
993     fprintf (F, CF_EDGE_ATTR);
994       if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
995     fprintf (F, INTER_MEM_EDGE_ATTR);
996     }
997     break;
998   case iro_EndReg:
999   case iro_EndExcept:
1000   case iro_Jmp:
1001   case iro_Break:
1002   case iro_Cond:
1003     print_data_edge_vcgattr(F, from, to);
1004     break;
1005   case iro_Return:
1006   case iro_Raise:
1007     if (to == 0)
1008       print_mem_edge_vcgattr(F, from, to);
1009     else
1010       print_data_edge_vcgattr(F, from, to);
1011     break;
1012   case iro_Const:
1013   case iro_SymConst:
1014     print_data_edge_vcgattr(F, from, to);
1015     break;
1016   case iro_Sel:
1017   case iro_Call:
1018     if (to == 0)
1019       print_mem_edge_vcgattr(F, from, to);
1020     else
1021       print_data_edge_vcgattr(F, from, to);
1022     break;
1023   case iro_CallBegin:
1024   case iro_Add:
1025   case iro_Sub:
1026   case iro_Minus:
1027   case iro_Mul:
1028     print_data_edge_vcgattr(F, from, to);
1029     break;
1030   case iro_Quot:
1031   case iro_DivMod:
1032   case iro_Div:
1033   case iro_Mod:
1034     if (to == 0)
1035       print_mem_edge_vcgattr(F, from, to);
1036     else
1037       print_data_edge_vcgattr(F, from, to);
1038     break;
1039   case iro_Abs:
1040   case iro_And:
1041   case iro_Or:
1042   case iro_Eor:
1043   case iro_Shl:
1044   case iro_Shr:
1045   case iro_Shrs:
1046   case iro_Rot:
1047   case iro_Cmp:
1048   case iro_Conv:
1049       print_data_edge_vcgattr(F, from, to);
1050     break;
1051   case iro_Phi:
1052     if (get_irn_modecode(from) == irm_M)
1053       fprintf (F, INTER_MEM_EDGE_ATTR);
1054     else
1055       print_data_edge_vcgattr(F, from, to);
1056     break;
1057   case iro_Load:
1058   case iro_Store:
1059   case iro_Alloc:
1060   case iro_Free:
1061     if (to == 0)
1062       print_mem_edge_vcgattr(F, from, to);
1063     else
1064       print_data_edge_vcgattr(F, from, to);
1065     break;
1066   case iro_Sync:
1067     print_mem_edge_vcgattr(F, from, to);
1068     break;
1069   case iro_Tuple:  break;
1070   case iro_Proj:
1071   case iro_Filter:
1072     switch (get_irn_modecode(from)) {
1073     case irm_X:
1074       fprintf (F, CF_EDGE_ATTR);
1075       break;
1076     case irm_M:
1077       fprintf (F, INTER_MEM_EDGE_ATTR);
1078       break;
1079     default:
1080       print_data_edge_vcgattr(F, from, to);
1081       break;
1082     }
1083     break;
1084   case iro_Bad:     break;
1085   case iro_Unknown: break;
1086   case iro_Id:
1087     switch (get_irn_modecode(from)) {
1088     case irm_M:
1089       fprintf (F, INTRA_MEM_EDGE_ATTR);
1090       break;
1091     case irm_X:
1092       fprintf (F, CF_EDGE_ATTR);
1093       break;
1094     default:
1095       print_data_edge_vcgattr(F, from, to);
1096       break;
1097     } break;
1098   default:
1099     ;
1100   }
1101 }
1102
1103 /* dump edges to our inputs */
1104 static void
1105 dump_ir_data_edges(FILE *F, ir_node *n)  {
1106   int i;
1107   unsigned long visited = get_irn_visited(n);
1108
1109   if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1110     return;
1111
1112   for (i = 0; i < get_irn_arity(n); i++) {
1113     ir_node * pred = get_irn_n(n, i);
1114     assert(pred);
1115
1116     if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1117       continue; /* pred not dumped */
1118
1119     if (dump_backedge_information_flag && is_backedge(n, i))
1120       fprintf (F, "backedge: {sourcename: \"");
1121     else
1122       fprintf (F, "edge: {sourcename: \"");
1123     PRINT_NODEID(n);
1124     fprintf (F, "\" targetname: ");
1125     if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1126       PRINT_CONSTID(n, pred);
1127     } else {
1128       fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1129     }
1130     fprintf (F, " label: \"%d\" ", i);
1131     print_edge_vcgattr(F, n, i);
1132     fprintf (F, "}\n");
1133   }
1134 }
1135
1136 /** Dumps a node and its edges but not the block edge
1137  */
1138 static INLINE void
1139 dump_node_wo_blockedge (ir_node *n, void *env) {
1140   FILE *F = env;
1141   dump_node(F, n);
1142   dump_ir_data_edges(F, n);
1143 }
1144
1145 /** Dumps a node and its edges.
1146  */
1147 static void
1148 dump_whole_node (ir_node *n, void *env) {
1149   FILE *F = env;
1150   dump_node_wo_blockedge(n, env);
1151   if (!node_floats(n)) dump_ir_block_edge(F, n);
1152 }
1153
1154 static void
1155 dump_const_node(ir_node *n, void *env) {
1156   if (is_Block(n)) return;
1157   dump_node_wo_blockedge(n, env);
1158 }
1159
1160 /***********************************************************************/
1161 /* the following routines dump the nodes/irgs bracketed to graphs.     */
1162 /***********************************************************************/
1163
1164 /** Dumps a constant expression as entity initializer, array bound ...
1165  */
1166 static void dump_const_expression(FILE *F, ir_node *value) {
1167   ir_graph *rem = current_ir_graph;
1168   int rem_dump_const_local = dump_const_local;
1169   dump_const_local = 0;
1170   current_ir_graph = get_const_code_irg();
1171   irg_walk(value, dump_const_node, NULL, F);
1172   /* Decrease visited flag so that we walk with the same flag for the next
1173      expression.  This guarantees that we don't dump the same node twice,
1174      as for const expressions cse is performed to save memory. */
1175   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1176   current_ir_graph = rem;
1177   dump_const_local = rem_dump_const_local;
1178 }
1179
1180 /** Dump a block as graph containing its nodes.
1181  *
1182  *  Expects to find nodes belonging to the block as list in its
1183  *  link field.
1184  *  Dumps the edges of all nodes including itself. */
1185 static void
1186 dump_whole_block(FILE *F, ir_node *block) {
1187   ir_node *node;
1188   assert(is_Block(block));
1189
1190   fprintf(F, "graph: { title: \"");
1191   PRINT_NODEID(block);
1192   fprintf(F, "\"  label: \"");
1193   dump_node_label(F, block);
1194 #if DO_HEAPANALYSIS
1195   if (get_opt_dump_abstvals())
1196     fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1197 #endif
1198   fprintf(F, "\" status:clustered color:%s \n",
1199        get_Block_matured(block) ? "yellow" : "red");
1200
1201   /* dump the blocks edges */
1202   dump_ir_data_edges(F, block);
1203
1204   /* dump the nodes that go into the block */
1205   for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1206     dump_node(F, node);
1207     dump_ir_data_edges(F, node);
1208   }
1209
1210   /* Close the vcg information for the block */
1211   fprintf(F, "}\n");
1212   dump_const_node_local(F, block);
1213 #if DO_HEAPANALYSIS
1214   dump_irn_chi_term(F, block);
1215 #endif
1216   fprintf(F, "\n");
1217 }
1218
1219 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1220  *  The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1221 static void
1222 dump_block_graph(FILE *F, ir_graph *irg) {
1223   int i;
1224   ir_graph *rem = current_ir_graph;
1225   ir_node **arr = ird_get_irg_link(irg);
1226   current_ir_graph = irg;
1227
1228   for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1229     ir_node * node = arr[i];
1230     if (is_Block(node)) {
1231       /* Dumps the block and all the nodes in the block, which are to
1232          be found in Block->link. */
1233       dump_whole_block(F, node);
1234     } else {
1235       /* Nodes that are not in a Block. */
1236       dump_node(F, node);
1237       if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1238         dump_const_block_local(F, node);
1239       }
1240       dump_ir_data_edges(F, node);
1241     }
1242   }
1243
1244   if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1245     dump_loop_nodes_into_graph(F, irg);
1246
1247   current_ir_graph = rem;
1248 }
1249
1250 /** Dumps an irg as a graph clustered by block nodes.
1251  *  If interprocedural view edges can point to nodes out of this graph.
1252  */
1253 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1254
1255   fprintf(F, "graph: { title: \"");
1256   PRINT_IRGID(irg);
1257   fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1258       get_ent_dump_name(get_irg_entity(irg)));
1259
1260   dump_block_graph(F, irg);
1261
1262   /* Close the vcg information for the irg */
1263   fprintf(F, "}\n\n");
1264 }
1265
1266 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1267  *  The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1268 static void
1269 dump_extblock_graph(FILE *F, ir_graph *irg) {
1270   int i;
1271   ir_graph *rem = current_ir_graph;
1272   ir_extblk **arr = ird_get_irg_link(irg);
1273   current_ir_graph = irg;
1274
1275   compute_extbb(irg);
1276   for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1277     ir_extblk *extbb = arr[i];
1278     ir_node *leader = extbb->blks[0];
1279     int j;
1280
1281     fprintf(F, "graph: { title: \"");
1282     PRINT_EXTBBID(leader);
1283     fprintf(F, "\"  label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1284             get_irn_node_nr(leader));
1285
1286     for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1287       ir_node * node = extbb->blks[j];
1288       if (is_Block(node)) {
1289         /* Dumps the block and all the nodes in the block, which are to
1290            be found in Block->link. */
1291         dump_whole_block(F, node);
1292       } else {
1293         /* Nodes that are not in a Block. */
1294         dump_node(F, node);
1295         if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1296           dump_const_block_local(F, node);
1297         }
1298         dump_ir_data_edges(F, node);
1299       }
1300     }
1301     fprintf(F, "}\n");
1302   }
1303
1304   if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1305     dump_loop_nodes_into_graph(F, irg);
1306
1307   current_ir_graph = rem;
1308   free_extbb(irg);
1309 }
1310
1311
1312 /*******************************************************************/
1313 /* Basic type and entity nodes and edges.                          */
1314 /*******************************************************************/
1315
1316 /** dumps the edges between nodes and their type or entity attributes. */
1317 static void dump_node2type_edges(ir_node *n, void *env)
1318 {
1319   FILE *F = env;
1320   assert(n);
1321
1322   switch (get_irn_opcode(n)) {
1323   case iro_Const :
1324     /* @@@ some consts have an entity */
1325     break;
1326   case iro_SymConst:
1327     if (   (get_SymConst_kind(n) ==symconst_type_tag)
1328        || (get_SymConst_kind(n) ==symconst_size))
1329       {
1330         print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1331       }
1332     break;
1333   case iro_Sel: {
1334       print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1335     } break;
1336   case iro_Call: {
1337       print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1338     } break;
1339   case iro_Alloc: {
1340       print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1341     } break;
1342   case iro_Free: {
1343       print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1344     } break;
1345   case iro_Cast: {
1346       print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1347     } break;
1348   default:
1349     break;
1350   }
1351 }
1352
1353 #if 0
1354 static int print_type_info(FILE *F, type *tp) {
1355   int bad = 0;
1356
1357   if (get_type_state(tp) == layout_undefined) {
1358     fprintf(F, "state: layout_undefined\n");
1359   } else {
1360     fprintf(F, "state: layout_fixed,\n");
1361   }
1362   if (get_type_mode(tp))
1363     fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1364   fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1365
1366   return bad;
1367 }
1368
1369 static void print_typespecific_info(FILE *F, type *tp) {
1370   switch (get_type_tpop_code(tp)) {
1371   case tpo_class:
1372     {
1373       fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1374     } break;
1375   case tpo_struct:
1376     {
1377     } break;
1378   case tpo_method:
1379     {
1380       fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1381       fprintf(F, "params: %d\n", get_method_n_params(tp));
1382       fprintf(F, "results: %d\n", get_method_n_ress(tp));
1383     } break;
1384   case tpo_union:
1385     {
1386     } break;
1387   case tpo_array:
1388     {
1389     } break;
1390   case tpo_enumeration:
1391     {
1392     } break;
1393   case tpo_pointer:
1394     {
1395     } break;
1396   case tpo_primitive:
1397     {
1398     } break;
1399   default: break;
1400   } /* switch type */
1401 }
1402 #endif
1403
1404 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1405   switch (get_type_tpop_code(tp)) {
1406   case tpo_class:
1407     {
1408       if (peculiarity_existent == get_class_peculiarity(tp))
1409     fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1410       else
1411     fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1412     } break;
1413   case tpo_struct:
1414     {
1415       fprintf (F, " " TYPE_METH_NODE_ATTR);
1416     } break;
1417   case tpo_method:
1418     {
1419     } break;
1420   case tpo_union:
1421     {
1422     } break;
1423   case tpo_array:
1424     {
1425     } break;
1426   case tpo_enumeration:
1427     {
1428     } break;
1429   case tpo_pointer:
1430     {
1431     } break;
1432   case tpo_primitive:
1433     {
1434     } break;
1435   default: break;
1436   } /* switch type */
1437 }
1438
1439
1440 /* Why not dump_type_node as the others? */
1441 static int print_type_node(FILE *F, type *tp)
1442 {
1443   int bad = 0;
1444
1445   fprintf (F, "node: {title: ");
1446   PRINT_TYPEID(tp);
1447   fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1448   fprintf (F, " info1: \"");
1449 #if 0
1450   bad |= print_type_info(F, tp);
1451   print_typespecific_info(F, tp);
1452 #else
1453   dump_type_to_file(F, tp, dump_verbosity_max);
1454 #endif
1455   fprintf (F, "\"");
1456   print_typespecific_vcgattr(F, tp);
1457   fprintf (F, "}\n");
1458
1459   return bad;
1460 }
1461
1462 int dump_type_node(FILE *F, type *tp) {
1463   return print_type_node(F, tp);
1464 }
1465
1466
1467 #define X(a)    case a: fprintf(F, #a); break
1468 void dump_entity_node(FILE *F, entity *ent, int color)
1469 {
1470   fprintf (F, "node: {title: \"");
1471   PRINT_ENTID(ent); fprintf(F, "\"");
1472   fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1473   fprintf (F, "label: ");
1474   fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1475   if (color)
1476     fprintf(F, "color: %d", color);
1477   else
1478     fprintf (F, ENTITY_NODE_ATTR);
1479   fprintf (F, "\n info1: \"");
1480
1481   dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1482
1483   fprintf(F, "\"\n}\n");
1484 }
1485 #undef X
1486
1487 static void dump_enum_item(FILE *F, type *tp, int pos)
1488 {
1489   char buf[1024];
1490   ident *id  = get_enumeration_nameid(tp, pos);
1491   tarval *tv = get_enumeration_enum(tp, pos);
1492
1493   tarval_snprintf(buf, sizeof(buf), tv);
1494   fprintf (F, "node: {title: \"");
1495   PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1496   fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1497   fprintf (F, "label: ");
1498   fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1499   fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1500 }
1501
1502 /* dumps a type or entity and it's edges. */
1503 static void
1504 dump_type_info(type_or_ent *tore, void *env) {
1505   FILE *F = env;
1506   int i = 0;  /* to shutup gcc */
1507
1508   /* dump this type or entity */
1509
1510   switch (get_kind(tore)) {
1511   case k_entity:
1512     {
1513       entity *ent = (entity *)tore;
1514       ir_node *value;
1515       /* The node */
1516       dump_entity_node(F, ent, 0);
1517       /* The Edges */
1518       /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
1519       fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1520                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1521       print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1522       if (is_Class_type(get_entity_owner(ent))) {
1523         for(i = 0; i < get_entity_n_overwrites(ent); i++)
1524           print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1525       }
1526       /* attached subgraphs */
1527       if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1528         if (is_atomic_entity(ent)) {
1529           value = get_atomic_ent_value(ent);
1530           if (value) {
1531             print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1532             /* DDMN(value);  $$$ */
1533             dump_const_expression(F, value);
1534           }
1535         }
1536         if (is_compound_entity(ent)) {
1537           for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1538             value = get_compound_ent_value(ent, i);
1539             if (value) {
1540               print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1541               dump_const_expression(F, value);
1542               print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1543               /*
1544               fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1545               ENT_CORR_EDGE_ATTR  "}\n", GET_ENTID(ent),
1546               get_compound_ent_value_member(ent, i), i);
1547               */
1548             }
1549           }
1550         }
1551       }
1552     } break;
1553   case k_type:
1554     {
1555       type *tp = (type *)tore;
1556       print_type_node(F, tp);
1557       /* and now the edges */
1558       switch (get_type_tpop_code(tp)) {
1559       case tpo_class:
1560         {
1561           for (i=0; i < get_class_n_supertypes(tp); i++)
1562             print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1563           for (i=0; i < get_class_n_members(tp); i++)
1564             print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1565         } break;
1566       case tpo_struct:
1567         {
1568           for (i=0; i < get_struct_n_members(tp); i++)
1569             print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1570         } break;
1571       case tpo_method:
1572         {
1573           for (i = 0; i < get_method_n_params(tp); i++)
1574             print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1575           for (i = 0; i < get_method_n_ress(tp); i++)
1576             print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1577         } break;
1578       case tpo_union:
1579         {
1580           for (i = 0; i < get_union_n_members(tp); i++)
1581             print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1582         } break;
1583       case tpo_array:
1584         {
1585           print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1586           print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1587           for (i = 0; i < get_array_n_dimensions(tp); i++) {
1588             ir_node *upper = get_array_upper_bound(tp, i);
1589             ir_node *lower = get_array_lower_bound(tp, i);
1590             print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1591             print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1592             dump_const_expression(F, upper);
1593             dump_const_expression(F, lower);
1594           }
1595
1596         } break;
1597       case tpo_enumeration:
1598         {
1599           for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1600             dump_enum_item(F, tp, i);
1601             print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1602           }
1603         } break;
1604       case tpo_pointer:
1605         {
1606           print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1607         } break;
1608       case tpo_primitive:
1609         {
1610         } break;
1611       default: break;
1612       } /* switch type */
1613     }
1614     break; /* case k_type */
1615   default:
1616     {
1617       printf(" *** irdump,  dump_type_info(l.%i), faulty type.\n", __LINE__);
1618     } break;
1619   } /* switch kind_or_entity */
1620 }
1621
1622 typedef struct _h_env {
1623   int dump_ent;
1624   FILE *f;
1625 } h_env_t;
1626
1627 /** For dumping class hierarchies.
1628  * Dumps a class type node and a superclass edge.
1629  * If env->dump_ent dumps entities of classes and overwrites edges.
1630  */
1631 static void
1632 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1633   h_env_t *env = ctx;
1634   FILE *F = env->f;
1635   int i = 0;  /* to shutup gcc */
1636
1637   /* dump this type or entity */
1638   switch (get_kind(tore)) {
1639   case k_entity: {
1640     entity *ent = (entity *)tore;
1641     if (get_entity_owner(ent) == get_glob_type()) break;
1642     if (!is_Method_type(get_entity_type(ent))) break;  /* GL */
1643     if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1644       /* The node */
1645       dump_entity_node(F, ent, 0);
1646       /* The edges */
1647       print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1648       for(i = 0; i < get_entity_n_overwrites(ent); i++)
1649         print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1650     }
1651   } break; /* case k_entity */
1652   case k_type:
1653     {
1654       type *tp = (type *)tore;
1655       if (tp == get_glob_type()) break;
1656       switch (get_type_tpop_code(tp)) {
1657         case tpo_class: {
1658           print_type_node(F, tp);
1659           /* and now the edges */
1660           for (i=0; i < get_class_n_supertypes(tp); i++)
1661           {
1662               print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1663           }
1664         } break;
1665         default: break;
1666       } /* switch type */
1667     }
1668     break; /* case k_type */
1669   default:
1670     {
1671       printf(" *** irdump,  dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1672     } break;
1673   } /* switch kind_or_entity */
1674 }
1675
1676 /*******************************************************************/
1677 /* dump analysis information that is expressed in graph terms.     */
1678 /*******************************************************************/
1679
1680 /* dump out edges */
1681 static void
1682 dump_out_edge(ir_node *n, void *env) {
1683   FILE *F = env;
1684   int i;
1685   for (i = 0; i < get_irn_n_outs(n); i++) {
1686     assert(get_irn_out(n, i));
1687     fprintf (F, "edge: {sourcename: \"");
1688     PRINT_NODEID(n);
1689     fprintf (F, "\" targetname: \"");
1690     PRINT_NODEID(get_irn_out(n, i));
1691     fprintf (F, "\" color: red linestyle: dashed");
1692     fprintf (F, "}\n");
1693   }
1694 }
1695
1696 static INLINE void
1697 dump_loop_label(FILE *F, ir_loop *loop) {
1698   fprintf (F, "loop %d, %d sons, %d nodes",
1699        get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1700 }
1701
1702 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1703   fprintf (F, " info1: \"");
1704   fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1705 #if DEBUG_libfirm   /* GL @@@ debug analyses */
1706   fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1707 #endif
1708   fprintf (F, "\"");
1709 }
1710
1711 static INLINE void
1712 dump_loop_node(FILE *F, ir_loop *loop) {
1713   fprintf (F, "node: {title: \"");
1714   PRINT_LOOPID(loop);
1715   fprintf (F, "\" label: \"");
1716   dump_loop_label(F, loop);
1717   fprintf (F, "\" ");
1718   dump_loop_info(F, loop);
1719   fprintf (F, "}\n");
1720
1721 }
1722
1723 static INLINE void
1724 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1725   assert(loop);
1726   fprintf (F, "edge: {sourcename: \"");
1727   PRINT_LOOPID(loop);
1728   fprintf (F, "\" targetname: \"");
1729   PRINT_NODEID(get_loop_node(loop, i));
1730   fprintf (F, "\" color: green");
1731   fprintf (F, "}\n");
1732 }
1733
1734 static INLINE void
1735 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1736   assert(loop);
1737   fprintf (F, "edge: {sourcename: \"");
1738   PRINT_LOOPID(loop);
1739   fprintf (F, "\" targetname: \"");
1740   PRINT_LOOPID(get_loop_son(loop, i));
1741   fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1742        get_loop_element_pos(loop, get_loop_son(loop, i)));
1743 }
1744
1745 static
1746 void dump_loops(FILE *F, ir_loop *loop) {
1747   int i;
1748   /* dump this loop node */
1749   dump_loop_node(F, loop);
1750
1751   /* dump edges to nodes in loop -- only if it is a real loop */
1752   if (get_loop_depth(loop) != 0) {
1753     for (i = 0; i < get_loop_n_nodes(loop); i++) {
1754       dump_loop_node_edge(F, loop, i);
1755     }
1756   }
1757   for (i = 0; i < get_loop_n_sons(loop); i++) {
1758     dump_loops(F, get_loop_son(loop, i));
1759     dump_loop_son_edge(F, loop, i);
1760   }
1761 }
1762
1763 static INLINE
1764 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1765   ir_graph *rem = current_ir_graph;
1766   current_ir_graph = irg;
1767
1768   if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1769
1770   current_ir_graph = rem;
1771 }
1772
1773
1774 /**
1775  * dumps the VCG header
1776  */
1777 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1778   char *label;
1779
1780   if (edge_label) {
1781     label = "yes";
1782   } else {
1783     label = "no";
1784   }
1785
1786   if (!orientation) orientation = "bottom_to_top";
1787
1788   /* print header */
1789   fprintf (F,
1790        "graph: { title: \"ir graph of %s\"\n"
1791        "display_edge_labels: %s\n"
1792        "layoutalgorithm: mindepth\n"
1793        "manhattan_edges: yes\n"
1794        "port_sharing: no\n"
1795        "orientation: %s\n"
1796        "classname 1:  \"intrablock Data\"\n"
1797        "classname 16: \"interblock Data\"\n"
1798        "classname 2:  \"Block\"\n"
1799        "classname 13: \"Control Flow\"\n"
1800        "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1801        "classname 14: \"intrablock Memory\"\n"
1802        "classname 17: \"interblock Memory\"\n"
1803        "classname 15: \"Dominators\"\n"
1804        "classname 3:  \"Entity type\"\n"
1805        "classname 4:  \"Entity owner\"\n"
1806        "classname 5:  \"Method Param\"\n"
1807        "classname 6:  \"Method Res\"\n"
1808        "classname 7:  \"Super\"\n"
1809        "classname 8:  \"Union\"\n"
1810        "classname 9:  \"Points-to\"\n"
1811        "classname 10: \"Array Element Type\"\n"
1812        "classname 11: \"Overwrites\"\n"
1813        "classname 12: \"Member\"\n"
1814        "infoname 1: \"Attribute\"\n"
1815        "infoname 2: \"Verification errors\"\n",
1816        name, label, orientation);
1817
1818   /* don't use all, the range is too whith/black. */
1819   n_colors   = 18;
1820   base_color = 105;
1821   fprintf (F,
1822        "colorentry 100:    0   0    0\n"
1823        "colorentry 101:   20   0    0\n"
1824        "colorentry 102:   40   0    0\n"
1825        "colorentry 103:   60   0    0\n"
1826        "colorentry 104:   80   0    0\n"
1827        "colorentry 105:  100   0    0\n"
1828        "colorentry 106:  120   0    0\n"
1829        "colorentry 107:  140   0    0\n"
1830        "colorentry 108:  150   0    0\n"
1831        "colorentry 109:  180   0    0\n"
1832        "colorentry 110:  200   0    0\n"
1833        "colorentry 111:  220   0    0\n"
1834        "colorentry 112:  240   0    0\n"
1835        "colorentry 113:  255   0    0\n"
1836        "colorentry 113:  255  20   20\n"
1837        "colorentry 114:  255  40   40\n"
1838        "colorentry 115:  255  60   60\n"
1839        "colorentry 116:  255  80   80\n"
1840        "colorentry 117:  255 100  100\n"
1841        "colorentry 118:  255 120  120\n"
1842        "colorentry 119:  255 140  140\n"
1843        "colorentry 120:  255 150  150\n"
1844        "colorentry 121:  255 180  180\n"
1845        "colorentry 122:  255 200  200\n"
1846        "colorentry 123:  255 220  220\n"
1847        "colorentry 124:  255 240  240\n"
1848        "colorentry 125:  255 250  250\n"
1849        );
1850
1851   fprintf (F, "\n");        /* a separator */
1852 }
1853
1854 /**
1855  * open a vcg file
1856  *
1857  * @param irg     The graph to be dumped
1858  * @param suffix1 first filename suffix
1859  * @param suffix2 second filename suffix
1860  */
1861 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1862   FILE *F;
1863   const char *nm = get_irg_dump_name(irg);
1864   int len = strlen(nm), i, j;
1865   char *fname;  /* filename to put the vcg information in */
1866
1867   if (!suffix1) suffix1 = "";
1868   if (!suffix2) suffix2 = "";
1869
1870   /* open file for vcg graph */
1871   fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1872
1873   /* strncpy (fname, nm, len); */     /* copy the filename */
1874   j = 0;
1875   for (i = 0; i < len; ++i) {  /* replace '/' in the name: escape by @. */
1876     if (nm[i] == '/') {
1877       fname[j] = '@'; j++; fname[j] = '1'; j++;
1878     } else if (nm[i] == '@') {
1879       fname[j] = '@'; j++; fname[j] = '2'; j++;
1880     } else {
1881       fname[j] = nm[i]; j++;
1882     }
1883   }
1884   fname[j] = '\0';
1885   strcat (fname, suffix1);  /* append file suffix */
1886   strcat (fname, suffix2);  /* append file suffix */
1887   strcat (fname, ".vcg");   /* append the .vcg suffix */
1888
1889   /* vcg really expect only a <CR> at end of line, so
1890    * the "b"inary mode is what you mean (and even needed for Win32)
1891    */
1892   F = fopen (fname, "wb");  /* open file for writing */
1893   if (!F) {
1894     panic("cannot open %s for writing (%m)", fname);  /* not reached */
1895   }
1896   free(fname);
1897
1898   return F;
1899 }
1900
1901 /**
1902  * open a vcg file
1903  *
1904  * @param irg     The graph to be dumped
1905  * @param suffix  filename suffix
1906  */
1907 FILE *vcg_open_name (const char *name, const char *suffix) {
1908   FILE *F;
1909   char *fname;  /* filename to put the vcg information in */
1910   int i, j, len = strlen(name);
1911
1912   if (!suffix) suffix = "";
1913
1914   /** open file for vcg graph */
1915   fname = malloc (len * 2 + 5 + strlen(suffix));
1916   /* strcpy (fname, name);*/    /* copy the filename */
1917   j = 0;
1918   for (i = 0; i < len; ++i) {  /* replace '/' in the name: escape by @. */
1919     if (name[i] == '/') {
1920       fname[j] = '@'; j++; fname[j] = '1'; j++;
1921     } else if (name[i] == '@') {
1922       fname[j] = '@'; j++; fname[j] = '2'; j++;
1923     } else {
1924       fname[j] = name[i]; j++;
1925     }
1926   }
1927   fname[j] = '\0';
1928   strcat (fname, suffix);
1929   strcat (fname, ".vcg");  /* append the .vcg suffix */
1930
1931   /* vcg really expect only a <CR> at end of line, so
1932    * the "b"inary mode is what you mean (and even needed for Win32)
1933    */
1934   F = fopen (fname, "wb");  /* open file for writing */
1935   if (!F) {
1936     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
1937   }
1938   free(fname);
1939
1940   return F;
1941 }
1942
1943 /**
1944  * Dumps the vcg file footer
1945  */
1946 static INLINE void dump_vcg_footer (FILE *F) {
1947   fprintf (F, "}\n");
1948 }
1949
1950 /**
1951  * close the vcg file
1952  */
1953 void vcg_close (FILE *F) {
1954   dump_vcg_footer(F);    /* print footer */
1955   fclose (F);           /* close vcg file */
1956 }
1957
1958 /************************************************************************/
1959 /************************************************************************/
1960 /* Routines that dump all or parts of the firm representation to a file */
1961 /************************************************************************/
1962 /************************************************************************/
1963
1964 /************************************************************************/
1965 /* Dump ir graphs, different formats and additional information.        */
1966 /************************************************************************/
1967
1968 /** Routine to dump a graph, blocks as conventional nodes.  */
1969 void
1970 dump_ir_graph (ir_graph *irg, const char *suffix )
1971 {
1972   FILE *f;
1973   ir_graph *rem;
1974   char *suffix1;
1975   rem = current_ir_graph;
1976
1977   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
1978
1979   current_ir_graph = irg;
1980   if (get_interprocedural_view()) suffix1 = "-pure-ip";
1981   else                            suffix1 = "-pure";
1982   f = vcg_open(irg, suffix, suffix1);
1983   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1984
1985   /* walk over the graph */
1986   /* dump_whole_node must be called in post visiting predecessors */
1987   irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1988
1989   /* dump the out edges in a separate walk */
1990   if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1991     irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
1992   }
1993
1994   vcg_close(f);
1995
1996   current_ir_graph = rem;
1997 }
1998
1999 /* Dump a firm graph without explicit block nodes. */
2000 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2001 {
2002   FILE *f;
2003   int i;
2004   char *suffix1;
2005
2006   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2007     return;
2008
2009   if (get_interprocedural_view()) suffix1 = "-ip";
2010   else                            suffix1 = "";
2011   f = vcg_open(irg, suffix, suffix1);
2012   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2013
2014   construct_block_lists(irg);
2015
2016   /*
2017    * If we are in the interprocedural view, we dump not
2018    * only the requested irg but also all irgs that can be reached
2019    * from irg.
2020    */
2021   for (i = 0; i < get_irp_n_irgs(); i++) {
2022     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2023     if (arr) {
2024       dump_graph_from_list(f, get_irp_irg(i));
2025       DEL_ARR_F(arr);
2026     }
2027   }
2028
2029   vcg_close(f);
2030 }
2031
2032 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2033 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2034 {
2035   FILE *F;
2036   int i;
2037   char *suffix1;
2038
2039   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2040     return;
2041
2042   compute_extbb(irg);
2043
2044   if (get_interprocedural_view()) suffix1 = "-ip";
2045   else                            suffix1 = "";
2046   F = vcg_open(irg, suffix, suffix1);
2047   dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2048
2049   construct_extblock_lists(irg);
2050
2051   fprintf(F, "graph: { title: \"");
2052   PRINT_IRGID(irg);
2053   fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
2054     get_ent_dump_name(get_irg_entity(irg)));
2055
2056   for (i = 0; i < get_irp_n_irgs(); i++) {
2057     ir_graph *irg     = get_irp_irg(i);
2058     list_tuple *lists = ird_get_irg_link(irg);
2059
2060     if (lists) {
2061       /* dump the extended blocks first */
2062       if (ARR_LEN(lists->extbb_list)) {
2063         ird_set_irg_link(irg, lists->extbb_list);
2064         dump_extblock_graph(F, irg);
2065       }
2066
2067       /* we may have blocks without extended blocks, bad for instance */
2068       if (ARR_LEN(lists->blk_list)) {
2069         ird_set_irg_link(irg, lists->blk_list);
2070         dump_block_graph(F, irg);
2071       }
2072
2073       DEL_ARR_F(lists->extbb_list);
2074       DEL_ARR_F(lists->blk_list);
2075       xfree(lists);
2076     }
2077   }
2078
2079   /* Close the vcg information for the irg */
2080   fprintf(F, "}\n\n");
2081
2082   vcg_close(F);
2083   free_extbb(irg);
2084 }
2085
2086 /* dumps a graph with type information */
2087 void
2088 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2089 {
2090   FILE *f;
2091   ir_graph *rem = current_ir_graph;
2092   char *suffix1;
2093
2094   /* if a filter is set, dump only the irg's that match the filter */
2095   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2096     return;
2097
2098   current_ir_graph = irg;
2099
2100   if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2101   else                            suffix1 = "-pure-wtypes";
2102   f = vcg_open(irg,suffix, suffix1);
2103   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2104
2105   /* dump common ir graph */
2106   irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2107   /* dump type info */
2108   type_walk_irg(irg, dump_type_info, NULL, f);
2109   inc_irg_visited(get_const_code_irg());
2110   /* dump edges from graph to type info */
2111   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2112
2113   vcg_close(f);
2114   current_ir_graph = rem;
2115 }
2116
2117 void
2118 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2119 {
2120   FILE *f;
2121   int i;
2122   char *suffix1;
2123   ir_graph *rem = current_ir_graph;
2124
2125   /* if a filter is set, dump only the irg's that match the filter */
2126   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2127     return;
2128
2129   if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2130   else                            suffix1 = "-wtypes";
2131   f = vcg_open(irg, suffix, suffix1);
2132   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2133
2134   /* dump common blocked ir graph */
2135   construct_block_lists(irg);
2136
2137   for (i = 0; i < get_irp_n_irgs(); i++) {
2138     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2139     if (arr) {
2140       dump_graph_from_list(f, get_irp_irg(i));
2141       DEL_ARR_F(arr);
2142     }
2143   }
2144
2145   /* dump type info */
2146   current_ir_graph = irg;
2147   type_walk_irg(irg, dump_type_info, NULL, f);
2148   inc_irg_visited(get_const_code_irg());
2149
2150   /* dump edges from graph to type info */
2151   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2152
2153   current_ir_graph = rem;
2154   vcg_close(f);
2155 }
2156
2157 /*---------------------------------------------------------------------*/
2158 /* The following routines dump a control flow graph.                   */
2159 /*---------------------------------------------------------------------*/
2160
2161 static void
2162 dump_block_to_cfg(ir_node *block, void *env) {
2163   FILE *F = env;
2164   int i, fl;
2165   ir_node *pred;
2166
2167   if (is_Block(block)) {
2168     /* This is a block. Dump a node for the block. */
2169     fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2170     fprintf (F, "\" label: \"");
2171     if (block == get_irg_start_block(get_irn_irg(block)))
2172       fprintf(F, "Start ");
2173     if (block == get_irg_end_block(get_irn_irg(block)))
2174       fprintf(F, "End ");
2175
2176     fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2177     PRINT_NODEID(block);
2178     fprintf (F, "\" ");
2179     fprintf(F, "info1:\"");
2180
2181 #if 0
2182     if (dump_dominator_information_flag) {
2183       fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2184       fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block));
2185       fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block));
2186     }
2187
2188     /* show arity and possible Bad predecessors of the block */
2189     fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2190     for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2191       ir_node *pred = get_Block_cfgpred(block, i);
2192       if (is_Bad(pred)) {
2193         if (! fl)
2194           fprintf(F, "Bad pred at pos: ");
2195         fprintf(F, "%d ", i);
2196         fl = 1;
2197       }
2198     }
2199     if (fl)
2200       fprintf(F, "\n");
2201 #else
2202     /* the generic version. */
2203     dump_irnode_to_file(F, block);
2204
2205     /* Check whether we have bad predecessors to color the block. */
2206     for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2207       if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2208         break;
2209 #endif
2210
2211     fprintf (F, "\"");  /* closing quote of info */
2212
2213     if ((block == get_irg_start_block(get_irn_irg(block))) ||
2214     (block == get_irg_end_block(get_irn_irg(block)))     )
2215       fprintf(F, " color:blue ");
2216     else if (fl)
2217       fprintf(F, " color:yellow ");
2218
2219     fprintf (F, "}\n");
2220     /* Dump the edges */
2221     for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2222       if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2223         pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2224         fprintf (F, "edge: { sourcename: \"");
2225         PRINT_NODEID(block);
2226         fprintf (F, "\" targetname: \"");
2227         PRINT_NODEID(pred);
2228         fprintf (F, "\"}\n");
2229       }
2230
2231     /* Dump dominator edge */
2232     if (dump_dominator_information_flag && get_Block_idom(block)) {
2233       pred = get_Block_idom(block);
2234       fprintf (F, "edge: { sourcename: \"");
2235       PRINT_NODEID(block);
2236       fprintf (F, "\" targetname: \"");
2237       PRINT_NODEID(pred);
2238       fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2239     }
2240   }
2241 }
2242
2243 void
2244 dump_cfg (ir_graph *irg, const char *suffix)
2245 {
2246   FILE *f;
2247   ir_graph *rem = current_ir_graph;
2248   int ddif = dump_dominator_information_flag;
2249   int ipv = get_interprocedural_view();
2250
2251   /* if a filter is set, dump only the irg's that match the filter */
2252   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2253     return;
2254
2255   current_ir_graph = irg;
2256
2257   f = vcg_open(irg, suffix, "-cfg");
2258   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2259
2260   if (ipv) {
2261     printf("Warning: dumping cfg not in interprocedural view!\n");
2262     set_interprocedural_view(false);
2263   }
2264
2265   if (get_irg_dom_state(irg) != dom_consistent)
2266     dump_dominator_information_flag = 0;
2267
2268   /* walk over the blocks in the graph */
2269   irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2270   dump_node(f, get_irg_bad(irg));
2271
2272   dump_dominator_information_flag = ddif;
2273   set_interprocedural_view(ipv);
2274   vcg_close(f);
2275   current_ir_graph = rem;
2276 }
2277
2278
2279 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2280   if (pset_find_ptr(mark_set, n)) return;
2281
2282   pset_insert_ptr(mark_set, n);
2283
2284   if (depth > 0) {
2285     int i, start = is_Block(n) ? 0 : -1;
2286     dump_whole_node(n, F);
2287     for (i = start; i < get_irn_arity(n); ++i)
2288       descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2289   } else {
2290     dump_node(F, n);
2291     /* Don't dump edges to nodes further out.  These might be edges to
2292        nodes we already dumped, if there is a shorter path to these. */
2293   }
2294 }
2295
2296 static int subgraph_counter = 0;
2297 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2298   FILE *F;
2299   char buf[32];
2300   pset *mark_set = pset_new_ptr(1);
2301   sprintf(buf, "-subg_%03d", subgraph_counter++);
2302   F = vcg_open(get_irn_irg(root), suffix, buf);
2303   dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2304   descend_and_dump(F, root, depth, mark_set);
2305   vcg_close(F);
2306   del_pset(mark_set);
2307 }
2308
2309
2310 static int weight_overall(int rec, int loop) {
2311   return 2*rec + loop;
2312 }
2313
2314 static int compute_color (int my, int max) {
2315   int color;
2316   if (!max) {
2317     color = 0;
2318   } else {
2319     int step;
2320
2321     /* if small, scale to the full color range. */
2322     if (max < n_colors)
2323       my = my * (n_colors/max);
2324
2325     step = 1 + (max / n_colors);
2326
2327     color = my/step;
2328   }
2329   return base_color + n_colors - color;
2330 }
2331
2332 static int get_entity_color(entity *ent) {
2333   ir_graph *irg = get_entity_irg(ent);
2334   assert(irg);
2335
2336   {
2337     int rec_depth     = get_irg_recursion_depth(irg);
2338     int loop_depth    = get_irg_loop_depth(irg);
2339     int overall_depth = weight_overall(rec_depth, loop_depth);
2340
2341     int max_rec_depth     = irp->max_callgraph_recursion_depth;
2342     int max_loop_depth    = irp->max_callgraph_loop_depth;
2343     int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2344
2345     /* int my_rec_color     = compute_color(rec_depth, max_rec_depth); */
2346     /* int my_loop_color    = compute_color(loop_depth, max_loop_depth); */
2347     int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2348
2349     return my_overall_color;
2350   }
2351 }
2352
2353 void dump_callgraph(const char *suffix) {
2354   FILE *F;
2355   int i, n_irgs = get_irp_n_irgs();
2356   int rem = edge_label;
2357   edge_label = 1;
2358   //ident *prefix = new_id_from_str("java/");
2359
2360   F = vcg_open_name("Callgraph", suffix);
2361   dump_vcg_header(F, "Callgraph", NULL);
2362
2363   for (i = 0; i < n_irgs; ++i) {
2364     ir_graph *irg = get_irp_irg(i);
2365     entity *ent = get_irg_entity(irg);
2366     int j, n_callees = get_irg_n_callees(irg);
2367
2368     /* Do not dump runtime system. */
2369     //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2370
2371     dump_entity_node(F, ent, get_entity_color(ent));
2372     for (j = 0; j < n_callees; ++j) {
2373       entity *c = get_irg_entity(get_irg_callee(irg, j));
2374       //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2375       int be = is_irg_callee_backedge(irg, j);
2376       char *attr;
2377       attr = (be) ?
2378         "label:\"recursion %d\" color: %d" :
2379         "label:\"calls %d\" color: %d";
2380       print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2381     }
2382   }
2383
2384   edge_label = rem;
2385   vcg_close(F);
2386 }
2387
2388 /* Dump all irgs in interprocedural view to a single file. */
2389 void dump_all_cg_block_graph(const char *suffix) {
2390   FILE *f;
2391   int i;
2392   int rem_view = get_interprocedural_view();
2393   set_interprocedural_view(true);
2394
2395   f = vcg_open_name("All_graphs", suffix);
2396   dump_vcg_header(f, "All_graphs", NULL);
2397
2398   /* collect nodes in all irgs reachable in call graph*/
2399   for (i = 0; i < get_irp_n_irgs(); i++)
2400     ird_set_irg_link(get_irp_irg(i), NULL);
2401
2402   cg_walk(clear_link, collect_node, NULL);
2403
2404   /* dump all graphs */
2405   for (i = 0; i < get_irp_n_irgs(); i++) {
2406     current_ir_graph = get_irp_irg(i);
2407     assert(ird_get_irg_link(current_ir_graph));
2408     dump_graph_from_list(f, current_ir_graph);
2409     DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2410   }
2411
2412   vcg_close(f);
2413   set_interprocedural_view(rem_view);
2414 }
2415
2416 /*---------------------------------------------------------------------*/
2417 /* the following routines dumps type information without any ir nodes. */
2418 /*---------------------------------------------------------------------*/
2419
2420 void
2421 dump_type_graph (ir_graph *irg, const char *suffix)
2422 {
2423   FILE *f;
2424   ir_graph *rem;
2425   rem = current_ir_graph;
2426
2427   /* if a filter is set, dump only the irg's that match the filter */
2428   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2429
2430   current_ir_graph = irg;
2431
2432   f = vcg_open(irg, suffix, "-type");
2433   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2434
2435   /* walk over the blocks in the graph */
2436   type_walk_irg(irg, dump_type_info, NULL, f);
2437   /* The walker for the const code can be called several times for the
2438      same (sub) expression.  So that no nodes are dumped several times
2439      we decrease the visited flag of the corresponding graph after each
2440      walk.  So now increase it finally. */
2441   inc_irg_visited(get_const_code_irg());
2442
2443   vcg_close(f);
2444   current_ir_graph = rem;
2445 }
2446
2447 void
2448 dump_all_types (const char *suffix)
2449 {
2450   FILE *f = vcg_open_name("All_types", suffix);
2451   dump_vcg_header(f, "All_types", NULL);
2452   type_walk(dump_type_info, NULL, f);
2453   inc_irg_visited(get_const_code_irg());
2454   vcg_close(f);
2455 }
2456
2457 void
2458 dump_class_hierarchy (bool entities, const char *suffix)
2459 {
2460   FILE *f = vcg_open_name("class_hierarchy", suffix);
2461   h_env_t env;
2462
2463   env.f = f;
2464   dump_vcg_header(f, "class_hierarchy", NULL);
2465   if (entities)
2466     env.dump_ent = 1;
2467   else
2468     env.dump_ent = 0;
2469   type_walk(dump_class_hierarchy_node, NULL, &env);
2470   vcg_close(f);
2471 }
2472
2473 /*---------------------------------------------------------------------*/
2474 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
2475 /*  dump_ir_graph                                                      */
2476 /*  dump_ir_block_graph                                                */
2477 /*  dump_cfg                                                           */
2478 /*  dump_type_graph                                                    */
2479 /*  dump_ir_graph_w_types                                              */
2480 /*---------------------------------------------------------------------*/
2481
2482 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2483   int i, n_irgs = get_irp_n_irgs();
2484   for (i = 0; i < n_irgs; ++i) {
2485     dmp_grph(get_irp_irg(i), suffix);
2486   }
2487 }
2488
2489
2490 /*--------------------------------------------------------------------------------*
2491  * Dumps a stand alone loop graph with firm nodes which belong to one loop node   *
2492  * packed together in one subgraph/box                                            *
2493  *--------------------------------------------------------------------------------*/
2494
2495 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2496   int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2497   loop_element le;
2498   ir_loop *son = NULL;
2499
2500   /* Dump a new loop node. */
2501   dump_loop_node(F, loop);
2502
2503   /* Dump the loop elements. */
2504
2505   for(i = 0; i < get_loop_n_elements(loop); i++) {
2506     le = get_loop_element(loop, i);
2507     son = le.son;
2508     if (get_kind(son) == k_ir_loop) {
2509
2510       /* We are a loop son -> Recurse */
2511
2512       if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2513         fprintf(F, "\" }\n");
2514         fprintf (F, "edge: {sourcename: \"");
2515         PRINT_LOOPID(loop);
2516         fprintf (F, "\" targetname: \"");
2517         PRINT_LOOPID(loop);
2518         fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2519         loop_node_started = 0;
2520       }
2521       dump_loop_son_edge(F, loop, son_number++);
2522       dump_loops_standalone(F, son);
2523     } else if (get_kind(son) == k_ir_node) {
2524       /* We are a loop node -> Collect firm nodes */
2525
2526       ir_node *n = le.node;
2527       int bad = 0;
2528
2529       if (!loop_node_started) {
2530         /* Start a new node which contains all firm nodes of the current loop */
2531         fprintf (F, "node: { title: \"");
2532         PRINT_LOOPID(loop);
2533         fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2534         loop_node_started = 1;
2535         first = i;
2536       }
2537       else
2538         fprintf(F, "\n");
2539
2540       bad |= dump_node_label(F, n);
2541       /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2542       if (has_backedges(n)) fprintf(F, "\t loop head!");
2543     } else { /* for callgraph loop tree */
2544       ir_graph *n;
2545       assert(get_kind(son) == k_ir_graph);
2546
2547       /* We are a loop node -> Collect firm graphs */
2548       n = (ir_graph *)le.node;
2549       if (!loop_node_started) {
2550         /* Start a new node which contains all firm nodes of the current loop */
2551         fprintf (F, "node: { title: \"");
2552         PRINT_LOOPID(loop);
2553         fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2554         loop_node_started = 1;
2555         first = i;
2556       }
2557       else
2558         fprintf(F, "\n");
2559       fprintf (F, " %s", get_irg_dump_name(n));
2560       /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2561     }
2562   }
2563
2564   if (loop_node_started) {
2565     fprintf(F, "\" }\n");
2566     fprintf (F, "edge: {sourcename: \"");
2567     PRINT_LOOPID(loop);
2568     fprintf (F, "\" targetname: \"");
2569     PRINT_LOOPID(loop);
2570     fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2571     loop_node_started = 0;
2572   }
2573 }
2574
2575 void dump_loop_tree(ir_graph *irg, const char *suffix)
2576 {
2577   FILE *f;
2578   ir_graph *rem = current_ir_graph;
2579   int el_rem = edge_label;
2580   edge_label = 1;
2581
2582   /* if a filter is set, dump only the irg's that match the filter */
2583   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2584
2585   current_ir_graph = irg;
2586
2587   f = vcg_open(irg, suffix, "-looptree");
2588   dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2589
2590   if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2591
2592   vcg_close(f);
2593
2594   edge_label = el_rem;
2595   current_ir_graph = rem;
2596 }
2597
2598 void dump_callgraph_loop_tree(const char *suffix) {
2599   FILE *F;
2600   F = vcg_open_name("Callgraph_looptree", suffix);
2601   dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2602   dump_loops_standalone(F, irp->outermost_cg_loop);
2603   vcg_close(F);
2604 }
2605
2606
2607 /*-----------------------------------------------------------------------------*/
2608 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2609 /*-----------------------------------------------------------------------------*/
2610
2611 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2612   int i, son_number = 0, node_number = 0;
2613
2614   if (dump_loop_information_flag) dump_loop_node(F, loop);
2615
2616   for (i = 0; i < get_loop_n_elements(loop); i++) {
2617     loop_element le = get_loop_element(loop, i);
2618     if (*(le.kind) == k_ir_loop) {
2619       if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2620       /* Recur */
2621       collect_nodeloop(F, le.son, loopnodes);
2622     } else {
2623       if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2624       eset_insert(loopnodes, le.node);
2625     }
2626   }
2627 }
2628
2629 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2630   int i, j, start;
2631
2632   for(i = 0; i < get_loop_n_elements(loop); i++) {
2633     loop_element le = get_loop_element(loop, i);
2634     if (*(le.kind) == k_ir_loop) {
2635       /* Recur */
2636       collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2637     } else {
2638       if (is_Block(le.node)) start = 0; else start = -1;
2639       for (j = start; j < get_irn_arity(le.node); j++) {
2640         ir_node *pred = get_irn_n(le.node, j);
2641         if (!eset_contains(loopnodes, pred)) {
2642           eset_insert(extnodes, pred);
2643           if (!is_Block(pred)) {
2644             pred = get_nodes_block(pred);
2645             if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2646           }
2647         }
2648       }
2649     }
2650   }
2651 }
2652
2653 void dump_loop(ir_loop *l, const char *suffix) {
2654   FILE *F;
2655   char name[50];
2656   eset *loopnodes = eset_create();
2657   eset *extnodes = eset_create();
2658   ir_node *n, *b;
2659
2660   snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2661   F = vcg_open_name (name, suffix);
2662   dump_vcg_header(F, name, NULL);
2663
2664   /* collect all nodes to dump */
2665   collect_nodeloop(F, l, loopnodes);
2666   collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2667
2668   /* build block lists */
2669   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2670     set_irn_link(n, NULL);
2671   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2672     set_irn_link(n, NULL);
2673   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2674     if (!is_Block(n)) {
2675       b = get_nodes_block(n);
2676       set_irn_link(n, get_irn_link(b));
2677       set_irn_link(b, n);
2678     }
2679   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2680     if (!is_Block(n)) {
2681       b = get_nodes_block(n);
2682       set_irn_link(n, get_irn_link(b));
2683       set_irn_link(b, n);
2684     }
2685
2686   for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2687     if (is_Block(b)) {
2688       fprintf(F, "graph: { title: \"");
2689       PRINT_NODEID(b);
2690       fprintf(F, "\"  label: \"");
2691       dump_node_opcode(F, b);
2692       fprintf (F, " %ld", get_irn_node_nr(b));
2693       fprintf(F, "\" status:clustered color:yellow\n");
2694
2695       /* dump the blocks edges */
2696       dump_ir_data_edges(F, b);
2697
2698       /* dump the nodes that go into the block */
2699       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2700         if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2701         dump_node(F, n);
2702         overrule_nodecolor = NULL;
2703         if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2704       }
2705
2706       /* Close the vcg information for the block */
2707       fprintf(F, "}\n");
2708       dump_const_node_local(F, b);
2709       fprintf(F, "\n");
2710     }
2711   for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2712     if (is_Block(b)) {
2713       fprintf(F, "graph: { title: \"");
2714       PRINT_NODEID(b);
2715       fprintf(F, "\"  label: \"");
2716       dump_node_opcode(F, b);
2717       fprintf (F, " %ld", get_irn_node_nr(b));
2718       fprintf(F, "\" status:clustered color:lightblue\n");
2719
2720       /* dump the nodes that go into the block */
2721       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2722         if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2723         dump_node(F, n);
2724         overrule_nodecolor = NULL;
2725         if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2726       }
2727
2728       /* Close the vcg information for the block */
2729       fprintf(F, "}\n");
2730       dump_const_node_local(F, b);
2731       fprintf(F, "\n");
2732     }
2733
2734   eset_destroy(loopnodes);
2735   eset_destroy(extnodes);
2736   vcg_close(F);
2737 }