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