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