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