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