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