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