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