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