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