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