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