7178dc09aff8ddb9e28123c8db2f1b5c4df288e0
[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 #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 set_opt_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) == ir_typeinfo_consistent  ||
612         get_irg_typeinfo_state(current_ir_graph) == ir_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 a node label without the enclosing ". */
666 static int dump_node_label(FILE *F, ir_node *n) {
667   int bad = 0;
668
669   bad |= dump_node_opcode(F, n);
670   bad |= dump_node_mode(F, n);
671   fprintf (F, " ");
672   bad |= dump_node_typeinfo(F, n);
673   bad |= dump_node_nodeattr(F, n);
674   fprintf(F, "%ld", get_irn_node_nr(n));
675
676   return bad;
677 }
678
679
680 /**
681  * Dumps the attributes of a node n into the file F.
682  * Currently this is only the color of a node.
683  */
684 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
685 {
686   ir_node *n;
687
688   if (bad) {
689     fprintf(F, "color: red");
690     return;
691   }
692
693   if (dump_node_vcgattr_hook)
694     if (dump_node_vcgattr_hook(F, node, local))
695       return;
696
697   n = local ? local : node;
698
699   switch (get_irn_opcode(n)) {
700   case iro_Start:
701   case iro_EndReg:
702     /* fall through */
703   case iro_EndExcept:
704     /* fall through */
705   case iro_End:
706     fprintf (F, "color: blue");
707     break;
708   case iro_Block:
709     if (is_Block_dead(n))
710       fprintf (F, "color: lightred");
711     else
712       fprintf (F, "color: lightyellow");
713     break;
714   case iro_Phi:
715     fprintf (F, "color: green");
716     break;
717   case iro_Const:
718   case iro_Proj:
719   case iro_Filter:
720   case iro_Tuple:
721     fprintf (F, "color: yellow");
722     break;
723   default:
724     PRINT_DEFAULT_NODE_ATTR;
725   }
726
727   if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
728 }
729
730
731 /**
732  * Dump the node information of a node n to a file F.
733  */
734 static INLINE int dump_node_info(FILE *F, ir_node *n)
735 { int bad = 0;
736   fprintf (F, " info1: \"");
737   bad = dump_irnode_to_file(F, n);
738   fprintf(F, "\"\n");
739   return bad;
740 }
741
742 /**
743  * checks wheater a node is "constant-like", ie can be treated "block-less"
744  */
745 static INLINE
746 bool is_constlike_node(ir_node *n) {
747   ir_op *op = get_irn_op(n);
748   return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
749 }
750
751
752 /** outputs the predecessors of n, that are constants, local.  I.e.,
753    generates a copy of the constant predecessors for each node called with. */
754 static void dump_const_node_local(FILE *F, ir_node *n) {
755   int i;
756   if (!get_opt_dump_const_local()) return;
757
758   /* Use visited flag to avoid outputting nodes twice.
759      initialize it first. */
760   for (i = 0; i < get_irn_arity(n); i++) {
761     ir_node *con = get_irn_n(n, i);
762     if (is_constlike_node(con)) {
763       set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
764     }
765   }
766
767   for (i = 0; i < get_irn_arity(n); i++) {
768     ir_node *con = get_irn_n(n, i);
769     if (is_constlike_node(con) && irn_not_visited(con)) {
770       int bad = 0;
771
772       mark_irn_visited(con);
773       /* Generate a new name for the node by appending the names of
774          n and const. */
775       fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
776       fprintf(F, " label: \"");
777       bad |= dump_node_label(F, con);
778       fprintf(F, "\" ");
779       bad |= dump_node_info(F, con);
780       dump_node_vcgattr(F, n, con, bad);
781       fprintf(F, "}\n");
782     }
783   }
784 }
785
786 /** If the block of an edge is a const_like node, dump it local with an edge */
787 static void dump_const_block_local(FILE *F, ir_node *n) {
788   ir_node *blk;
789
790   if (!get_opt_dump_const_local()) return;
791
792   blk = get_nodes_block(n);
793   if (is_constlike_node(blk)) {
794     int bad = 0;
795
796     /* Generate a new name for the node by appending the names of
797        n and blk. */
798     fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
799     fprintf(F, "\" label: \"");
800     bad |= dump_node_label(F, blk);
801     fprintf(F, "\" ");
802     bad |= dump_node_info(F, blk);
803     dump_node_vcgattr(F, n, blk, bad);
804     fprintf(F, "}\n");
805
806     fprintf (F, "edge: { sourcename: \"");
807     PRINT_NODEID(n);
808     fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
809     fprintf (F, "\" "   BLOCK_EDGE_ATTR "}\n");
810   }
811 }
812
813 /**
814  * prints the error message of a node to a file F as info2.
815  */
816 static void INLINE print_node_error(FILE *F, const char *err_msg)
817 {
818   if (! err_msg)
819     return;
820
821   fprintf (F, " info2: \"%s\"", err_msg);
822 }
823
824 /**
825  * Dump a node
826  */
827 static void dump_node(FILE *F, ir_node *n)
828 {
829   int bad = 0;
830   const char *p;
831
832   if (get_opt_dump_const_local() && is_constlike_node(n))
833     return;
834
835   /* dump this node */
836   fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
837
838   bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
839   bad |= dump_node_label(F, n);
840   dump_node_ana_info(F, n);
841   fprintf(F, "\" ");
842   bad |= dump_node_info(F, n);
843   print_node_error(F, p);
844   dump_node_vcgattr(F, n, NULL, bad);
845   fprintf(F, "}\n");
846   dump_const_node_local(F, n);
847 #if DO_HEAPANALYSIS
848   dump_irn_chi_term(F, n);
849   dump_irn_state(F, n);
850 #endif
851 }
852
853 /** dump the edge to the block this node belongs to */
854 static void
855 dump_ir_block_edge(FILE *F, ir_node *n)  {
856   if (get_opt_dump_const_local() && is_constlike_node(n)) return;
857   if (is_no_Block(n)) {
858     ir_node *block = get_nodes_block(n);
859
860     if (get_opt_dump_const_local() && is_constlike_node(block)) {
861       dump_const_block_local(F, n);
862     }
863     else {
864       fprintf (F, "edge: { sourcename: \"");
865       PRINT_NODEID(n);
866       fprintf (F, "\" targetname: ");
867       fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
868       fprintf (F, " "   BLOCK_EDGE_ATTR "}\n");
869     }
870   }
871 }
872
873 static void
874 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
875   if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
876     fprintf (F, INTRA_DATA_EDGE_ATTR);
877   else
878     fprintf (F, INTER_DATA_EDGE_ATTR);
879 }
880
881 static void
882 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
883   if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
884     fprintf (F, INTRA_MEM_EDGE_ATTR);
885   else
886     fprintf (F, INTER_MEM_EDGE_ATTR);
887 }
888
889 static void
890 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
891   assert(from);
892
893   if (dump_backedge_information_flag && is_backedge(from, to))
894     fprintf (F, BACK_EDGE_ATTR);
895
896   switch (get_irn_opcode(from)) {
897   case iro_Block:
898     fprintf (F, CF_EDGE_ATTR);
899     break;
900   case iro_Start:   break;
901   case iro_End:
902     if (to >= 0) {
903       if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
904     fprintf (F, CF_EDGE_ATTR);
905       if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
906     fprintf (F, INTER_MEM_EDGE_ATTR);
907     }
908     break;
909   case iro_EndReg:
910   case iro_EndExcept:
911   case iro_Jmp:
912   case iro_Break:
913   case iro_Cond:
914     print_data_edge_vcgattr(F, from, to);
915     break;
916   case iro_Return:
917   case iro_Raise:
918     if (to == 0)
919       print_mem_edge_vcgattr(F, from, to);
920     else
921       print_data_edge_vcgattr(F, from, to);
922     break;
923   case iro_Const:
924   case iro_SymConst:
925     print_data_edge_vcgattr(F, from, to);
926     break;
927   case iro_Sel:
928   case iro_Call:
929     if (to == 0)
930       print_mem_edge_vcgattr(F, from, to);
931     else
932       print_data_edge_vcgattr(F, from, to);
933     break;
934   case iro_CallBegin:
935   case iro_Add:
936   case iro_Sub:
937   case iro_Minus:
938   case iro_Mul:
939     print_data_edge_vcgattr(F, from, to);
940     break;
941   case iro_Quot:
942   case iro_DivMod:
943   case iro_Div:
944   case iro_Mod:
945     if (to == 0)
946       print_mem_edge_vcgattr(F, from, to);
947     else
948       print_data_edge_vcgattr(F, from, to);
949     break;
950   case iro_Abs:
951   case iro_And:
952   case iro_Or:
953   case iro_Eor:
954   case iro_Shl:
955   case iro_Shr:
956   case iro_Shrs:
957   case iro_Rot:
958   case iro_Cmp:
959   case iro_Conv:
960       print_data_edge_vcgattr(F, from, to);
961     break;
962   case iro_Phi:
963     if (get_irn_modecode(from) == irm_M)
964       fprintf (F, INTER_MEM_EDGE_ATTR);
965     else
966       print_data_edge_vcgattr(F, from, to);
967     break;
968   case iro_Load:
969   case iro_Store:
970   case iro_Alloc:
971   case iro_Free:
972     if (to == 0)
973       print_mem_edge_vcgattr(F, from, to);
974     else
975       print_data_edge_vcgattr(F, from, to);
976     break;
977   case iro_Sync:
978     print_mem_edge_vcgattr(F, from, to);
979     break;
980   case iro_Tuple:  break;
981   case iro_Proj:
982   case iro_Filter:
983     switch (get_irn_modecode(from)) {
984     case irm_X:
985       fprintf (F, CF_EDGE_ATTR);
986       break;
987     case irm_M:
988       fprintf (F, INTER_MEM_EDGE_ATTR);
989       break;
990     default:
991       print_data_edge_vcgattr(F, from, to);
992       break;
993     }
994     break;
995   case iro_Bad:     break;
996   case iro_Unknown: break;
997   case iro_Id:
998     switch (get_irn_modecode(from)) {
999     case irm_M:
1000       fprintf (F, INTRA_MEM_EDGE_ATTR);
1001       break;
1002     case irm_X:
1003       fprintf (F, CF_EDGE_ATTR);
1004       break;
1005     default:
1006       print_data_edge_vcgattr(F, from, to);
1007       break;
1008     } break;
1009   default:
1010     ;
1011   }
1012 }
1013
1014 /* dump edges to our inputs */
1015 static void
1016 dump_ir_data_edges(FILE *F, ir_node *n)  {
1017   int i;
1018   unsigned long visited = get_irn_visited(n);
1019
1020   if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1021     return;
1022
1023   for (i = 0; i < get_irn_arity(n); i++) {
1024     ir_node * pred = get_irn_n(n, i);
1025     assert(pred);
1026
1027     if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1028       continue; /* pred not dumped */
1029
1030     if (dump_backedge_information_flag && is_backedge(n, i))
1031       fprintf (F, "backedge: {sourcename: \"");
1032     else
1033       fprintf (F, "edge: {sourcename: \"");
1034     PRINT_NODEID(n);
1035     fprintf (F, "\" targetname: ");
1036     if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1037       PRINT_CONSTID(n, pred);
1038     } else {
1039       fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1040     }
1041     fprintf (F, " label: \"%d\" ", i);
1042     print_edge_vcgattr(F, n, i);
1043     fprintf (F, "}\n");
1044   }
1045 }
1046
1047 /** Dumps a node and its edges but not the block edge
1048  */
1049 static INLINE void
1050 dump_node_wo_blockedge (ir_node *n, void *env) {
1051   FILE *F = env;
1052   dump_node(F, n);
1053   dump_ir_data_edges(F, n);
1054 }
1055
1056 /** Dumps a node and its edges.
1057  */
1058 static void
1059 dump_whole_node (ir_node *n, void *env) {
1060   FILE *F = env;
1061   dump_node_wo_blockedge(n, env);
1062   if (!node_floats(n)) dump_ir_block_edge(F, n);
1063 }
1064
1065 static void
1066 dump_const_node(ir_node *n, void *env) {
1067   if (is_Block(n)) return;
1068   dump_node_wo_blockedge(n, env);
1069 }
1070
1071 /***********************************************************************/
1072 /* the following routines dump the nodes/irgs bracketed to graphs.     */
1073 /***********************************************************************/
1074
1075 /** Dumps a constant expression as entity initializer, array bound ...
1076  */
1077 static void dump_const_expression(FILE *F, ir_node *value) {
1078   ir_graph *rem = current_ir_graph;
1079   int rem_dump_const_local = dump_const_local;
1080   dump_const_local = 0;
1081   current_ir_graph = get_const_code_irg();
1082   irg_walk(value, dump_const_node, NULL, F);
1083   /* Decrease visited flag so that we walk with the same flag for the next
1084      expresssion.  This guarantees that we don't dump the same node twice,
1085      as for const expressions cse is performed to save memory. */
1086   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1087   current_ir_graph = rem;
1088   dump_const_local = rem_dump_const_local;
1089 }
1090
1091 /** Dump a block as graph containing its nodes.
1092  *
1093  *  Expects to find nodes belonging to the block as list in its
1094  *  link field.
1095  *  Dumps the edges of all nodes including itself. */
1096 static void
1097 dump_whole_block(FILE *F, ir_node *block) {
1098   ir_node *node;
1099   assert(is_Block(block));
1100
1101   fprintf(F, "graph: { title: \"");
1102   PRINT_NODEID(block);
1103   fprintf(F, "\"  label: \"");
1104   dump_node_label(F, block);
1105 #if DO_HEAPANALYSIS
1106   if (get_opt_dump_abstvals())
1107     fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1108 #endif
1109   fprintf(F, "\" status:clustered color:%s \n",
1110        get_Block_matured(block) ? "yellow" : "red");
1111
1112   /* dump the blocks edges */
1113   dump_ir_data_edges(F, block);
1114
1115   /* dump the nodes that go into the block */
1116   for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1117     dump_node(F, node);
1118     dump_ir_data_edges(F, node);
1119   }
1120
1121   /* Close the vcg information for the block */
1122   fprintf(F, "}\n");
1123   dump_const_node_local(F, block);
1124 #if DO_HEAPANALYSIS
1125   dump_irn_chi_term(F, block);
1126 #endif
1127   fprintf(F, "\n");
1128 }
1129
1130 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1131  *  The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1132 static void
1133 dump_block_graph(FILE *F, ir_graph *irg) {
1134   int i;
1135   ir_graph *rem = current_ir_graph;
1136   ir_node **arr = ird_get_irg_link(irg);
1137   current_ir_graph = irg;
1138
1139   for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1140     ir_node * node = arr[i];
1141     if (is_Block(node)) {
1142       /* Dumps the block and all the nodes in the block, which are to
1143          be found in Block->link. */
1144       dump_whole_block(F, node);
1145     } else {
1146       /* Nodes that are not in a Block. */
1147       dump_node(F, node);
1148       if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1149         dump_const_block_local(F, node);
1150       }
1151       dump_ir_data_edges(F, node);
1152     }
1153   }
1154
1155   if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1156     dump_loop_nodes_into_graph(F, irg);
1157
1158   current_ir_graph = rem;
1159 }
1160
1161 /** Dumps an irg as a graph.
1162  *  If interprocedural view edges can point to nodes out of this graph.
1163  */
1164 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1165
1166   fprintf(F, "graph: { title: \"");
1167   PRINT_IRGID(irg);
1168   fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1169       get_ent_dump_name(get_irg_entity(irg)));
1170
1171   dump_block_graph(F, irg);
1172
1173   /* Close the vcg information for the irg */
1174   fprintf(F, "}\n\n");
1175 }
1176
1177 /*******************************************************************/
1178 /* Basic type and entity nodes and edges.                          */
1179 /*******************************************************************/
1180
1181 /** dumps the edges between nodes and their type or entity attributes. */
1182 static void dump_node2type_edges(ir_node *n, void *env)
1183 {
1184   FILE *F = env;
1185   assert(n);
1186
1187   switch (get_irn_opcode(n)) {
1188   case iro_Const :
1189     /* @@@ some consts have an entity */
1190     break;
1191   case iro_SymConst:
1192     if (   (get_SymConst_kind(n) ==symconst_type_tag)
1193        || (get_SymConst_kind(n) ==symconst_size))
1194       {
1195         print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1196       }
1197     break;
1198   case iro_Sel: {
1199       print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1200     } break;
1201   case iro_Call: {
1202       print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1203     } break;
1204   case iro_Alloc: {
1205       print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1206     } break;
1207   case iro_Free: {
1208       print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1209     } break;
1210   case iro_Cast: {
1211       print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1212     } break;
1213   default:
1214     break;
1215   }
1216 }
1217
1218
1219 static int print_type_info(FILE *F, type *tp) {
1220   int bad = 0;
1221
1222   if (get_type_state(tp) == layout_undefined) {
1223     fprintf(F, "state: layout_undefined\n");
1224   } else {
1225     fprintf(F, "state: layout_fixed,\n");
1226   }
1227   if (get_type_mode(tp))
1228     fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1229   fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1230
1231   return bad;
1232 }
1233
1234 static void print_typespecific_info(FILE *F, type *tp) {
1235   switch (get_type_tpop_code(tp)) {
1236   case tpo_class:
1237     {
1238       fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1239     } break;
1240   case tpo_struct:
1241     {
1242     } break;
1243   case tpo_method:
1244     {
1245       fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1246       fprintf(F, "params: %d\n", get_method_n_params(tp));
1247       fprintf(F, "results: %d\n", get_method_n_ress(tp));
1248     } break;
1249   case tpo_union:
1250     {
1251     } break;
1252   case tpo_array:
1253     {
1254     } break;
1255   case tpo_enumeration:
1256     {
1257     } break;
1258   case tpo_pointer:
1259     {
1260     } break;
1261   case tpo_primitive:
1262     {
1263     } break;
1264   default: break;
1265   } /* switch type */
1266 }
1267
1268
1269 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1270   switch (get_type_tpop_code(tp)) {
1271   case tpo_class:
1272     {
1273       if (peculiarity_existent == get_class_peculiarity(tp))
1274     fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1275       else
1276     fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1277     } break;
1278   case tpo_struct:
1279     {
1280       fprintf (F, " " TYPE_METH_NODE_ATTR);
1281     } break;
1282   case tpo_method:
1283     {
1284     } break;
1285   case tpo_union:
1286     {
1287     } break;
1288   case tpo_array:
1289     {
1290     } break;
1291   case tpo_enumeration:
1292     {
1293     } break;
1294   case tpo_pointer:
1295     {
1296     } break;
1297   case tpo_primitive:
1298     {
1299     } break;
1300   default: break;
1301   } /* switch type */
1302 }
1303
1304 static int print_type_node(FILE *F, type *tp)
1305 {
1306   int bad = 0;
1307
1308   fprintf (F, "node: {title: ");
1309   PRINT_TYPEID(tp);
1310   fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1311   fprintf (F, " info1: \"");
1312   bad |= print_type_info(F, tp);
1313   print_typespecific_info(F, tp);
1314   fprintf (F, "\"");
1315   print_typespecific_vcgattr(F, tp);
1316   fprintf (F, "}\n");
1317
1318   return bad;
1319 }
1320
1321 #define X(a)    case a: fprintf(F, #a); break
1322 void dump_entity_node(FILE *F, entity *ent, int color)
1323 {
1324   fprintf (F, "node: {title: \"");
1325   PRINT_ENTID(ent); fprintf(F, "\"");
1326   fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1327   fprintf (F, "label: ");
1328   fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1329   if (color)
1330     fprintf(F, "color: %d", color);
1331   else
1332     fprintf (F, ENTITY_NODE_ATTR);
1333   fprintf (F, "\n info1: \"");
1334
1335   dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1336
1337   fprintf(F, "\"\n}\n");
1338 }
1339 #undef X
1340
1341 static void dump_enum_item(FILE *F, type *tp, int pos)
1342 {
1343   char buf[1024];
1344   ident *id  = get_enumeration_nameid(tp, pos);
1345   tarval *tv = get_enumeration_enum(tp, pos);
1346
1347   tarval_snprintf(buf, sizeof(buf), tv);
1348   fprintf (F, "node: {title: \"");
1349   PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1350   fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1351   fprintf (F, "label: ");
1352   fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1353   fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1354 }
1355
1356 /* dumps a type or entity and it's edges. */
1357 static void
1358 dump_type_info(type_or_ent *tore, void *env) {
1359   FILE *F = env;
1360   int i = 0;  /* to shutup gcc */
1361
1362   /* dump this type or entity */
1363
1364   switch (get_kind(tore)) {
1365   case k_entity:
1366     {
1367       entity *ent = (entity *)tore;
1368       ir_node *value;
1369       /* The node */
1370       dump_entity_node(F, ent, 0);
1371       /* The Edges */
1372       /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
1373       fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1374                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1375       print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1376       if (is_Class_type(get_entity_owner(ent))) {
1377         for(i = 0; i < get_entity_n_overwrites(ent); i++)
1378           print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1379       }
1380       /* attached subgraphs */
1381       if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1382         if (is_atomic_entity(ent)) {
1383           value = get_atomic_ent_value(ent);
1384           if (value) {
1385             print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1386             /* DDMN(value);  $$$ */
1387             dump_const_expression(F, value);
1388           }
1389         }
1390         if (is_compound_entity(ent)) {
1391           for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1392             value = get_compound_ent_value(ent, i);
1393             if (value) {
1394               print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1395               dump_const_expression(F, value);
1396               print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1397               /*
1398               fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1399               ENT_CORR_EDGE_ATTR  "}\n", GET_ENTID(ent),
1400               get_compound_ent_value_member(ent, i), i);
1401               */
1402             }
1403           }
1404         }
1405       }
1406     } break;
1407   case k_type:
1408     {
1409       type *tp = (type *)tore;
1410       print_type_node(F, tp);
1411       /* and now the edges */
1412       switch (get_type_tpop_code(tp)) {
1413       case tpo_class:
1414         {
1415           for (i=0; i < get_class_n_supertypes(tp); i++)
1416             print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1417           for (i=0; i < get_class_n_members(tp); i++)
1418             print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1419         } break;
1420       case tpo_struct:
1421         {
1422           for (i=0; i < get_struct_n_members(tp); i++)
1423             print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1424         } break;
1425       case tpo_method:
1426         {
1427           for (i = 0; i < get_method_n_params(tp); i++)
1428             print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1429           for (i = 0; i < get_method_n_ress(tp); i++)
1430             print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1431         } break;
1432       case tpo_union:
1433         {
1434           for (i = 0; i < get_union_n_members(tp); i++)
1435             print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1436         } break;
1437       case tpo_array:
1438         {
1439           print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1440           print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1441           for (i = 0; i < get_array_n_dimensions(tp); i++) {
1442             ir_node *upper = get_array_upper_bound(tp, i);
1443             ir_node *lower = get_array_lower_bound(tp, i);
1444             print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1445             print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1446             dump_const_expression(F, upper);
1447             dump_const_expression(F, lower);
1448           }
1449
1450         } break;
1451       case tpo_enumeration:
1452         {
1453           for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1454             dump_enum_item(F, tp, i);
1455             print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1456           }
1457         } break;
1458       case tpo_pointer:
1459         {
1460           print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1461         } break;
1462       case tpo_primitive:
1463         {
1464         } break;
1465       default: break;
1466       } /* switch type */
1467     }
1468     break; /* case k_type */
1469   default:
1470     {
1471       printf(" *** irdump,  dump_type_info(l.%i), faulty type.\n", __LINE__);
1472     } break;
1473   } /* switch kind_or_entity */
1474 }
1475
1476 typedef struct _h_env {
1477   int dump_ent;
1478   FILE *f;
1479 } h_env_t;
1480
1481 /** For dumping class hierarchies.
1482  * Dumps a class type node and a superclass edge.
1483  * If env->dump_ent dumps entities of classes and overwrites edges.
1484  */
1485 static void
1486 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1487   h_env_t *env = ctx;
1488   FILE *F = env->f;
1489   int i = 0;  /* to shutup gcc */
1490
1491   /* dump this type or entity */
1492   switch (get_kind(tore)) {
1493   case k_entity: {
1494     entity *ent = (entity *)tore;
1495     if (get_entity_owner(ent) == get_glob_type()) break;
1496     if (!is_Method_type(get_entity_type(ent))) break;  /* GL */
1497     if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1498       /* The node */
1499       dump_entity_node(F, ent, 0);
1500       /* The edges */
1501       print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1502       for(i = 0; i < get_entity_n_overwrites(ent); i++)
1503         print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1504     }
1505   } break; /* case k_entity */
1506   case k_type:
1507     {
1508       type *tp = (type *)tore;
1509       if (tp == get_glob_type()) break;
1510       switch (get_type_tpop_code(tp)) {
1511         case tpo_class: {
1512           print_type_node(F, tp);
1513           /* and now the edges */
1514           for (i=0; i < get_class_n_supertypes(tp); i++)
1515           {
1516               print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1517           }
1518         } break;
1519         default: break;
1520       } /* switch type */
1521     }
1522     break; /* case k_type */
1523   default:
1524     {
1525       printf(" *** irdump,  dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1526     } break;
1527   } /* switch kind_or_entity */
1528 }
1529
1530 /*******************************************************************/
1531 /* dump analysis information that is expressed in graph terms.     */
1532 /*******************************************************************/
1533
1534 /* dump out edges */
1535 static void
1536 dump_out_edge(ir_node *n, void *env) {
1537   FILE *F = env;
1538   int i;
1539   for (i = 0; i < get_irn_n_outs(n); i++) {
1540     assert(get_irn_out(n, i));
1541     fprintf (F, "edge: {sourcename: \"");
1542     PRINT_NODEID(n);
1543     fprintf (F, "\" targetname: \"");
1544     PRINT_NODEID(get_irn_out(n, i));
1545     fprintf (F, "\" color: red linestyle: dashed");
1546     fprintf (F, "}\n");
1547   }
1548 }
1549
1550 static INLINE void
1551 dump_loop_label(FILE *F, ir_loop *loop) {
1552   fprintf (F, "loop %d, %d sons, %d nodes",
1553        get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1554 }
1555
1556 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1557   fprintf (F, " info1: \"");
1558   fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1559 #if DEBUG_libfirm   /* GL @@@ debug analyses */
1560   fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1561 #endif
1562   fprintf (F, "\"");
1563 }
1564
1565 static INLINE void
1566 dump_loop_node(FILE *F, ir_loop *loop) {
1567   fprintf (F, "node: {title: \"");
1568   PRINT_LOOPID(loop);
1569   fprintf (F, "\" label: \"");
1570   dump_loop_label(F, loop);
1571   fprintf (F, "\" ");
1572   dump_loop_info(F, loop);
1573   fprintf (F, "}\n");
1574
1575 }
1576
1577 static INLINE void
1578 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1579   assert(loop);
1580   fprintf (F, "edge: {sourcename: \"");
1581   PRINT_LOOPID(loop);
1582   fprintf (F, "\" targetname: \"");
1583   PRINT_NODEID(get_loop_node(loop, i));
1584   fprintf (F, "\" color: green");
1585   fprintf (F, "}\n");
1586 }
1587
1588 static INLINE void
1589 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1590   assert(loop);
1591   fprintf (F, "edge: {sourcename: \"");
1592   PRINT_LOOPID(loop);
1593   fprintf (F, "\" targetname: \"");
1594   PRINT_LOOPID(get_loop_son(loop, i));
1595   fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1596        get_loop_element_pos(loop, get_loop_son(loop, i)));
1597 }
1598
1599 static
1600 void dump_loops(FILE *F, ir_loop *loop) {
1601   int i;
1602   /* dump this loop node */
1603   dump_loop_node(F, loop);
1604
1605   /* dump edges to nodes in loop -- only if it is a real loop */
1606   if (get_loop_depth(loop) != 0) {
1607     for (i = 0; i < get_loop_n_nodes(loop); i++) {
1608       dump_loop_node_edge(F, loop, i);
1609     }
1610   }
1611   for (i = 0; i < get_loop_n_sons(loop); i++) {
1612     dump_loops(F, get_loop_son(loop, i));
1613     dump_loop_son_edge(F, loop, i);
1614   }
1615 }
1616
1617 static INLINE
1618 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1619   ir_graph *rem = current_ir_graph;
1620   current_ir_graph = irg;
1621
1622   if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1623
1624   current_ir_graph = rem;
1625 }
1626
1627
1628 /**
1629  * dumps the VCG header
1630  */
1631 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1632   char *label;
1633
1634   if (edge_label) {
1635     label = "yes";
1636   } else {
1637     label = "no";
1638   }
1639
1640   if (!orientation) orientation = "bottom_to_top";
1641
1642   /* print header */
1643   fprintf (F,
1644        "graph: { title: \"ir graph of %s\"\n"
1645        "display_edge_labels: %s\n"
1646        "layoutalgorithm: mindepth\n"
1647        "manhattan_edges: yes\n"
1648        "port_sharing: no\n"
1649        "orientation: %s\n"
1650        "classname 1:  \"intrablock Data\"\n"
1651        "classname 16: \"interblock Data\"\n"
1652        "classname 2:  \"Block\"\n"
1653        "classname 13: \"Control Flow\"\n"
1654        "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1655        "classname 14: \"intrablock Memory\"\n"
1656        "classname 17: \"interblock Memory\"\n"
1657        "classname 15: \"Dominators\"\n"
1658        "classname 3:  \"Entity type\"\n"
1659        "classname 4:  \"Entity owner\"\n"
1660        "classname 5:  \"Method Param\"\n"
1661        "classname 6:  \"Method Res\"\n"
1662        "classname 7:  \"Super\"\n"
1663        "classname 8:  \"Union\"\n"
1664        "classname 9:  \"Points-to\"\n"
1665        "classname 10: \"Array Element Type\"\n"
1666        "classname 11: \"Overwrites\"\n"
1667        "classname 12: \"Member\"\n"
1668        "infoname 1: \"Attribute\"\n"
1669        "infoname 2: \"Verification errors\"\n",
1670        name, label, orientation);
1671
1672   /* don't use all, the range is too whith/black. */
1673   n_colors   = 18;
1674   base_color = 105;
1675   fprintf (F,
1676        "colorentry 100:    0   0    0\n"
1677        "colorentry 101:   20   0    0\n"
1678        "colorentry 102:   40   0    0\n"
1679        "colorentry 103:   60   0    0\n"
1680        "colorentry 104:   80   0    0\n"
1681        "colorentry 105:  100   0    0\n"
1682        "colorentry 106:  120   0    0\n"
1683        "colorentry 107:  140   0    0\n"
1684        "colorentry 108:  150   0    0\n"
1685        "colorentry 109:  180   0    0\n"
1686        "colorentry 110:  200   0    0\n"
1687        "colorentry 111:  220   0    0\n"
1688        "colorentry 112:  240   0    0\n"
1689        "colorentry 113:  255   0    0\n"
1690        "colorentry 113:  255  20   20\n"
1691        "colorentry 114:  255  40   40\n"
1692        "colorentry 115:  255  60   60\n"
1693        "colorentry 116:  255  80   80\n"
1694        "colorentry 117:  255 100  100\n"
1695        "colorentry 118:  255 120  120\n"
1696        "colorentry 119:  255 140  140\n"
1697        "colorentry 120:  255 150  150\n"
1698        "colorentry 121:  255 180  180\n"
1699        "colorentry 122:  255 200  200\n"
1700        "colorentry 123:  255 220  220\n"
1701        "colorentry 124:  255 240  240\n"
1702        "colorentry 125:  255 250  250\n"
1703        );
1704
1705   fprintf (F, "\n");        /* a separator */
1706 }
1707
1708 /**
1709  * open a vcg file
1710  *
1711  * @param irg     The graph to be dumped
1712  * @param suffix1 first filename suffix
1713  * @param suffix2 second filename suffix
1714  */
1715 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1716   FILE *F;
1717   const char *nm = get_irg_dump_name(irg);
1718   int len = strlen(nm), i, j;
1719   char *fname;  /* filename to put the vcg information in */
1720
1721   if (!suffix1) suffix1 = "";
1722   if (!suffix2) suffix2 = "";
1723
1724   /* open file for vcg graph */
1725   fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1726
1727   /* strncpy (fname, nm, len); */     /* copy the filename */
1728   j = 0;
1729   for (i = 0; i < len; ++i) {  /* replace '/' in the name: escape by @. */
1730     if (nm[i] == '/') {
1731       fname[j] = '@'; j++; fname[j] = '1'; j++;
1732     } else if (nm[i] == '@') {
1733       fname[j] = '@'; j++; fname[j] = '2'; j++;
1734     } else {
1735       fname[j] = nm[i]; j++;
1736     }
1737   }
1738   fname[j] = '\0';
1739   strcat (fname, suffix1);  /* append file suffix */
1740   strcat (fname, suffix2);  /* append file suffix */
1741   strcat (fname, ".vcg");   /* append the .vcg suffix */
1742
1743   /* vcg really expect only a <CR> at end of line, so
1744    * the "b"inary mode is what you mean (and even needed for Win32)
1745    */
1746   F = fopen (fname, "wb");  /* open file for writing */
1747   if (!F) {
1748     panic("cannot open %s for writing (%m)", fname);  /* not reached */
1749   }
1750   free(fname);
1751
1752   return F;
1753 }
1754
1755 /**
1756  * open a vcg file
1757  *
1758  * @param irg     The graph to be dumped
1759  * @param suffix  filename suffix
1760  */
1761 FILE *vcg_open_name (const char *name, const char *suffix) {
1762   FILE *F;
1763   char *fname;  /* filename to put the vcg information in */
1764   int i, j, len = strlen(name);
1765
1766   if (!suffix) suffix = "";
1767
1768   /** open file for vcg graph */
1769   fname = malloc (len * 2 + 5 + strlen(suffix));
1770   /* strcpy (fname, name);*/    /* copy the filename */
1771   j = 0;
1772   for (i = 0; i < len; ++i) {  /* replace '/' in the name: escape by @. */
1773     if (name[i] == '/') {
1774       fname[j] = '@'; j++; fname[j] = '1'; j++;
1775     } else if (name[i] == '@') {
1776       fname[j] = '@'; j++; fname[j] = '2'; j++;
1777     } else {
1778       fname[j] = name[i]; j++;
1779     }
1780   }
1781   fname[j] = '\0';
1782   strcat (fname, suffix);
1783   strcat (fname, ".vcg");  /* append the .vcg suffix */
1784
1785   /* vcg really expect only a <CR> at end of line, so
1786    * the "b"inary mode is what you mean (and even needed for Win32)
1787    */
1788   F = fopen (fname, "wb");  /* open file for writing */
1789   if (!F) {
1790     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
1791   }
1792   free(fname);
1793
1794   return F;
1795 }
1796
1797 /**
1798  * Dumps the vcg file footer
1799  */
1800 static INLINE void dump_vcg_footer (FILE *F) {
1801   fprintf (F, "}\n");
1802 }
1803
1804 /**
1805  * close the vcg file
1806  */
1807 void vcg_close (FILE *F) {
1808   dump_vcg_footer(F);    /* print footer */
1809   fclose (F);           /* close vcg file */
1810 }
1811
1812 /************************************************************************/
1813 /************************************************************************/
1814 /* Routines that dump all or parts of the firm representation to a file */
1815 /************************************************************************/
1816 /************************************************************************/
1817
1818 /************************************************************************/
1819 /* Dump ir graphs, different formats and additional information.        */
1820 /************************************************************************/
1821
1822 /** Routine to dump a graph, blocks as conventional nodes.  */
1823 void
1824 dump_ir_graph (ir_graph *irg, const char *suffix )
1825 {
1826   FILE *f;
1827   ir_graph *rem;
1828   char *suffix1;
1829   rem = current_ir_graph;
1830
1831   if (strncmp(get_entity_name(get_irg_entity(irg)),
1832           dump_file_filter, strlen(dump_file_filter)) != 0) return;
1833
1834   current_ir_graph = irg;
1835   if (get_interprocedural_view()) suffix1 = "-pure-ip";
1836   else                            suffix1 = "-pure";
1837   f = vcg_open(irg, suffix, suffix1);
1838   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1839
1840   /* walk over the graph */
1841   /* dump_whole_node must be called in post visiting predecessors */
1842   irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1843
1844   /* dump the out edges in a separate walk */
1845   if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1846     irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
1847   }
1848
1849   vcg_close(f);
1850
1851   current_ir_graph = rem;
1852 }
1853
1854
1855 void
1856 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1857 {
1858   FILE *f;
1859   int i;
1860   char *suffix1;
1861
1862   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1863     return;
1864
1865   if (get_interprocedural_view()) suffix1 = "-ip";
1866   else                            suffix1 = "";
1867   f = vcg_open(irg, suffix, suffix1);
1868   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1869
1870   construct_block_lists(irg);
1871
1872   for (i = 0; i < get_irp_n_irgs(); i++) {
1873     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1874     if (arr) {
1875       dump_graph_from_list(f, get_irp_irg(i));
1876       DEL_ARR_F(arr);
1877     }
1878   }
1879
1880   vcg_close(f);
1881 }
1882
1883 /** dumps a graph with type information */
1884 void
1885 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1886 {
1887   FILE *f;
1888   ir_graph *rem = current_ir_graph;
1889   char *suffix1;
1890
1891   /* if a filter is set, dump only the irg's that match the filter */
1892   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1893     return;
1894
1895   current_ir_graph = irg;
1896
1897   if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
1898   else                            suffix1 = "-pure-wtypes";
1899   f = vcg_open(irg,suffix, suffix1);
1900   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1901
1902   /* dump common ir graph */
1903   irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1904   /* dump type info */
1905   type_walk_irg(irg, dump_type_info, NULL, f);
1906   inc_irg_visited(get_const_code_irg());
1907   /* dump edges from graph to type info */
1908   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1909
1910   vcg_close(f);
1911   current_ir_graph = rem;
1912 }
1913
1914 void
1915 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1916 {
1917   FILE *f;
1918   int i;
1919   char *suffix1;
1920   ir_graph *rem = current_ir_graph;
1921
1922   /* if a filter is set, dump only the irg's that match the filter */
1923   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1924     return;
1925
1926   if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
1927   else                            suffix1 = "-wtypes";
1928   f = vcg_open(irg, suffix, suffix1);
1929   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1930
1931   /* dump common blocked ir graph */
1932   construct_block_lists(irg);
1933
1934   for (i = 0; i < get_irp_n_irgs(); i++) {
1935     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1936     if (arr) {
1937       dump_graph_from_list(f, get_irp_irg(i));
1938       DEL_ARR_F(arr);
1939     }
1940   }
1941
1942   /* dump type info */
1943   current_ir_graph = irg;
1944   type_walk_irg(irg, dump_type_info, NULL, f);
1945   inc_irg_visited(get_const_code_irg());
1946
1947   /* dump edges from graph to type info */
1948   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1949
1950   current_ir_graph = rem;
1951   vcg_close(f);
1952 }
1953
1954 /*---------------------------------------------------------------------*/
1955 /* The following routines dump a control flow graph.                   */
1956 /*---------------------------------------------------------------------*/
1957
1958 static void
1959 dump_block_to_cfg(ir_node *block, void *env) {
1960   FILE *F = env;
1961   int i, fl;
1962   ir_node *pred;
1963
1964   if (is_Block(block)) {
1965     /* This is a block. Dump a node for the block. */
1966     fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1967     fprintf (F, "\" label: \"");
1968     if (block == get_irg_start_block(get_irn_irg(block)))
1969       fprintf(F, "Start ");
1970     if (block == get_irg_end_block(get_irn_irg(block)))
1971       fprintf(F, "End ");
1972
1973     fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1974     PRINT_NODEID(block);
1975     fprintf (F, "\" ");
1976     fprintf(F, "info1:\"");
1977     if (dump_dominator_information_flag) {
1978       fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
1979       fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block));
1980       fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block));
1981                 }
1982
1983     /* show arity and possible Bad predecessors of the block */
1984     fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
1985     for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
1986       ir_node *pred = get_Block_cfgpred(block, i);
1987       if (is_Bad(pred)) {
1988     if (! fl)
1989       fprintf(F, "Bad pred at pos: ");
1990     fprintf(F, "%d ", i);
1991     fl = 1;
1992       }
1993     }
1994     if (fl)
1995       fprintf(F, "\n");
1996
1997     fprintf (F, "\"");  /* closing quote of info */
1998
1999     if ((block == get_irg_start_block(get_irn_irg(block))) ||
2000     (block == get_irg_end_block(get_irn_irg(block)))     )
2001       fprintf(F, " color:blue ");
2002     else if (fl)
2003       fprintf(F, " color:yellow ");
2004
2005     fprintf (F, "}\n");
2006     /* Dump the edges */
2007     for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2008       if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2009         pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2010         fprintf (F, "edge: { sourcename: \"");
2011         PRINT_NODEID(block);
2012         fprintf (F, "\" targetname: \"");
2013         PRINT_NODEID(pred);
2014         fprintf (F, "\"}\n");
2015       }
2016
2017     /* Dump dominator edge */
2018     if (dump_dominator_information_flag && get_Block_idom(block)) {
2019       pred = get_Block_idom(block);
2020       fprintf (F, "edge: { sourcename: \"");
2021       PRINT_NODEID(block);
2022       fprintf (F, "\" targetname: \"");
2023       PRINT_NODEID(pred);
2024       fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2025     }
2026   }
2027 }
2028
2029 void
2030 dump_cfg (ir_graph *irg, const char *suffix)
2031 {
2032   FILE *f;
2033   ir_graph *rem = current_ir_graph;
2034   int ddif = dump_dominator_information_flag;
2035   int ipv = get_interprocedural_view();
2036
2037   /* if a filter is set, dump only the irg's that match the filter */
2038   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2039     return;
2040
2041   current_ir_graph = irg;
2042
2043   f = vcg_open(irg, suffix, "-cfg");
2044   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2045
2046   if (ipv) {
2047     printf("Warning: dumping cfg not in interprocedural view!\n");
2048     set_interprocedural_view(false);
2049   }
2050
2051   if (get_irg_dom_state(irg) != dom_consistent)
2052     dump_dominator_information_flag = 0;
2053
2054   /* walk over the blocks in the graph */
2055   irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2056   dump_node(f, get_irg_bad(irg));
2057
2058   dump_dominator_information_flag = ddif;
2059   set_interprocedural_view(ipv);
2060   vcg_close(f);
2061   current_ir_graph = rem;
2062 }
2063
2064
2065 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2066   if (pset_find_ptr(mark_set, n)) return;
2067
2068   pset_insert_ptr(mark_set, n);
2069
2070   if (depth > 0) {
2071     int i, start = is_Block(n) ? 0 : -1;
2072     dump_whole_node(n, F);
2073     for (i = start; i < get_irn_arity(n); ++i)
2074       descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2075   } else {
2076     dump_node(F, n);
2077     /* Don't dump edges to nodes further out.  These might be edges to
2078        nodes we already dumped, if there is a shorter path to these. */
2079   }
2080 }
2081
2082 static int subgraph_counter = 0;
2083 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2084   FILE *F;
2085   char buf[32];
2086   pset *mark_set = pset_new_ptr(1);
2087   sprintf(buf, "-subg_%03d", subgraph_counter++);
2088   F = vcg_open(get_irn_irg(root), suffix, buf);
2089   dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2090   descend_and_dump(F, root, depth, mark_set);
2091   vcg_close(F);
2092   del_pset(mark_set);
2093 }
2094
2095
2096 static int weight_overall(int rec, int loop) {
2097   return 2*rec + loop;
2098 }
2099
2100 static int compute_color (int my, int max) {
2101   int color;
2102   if (!max) {
2103     color = 0;
2104   } else {
2105     int step;
2106
2107     /* if small, scale to the full color range. */
2108     if (max < n_colors)
2109       my = my * (n_colors/max);
2110
2111     step = 1 + (max / n_colors);
2112
2113     color = my/step;
2114   }
2115   return base_color + n_colors - color;
2116 }
2117
2118 static int get_entity_color(entity *ent) {
2119   ir_graph *irg = get_entity_irg(ent);
2120   assert(irg);
2121
2122   {
2123     int rec_depth     = get_irg_recursion_depth(irg);
2124     int loop_depth    = get_irg_loop_depth(irg);
2125     int overall_depth = weight_overall(rec_depth, loop_depth);
2126
2127     int max_rec_depth     = irp->max_callgraph_recursion_depth;
2128     int max_loop_depth    = irp->max_callgraph_loop_depth;
2129     int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2130
2131     /* int my_rec_color     = compute_color(rec_depth, max_rec_depth); */
2132     /* int my_loop_color    = compute_color(loop_depth, max_loop_depth); */
2133     int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2134
2135     return my_overall_color;
2136   }
2137 }
2138
2139 void dump_callgraph(const char *suffix) {
2140   FILE *F;
2141   int i, n_irgs = get_irp_n_irgs();
2142   int rem = edge_label;
2143   edge_label = 1;
2144   //ident *prefix = new_id_from_str("java/");
2145
2146   F = vcg_open_name("Callgraph", suffix);
2147   dump_vcg_header(F, "Callgraph", NULL);
2148
2149   for (i = 0; i < n_irgs; ++i) {
2150     ir_graph *irg = get_irp_irg(i);
2151     entity *ent = get_irg_entity(irg);
2152     int j, n_callees = get_irg_n_callees(irg);
2153
2154     /* Do not dump runtime system. */
2155     //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2156
2157     dump_entity_node(F, ent, get_entity_color(ent));
2158     for (j = 0; j < n_callees; ++j) {
2159       entity *c = get_irg_entity(get_irg_callee(irg, j));
2160       //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2161       int be = is_irg_callee_backedge(irg, j);
2162       char *attr;
2163       attr = (be) ?
2164         "label:\"recursion %d\" color: %d" :
2165         "label:\"calls %d\" color: %d";
2166       print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2167     }
2168   }
2169
2170   edge_label = rem;
2171   vcg_close(F);
2172 }
2173
2174 /* Dump all irgs in interprocedural view to a single file. */
2175 void dump_all_cg_block_graph(const char *suffix) {
2176   FILE *f;
2177   int i;
2178   int rem_view = get_interprocedural_view();
2179   set_interprocedural_view(true);
2180
2181   f = vcg_open_name("All_graphs", suffix);
2182   dump_vcg_header(f, "All_graphs", NULL);
2183
2184   /* collect nodes in all irgs reachable in call graph*/
2185   for (i = 0; i < get_irp_n_irgs(); i++)
2186     ird_set_irg_link(get_irp_irg(i), NULL);
2187
2188   cg_walk(clear_link, collect_node, NULL);
2189
2190   /* dump all graphs */
2191   for (i = 0; i < get_irp_n_irgs(); i++) {
2192     current_ir_graph = get_irp_irg(i);
2193     assert(ird_get_irg_link(current_ir_graph));
2194     dump_graph_from_list(f, current_ir_graph);
2195     DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2196   }
2197
2198   vcg_close(f);
2199   set_interprocedural_view(rem_view);
2200 }
2201
2202 /*---------------------------------------------------------------------*/
2203 /* the following routines dumps type information without any ir nodes. */
2204 /*---------------------------------------------------------------------*/
2205
2206 void
2207 dump_type_graph (ir_graph *irg, const char *suffix)
2208 {
2209   FILE *f;
2210   ir_graph *rem;
2211   rem = current_ir_graph;
2212
2213   /* if a filter is set, dump only the irg's that match the filter */
2214   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2215
2216   current_ir_graph = irg;
2217
2218   f = vcg_open(irg, suffix, "-type");
2219   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2220
2221   /* walk over the blocks in the graph */
2222   type_walk_irg(irg, dump_type_info, NULL, f);
2223   /* The walker for the const code can be called several times for the
2224      same (sub) expression.  So that no nodes are dumped several times
2225      we decrease the visited flag of the corresponding graph after each
2226      walk.  So now increase it finally. */
2227   inc_irg_visited(get_const_code_irg());
2228
2229   vcg_close(f);
2230   current_ir_graph = rem;
2231 }
2232
2233 void
2234 dump_all_types (const char *suffix)
2235 {
2236   FILE *f = vcg_open_name("All_types", suffix);
2237   dump_vcg_header(f, "All_types", NULL);
2238   type_walk(dump_type_info, NULL, f);
2239   inc_irg_visited(get_const_code_irg());
2240   vcg_close(f);
2241 }
2242
2243 void
2244 dump_class_hierarchy (bool entities, const char *suffix)
2245 {
2246   FILE *f = vcg_open_name("class_hierarchy", suffix);
2247   h_env_t env;
2248
2249   env.f = f;
2250   dump_vcg_header(f, "class_hierarchy", NULL);
2251   if (entities)
2252     env.dump_ent = 1;
2253   else
2254     env.dump_ent = 0;
2255   type_walk(dump_class_hierarchy_node, NULL, &env);
2256   vcg_close(f);
2257 }
2258
2259 /*---------------------------------------------------------------------*/
2260 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
2261 /*  dump_ir_graph                                                      */
2262 /*  dump_ir_block_graph                                                */
2263 /*  dump_cfg                                                           */
2264 /*  dump_type_graph                                                    */
2265 /*  dump_ir_graph_w_types                                              */
2266 /*---------------------------------------------------------------------*/
2267
2268 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2269   int i, n_irgs = get_irp_n_irgs();
2270   for (i = 0; i < n_irgs; ++i) {
2271     dmp_grph(get_irp_irg(i), suffix);
2272   }
2273 }
2274
2275
2276 /*--------------------------------------------------------------------------------*
2277  * Dumps a stand alone loop graph with firm nodes which belong to one loop node   *
2278  * packed together in one subgraph/box                                            *
2279  *--------------------------------------------------------------------------------*/
2280
2281 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2282   int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2283   loop_element le;
2284   ir_loop *son = NULL;
2285
2286   /* Dump a new loop node. */
2287   dump_loop_node(F, loop);
2288
2289   /* Dump the loop elements. */
2290
2291   for(i = 0; i < get_loop_n_elements(loop); i++) {
2292     le = get_loop_element(loop, i);
2293     son = le.son;
2294     if (get_kind(son) == k_ir_loop) {
2295
2296       /* We are a loop son -> Recurse */
2297
2298       if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2299         fprintf(F, "\" }\n");
2300         fprintf (F, "edge: {sourcename: \"");
2301         PRINT_LOOPID(loop);
2302         fprintf (F, "\" targetname: \"");
2303         PRINT_LOOPID(loop);
2304         fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2305         loop_node_started = 0;
2306       }
2307       dump_loop_son_edge(F, loop, son_number++);
2308       dump_loops_standalone(F, son);
2309     } else if (get_kind(son) == k_ir_node) {
2310       /* We are a loop node -> Collect firm nodes */
2311
2312       ir_node *n = le.node;
2313       int bad = 0;
2314
2315       if (!loop_node_started) {
2316         /* Start a new node which contains all firm nodes of the current loop */
2317         fprintf (F, "node: { title: \"");
2318         PRINT_LOOPID(loop);
2319         fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2320         loop_node_started = 1;
2321         first = i;
2322       }
2323       else
2324         fprintf(F, "\n");
2325
2326       bad |= dump_node_label(F, n);
2327       /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2328       if (has_backedges(n)) fprintf(F, "\t loop head!");
2329     } else { /* for callgraph loop tree */
2330       ir_graph *n;
2331       assert(get_kind(son) == k_ir_graph);
2332
2333       /* We are a loop node -> Collect firm graphs */
2334       n = (ir_graph *)le.node;
2335       if (!loop_node_started) {
2336         /* Start a new node which contains all firm nodes of the current loop */
2337         fprintf (F, "node: { title: \"");
2338         PRINT_LOOPID(loop);
2339         fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2340         loop_node_started = 1;
2341         first = i;
2342       }
2343       else
2344         fprintf(F, "\n");
2345       fprintf (F, " %s", get_irg_dump_name(n));
2346       /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2347     }
2348   }
2349
2350   if (loop_node_started) {
2351     fprintf(F, "\" }\n");
2352     fprintf (F, "edge: {sourcename: \"");
2353     PRINT_LOOPID(loop);
2354     fprintf (F, "\" targetname: \"");
2355     PRINT_LOOPID(loop);
2356     fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2357     loop_node_started = 0;
2358   }
2359 }
2360
2361 void dump_loop_tree(ir_graph *irg, const char *suffix)
2362 {
2363   FILE *f;
2364   ir_graph *rem = current_ir_graph;
2365   int el_rem = edge_label;
2366   edge_label = 1;
2367
2368   /* if a filter is set, dump only the irg's that match the filter */
2369   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2370     return;
2371
2372   current_ir_graph = irg;
2373
2374   f = vcg_open(irg, suffix, "-looptree");
2375   dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2376
2377   if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2378
2379   vcg_close(f);
2380
2381   edge_label = el_rem;
2382   current_ir_graph = rem;
2383 }
2384
2385 void dump_callgraph_loop_tree(const char *suffix) {
2386   FILE *F;
2387   F = vcg_open_name("Callgraph_looptree", suffix);
2388   dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2389   dump_loops_standalone(F, irp->outermost_cg_loop);
2390   vcg_close(F);
2391 }
2392
2393
2394 /*-----------------------------------------------------------------------------*/
2395 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2396 /*-----------------------------------------------------------------------------*/
2397
2398 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2399   int i, son_number = 0, node_number = 0;
2400
2401   if (dump_loop_information_flag) dump_loop_node(F, loop);
2402
2403   for (i = 0; i < get_loop_n_elements(loop); i++) {
2404     loop_element le = get_loop_element(loop, i);
2405     if (*(le.kind) == k_ir_loop) {
2406       if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2407       /* Recur */
2408       collect_nodeloop(F, le.son, loopnodes);
2409     } else {
2410       if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2411       eset_insert(loopnodes, le.node);
2412     }
2413   }
2414 }
2415
2416 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2417   int i, j, start;
2418
2419   for(i = 0; i < get_loop_n_elements(loop); i++) {
2420     loop_element le = get_loop_element(loop, i);
2421     if (*(le.kind) == k_ir_loop) {
2422       /* Recur */
2423       collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2424     } else {
2425       if (is_Block(le.node)) start = 0; else start = -1;
2426       for (j = start; j < get_irn_arity(le.node); j++) {
2427         ir_node *pred = get_irn_n(le.node, j);
2428         if (!eset_contains(loopnodes, pred)) {
2429           eset_insert(extnodes, pred);
2430           if (!is_Block(pred)) {
2431             pred = get_nodes_block(pred);
2432             if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2433           }
2434         }
2435       }
2436     }
2437   }
2438 }
2439
2440 void dump_loop(ir_loop *l, const char *suffix) {
2441   FILE *F;
2442   char name[50];
2443   eset *loopnodes = eset_create();
2444   eset *extnodes = eset_create();
2445   ir_node *n, *b;
2446
2447   snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2448   F = vcg_open_name (name, suffix);
2449   dump_vcg_header(F, name, NULL);
2450
2451   /* collect all nodes to dump */
2452   collect_nodeloop(F, l, loopnodes);
2453   collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2454
2455   /* build block lists */
2456   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2457     set_irn_link(n, NULL);
2458   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2459     set_irn_link(n, NULL);
2460   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2461     if (!is_Block(n)) {
2462       b = get_nodes_block(n);
2463       set_irn_link(n, get_irn_link(b));
2464       set_irn_link(b, n);
2465     }
2466   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2467     if (!is_Block(n)) {
2468       b = get_nodes_block(n);
2469       set_irn_link(n, get_irn_link(b));
2470       set_irn_link(b, n);
2471     }
2472
2473   for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2474     if (is_Block(b)) {
2475       fprintf(F, "graph: { title: \"");
2476       PRINT_NODEID(b);
2477       fprintf(F, "\"  label: \"");
2478       dump_node_opcode(F, b);
2479       fprintf (F, " %ld", get_irn_node_nr(b));
2480       fprintf(F, "\" status:clustered color:yellow\n");
2481
2482       /* dump the blocks edges */
2483       dump_ir_data_edges(F, b);
2484
2485       /* dump the nodes that go into the block */
2486       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2487         if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2488         dump_node(F, n);
2489         overrule_nodecolor = NULL;
2490         if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2491       }
2492
2493       /* Close the vcg information for the block */
2494       fprintf(F, "}\n");
2495       dump_const_node_local(F, b);
2496       fprintf(F, "\n");
2497     }
2498   for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2499     if (is_Block(b)) {
2500       fprintf(F, "graph: { title: \"");
2501       PRINT_NODEID(b);
2502       fprintf(F, "\"  label: \"");
2503       dump_node_opcode(F, b);
2504       fprintf (F, " %ld", get_irn_node_nr(b));
2505       fprintf(F, "\" status:clustered color:lightblue\n");
2506
2507       /* dump the nodes that go into the block */
2508       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2509         if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2510         dump_node(F, n);
2511         overrule_nodecolor = NULL;
2512         if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2513       }
2514
2515       /* Close the vcg information for the block */
2516       fprintf(F, "}\n");
2517       dump_const_node_local(F, b);
2518       fprintf(F, "\n");
2519     }
2520
2521   eset_destroy(loopnodes);
2522   eset_destroy(extnodes);
2523   vcg_close(F);
2524 }