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