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