added test dumper
[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) dump_loop_nodes_into_graph(F, irg);
1178
1179   current_ir_graph = rem;
1180 }
1181
1182 /** Dumps an irg as a graph.
1183  *  If interprocedural view edges can point to nodes out of this graph.
1184  */
1185 static void dump_graph(FILE *F, ir_graph *irg) {
1186
1187   fprintf(F, "graph: { title: \"");
1188   PRINT_IRGID(irg);
1189   fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1190       get_ent_dump_name(get_irg_entity(irg)));
1191
1192   dump_block_graph(F, irg);
1193
1194   /* Close the vcg information for the irg */
1195   fprintf(F, "}\n\n");
1196 }
1197
1198 /*******************************************************************/
1199 /* Basic type and entity nodes and edges.                          */
1200 /*******************************************************************/
1201
1202 /* dumps the edges between nodes and their type or entity attributes. */
1203 static void dump_node2type_edges(ir_node *n, void *env)
1204 {
1205   FILE *F = env;
1206   assert(n);
1207
1208   switch (get_irn_opcode(n)) {
1209   case iro_Const :
1210     /* @@@ some consts have an entity */
1211     break;
1212   case iro_SymConst:
1213     if (   (get_SymConst_kind(n) ==symconst_type_tag)
1214        || (get_SymConst_kind(n) ==symconst_size))
1215       {
1216         print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1217       }
1218     break;
1219   case iro_Sel: {
1220       print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1221     } break;
1222   case iro_Call: {
1223       print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1224     } break;
1225   case iro_Alloc: {
1226       print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1227     } break;
1228   case iro_Free: {
1229       print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1230     } break;
1231   case iro_Cast: {
1232       print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1233     } break;
1234   default:
1235     break;
1236   }
1237 }
1238
1239
1240 static int print_type_info(FILE *F, type *tp) {
1241   int bad = 0;
1242
1243   if (get_type_state(tp) == layout_undefined) {
1244     fprintf(F, "state: layout_undefined\n");
1245   } else {
1246     fprintf(F, "state: layout_fixed,\n");
1247   }
1248   if (get_type_mode(tp))
1249     fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1250   fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1251
1252   return bad;
1253 }
1254
1255 static void print_typespecific_info(FILE *F, type *tp) {
1256   switch (get_type_tpop_code(tp)) {
1257   case tpo_class:
1258     {
1259       fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1260     } break;
1261   case tpo_struct:
1262     {
1263     } break;
1264   case tpo_method:
1265     {
1266       fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1267       fprintf(F, "params: %d\n", get_method_n_params(tp));
1268       fprintf(F, "results: %d\n", get_method_n_ress(tp));
1269     } break;
1270   case tpo_union:
1271     {
1272     } break;
1273   case tpo_array:
1274     {
1275     } break;
1276   case tpo_enumeration:
1277     {
1278     } break;
1279   case tpo_pointer:
1280     {
1281     } break;
1282   case tpo_primitive:
1283     {
1284     } break;
1285   default: break;
1286   } /* switch type */
1287 }
1288
1289
1290 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1291   switch (get_type_tpop_code(tp)) {
1292   case tpo_class:
1293     {
1294       if (peculiarity_existent == get_class_peculiarity(tp))
1295     fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1296       else
1297     fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1298     } break;
1299   case tpo_struct:
1300     {
1301       fprintf (F, " " TYPE_METH_NODE_ATTR);
1302     } break;
1303   case tpo_method:
1304     {
1305     } break;
1306   case tpo_union:
1307     {
1308     } break;
1309   case tpo_array:
1310     {
1311     } break;
1312   case tpo_enumeration:
1313     {
1314     } break;
1315   case tpo_pointer:
1316     {
1317     } break;
1318   case tpo_primitive:
1319     {
1320     } break;
1321   default: break;
1322   } /* switch type */
1323 }
1324
1325 static int print_type_node(FILE *F, type *tp)
1326 {
1327   int bad = 0;
1328
1329   fprintf (F, "node: {title: ");
1330   PRINT_TYPEID(tp);
1331   fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1332   fprintf (F, " info1: \"");
1333   bad |= print_type_info(F, tp);
1334   print_typespecific_info(F, tp);
1335   fprintf (F, "\"");
1336   print_typespecific_vcgattr(F, tp);
1337   fprintf (F, "}\n");
1338
1339   return bad;
1340 }
1341
1342 #define X(a)    case a: fprintf(F, #a); break
1343 void dump_entity_node(FILE *F, entity *ent, int color)
1344 {
1345   fprintf (F, "node: {title: \"");
1346   PRINT_ENTID(ent); fprintf(F, "\"");
1347   fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1348   fprintf (F, "label: ");
1349   fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1350   if (color)
1351     fprintf(F, "color: %d", color);
1352   else
1353     fprintf (F, ENTITY_NODE_ATTR);
1354   fprintf (F, "\n info1: \"");
1355
1356   dump_entity_to_file(F, ent, dump_verbosity_max);
1357
1358   fprintf(F, "\"\n}\n");
1359 }
1360 #undef X
1361
1362 static void dump_enum_item(FILE *F, type *tp, int pos)
1363 {
1364   char buf[1024];
1365   ident *id  = get_enumeration_nameid(tp, pos);
1366   tarval *tv = get_enumeration_enum(tp, pos);
1367
1368   tarval_snprintf(buf, sizeof(buf), tv);
1369   fprintf (F, "node: {title: \"");
1370   PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1371   fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1372   fprintf (F, "label: ");
1373   fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1374   fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1375 }
1376
1377 /* dumps a type or entity and it's edges. */
1378 static void
1379 dump_type_info(type_or_ent *tore, void *env) {
1380   FILE *F = env;
1381   int i = 0;  /* to shutup gcc */
1382
1383   /* dump this type or entity */
1384
1385   switch (get_kind(tore)) {
1386   case k_entity:
1387     {
1388       entity *ent = (entity *)tore;
1389       ir_node *value;
1390       /* The node */
1391       dump_entity_node(F, ent, 0);
1392       /* The Edges */
1393       /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
1394       fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1395                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1396       print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1397       if(is_class_type(get_entity_owner(ent))) {
1398         for(i = 0; i < get_entity_n_overwrites(ent); i++)
1399           print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1400       }
1401       /* attached subgraphs */
1402       if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1403         if (is_atomic_entity(ent)) {
1404           value = get_atomic_ent_value(ent);
1405           if (value) {
1406             print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1407             /* DDMN(value);  $$$ */
1408             dump_const_expression(F, value);
1409           }
1410         }
1411         if (is_compound_entity(ent)) {
1412           for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1413             value = get_compound_ent_value(ent, i);
1414             if (value) {
1415               print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1416               dump_const_expression(F, value);
1417               print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1418               /*
1419               fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1420               ENT_CORR_EDGE_ATTR  "}\n", GET_ENTID(ent),
1421               get_compound_ent_value_member(ent, i), i);
1422               */
1423             }
1424           }
1425         }
1426       }
1427     } break;
1428   case k_type:
1429     {
1430       type *tp = (type *)tore;
1431       print_type_node(F, tp);
1432       /* and now the edges */
1433       switch (get_type_tpop_code(tp)) {
1434       case tpo_class:
1435         {
1436           for (i=0; i < get_class_n_supertypes(tp); i++)
1437             print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1438           for (i=0; i < get_class_n_members(tp); i++)
1439             print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1440         } break;
1441       case tpo_struct:
1442         {
1443           for (i=0; i < get_struct_n_members(tp); i++)
1444             print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1445         } break;
1446       case tpo_method:
1447         {
1448           for (i = 0; i < get_method_n_params(tp); i++)
1449             print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1450           for (i = 0; i < get_method_n_ress(tp); i++)
1451             print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1452         } break;
1453       case tpo_union:
1454         {
1455           for (i = 0; i < get_union_n_members(tp); i++)
1456             print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1457         } break;
1458       case tpo_array:
1459         {
1460           print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1461           print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1462           for (i = 0; i < get_array_n_dimensions(tp); i++) {
1463             ir_node *upper = get_array_upper_bound(tp, i);
1464             ir_node *lower = get_array_lower_bound(tp, i);
1465             print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1466             print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1467             dump_const_expression(F, upper);
1468             dump_const_expression(F, lower);
1469           }
1470
1471         } break;
1472       case tpo_enumeration:
1473         {
1474           for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1475             dump_enum_item(F, tp, i);
1476             print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1477           }
1478         } break;
1479       case tpo_pointer:
1480         {
1481           print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1482         } break;
1483       case tpo_primitive:
1484         {
1485         } break;
1486       default: break;
1487       } /* switch type */
1488     }
1489     break; /* case k_type */
1490   default:
1491     {
1492       printf(" *** irdump,  dump_type_info(l.%i), faulty type.\n", __LINE__);
1493     } break;
1494   } /* switch kind_or_entity */
1495 }
1496
1497 typedef struct _h_env {
1498   int dump_ent;
1499   FILE *f;
1500 } h_env_t;
1501
1502 /** For dumping class hierarchies.
1503  * Dumps a class type node and a superclass edge.
1504  * If env->dump_ent dumps entities of classes and overwrites edges.
1505  */
1506 static void
1507 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1508   h_env_t *env = ctx;
1509   FILE *F = env->f;
1510   int i = 0;  /* to shutup gcc */
1511
1512   /* dump this type or entity */
1513   switch (get_kind(tore)) {
1514   case k_entity: {
1515     entity *ent = (entity *)tore;
1516     if (get_entity_owner(ent) == get_glob_type()) break;
1517     if (!is_method_type(get_entity_type(ent))) break;  /* GL */
1518     if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1519       /* The node */
1520       dump_entity_node(F, ent, 0);
1521       /* The edges */
1522       print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1523       for(i = 0; i < get_entity_n_overwrites(ent); i++)
1524         print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1525     }
1526   } break; /* case k_entity */
1527   case k_type:
1528     {
1529       type *tp = (type *)tore;
1530       if (tp == get_glob_type()) break;
1531       switch (get_type_tpop_code(tp)) {
1532         case tpo_class: {
1533           print_type_node(F, tp);
1534           /* and now the edges */
1535           for (i=0; i < get_class_n_supertypes(tp); i++)
1536           {
1537               print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1538           }
1539         } break;
1540         default: break;
1541       } /* switch type */
1542     }
1543     break; /* case k_type */
1544   default:
1545     {
1546       printf(" *** irdump,  dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1547     } break;
1548   } /* switch kind_or_entity */
1549 }
1550
1551 /*******************************************************************/
1552 /* dump analysis information that is expressed in graph terms.     */
1553 /*******************************************************************/
1554
1555 /* dump out edges */
1556 static void
1557 dump_out_edge(ir_node *n, void *env) {
1558   FILE *F = env;
1559   int i;
1560   for (i = 0; i < get_irn_n_outs(n); i++) {
1561     assert(get_irn_out(n, i));
1562     fprintf (F, "edge: {sourcename: \"");
1563     PRINT_NODEID(n);
1564     fprintf (F, "\" targetname: \"");
1565     PRINT_NODEID(get_irn_out(n, i));
1566     fprintf (F, "\" color: red linestyle: dashed");
1567     fprintf (F, "}\n");
1568   }
1569 }
1570
1571 static INLINE void
1572 dump_loop_label(FILE *F, ir_loop *loop) {
1573   fprintf (F, "loop %d, %d sons, %d nodes",
1574        get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1575 }
1576
1577 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1578   fprintf (F, " info1: \"");
1579   fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1580 #if DEBUG_libfirm   /* GL @@@ debug analyses */
1581   fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1582 #endif
1583   fprintf (F, "\"");
1584 }
1585
1586 static INLINE void
1587 dump_loop_node(FILE *F, ir_loop *loop) {
1588   fprintf (F, "node: {title: \"");
1589   PRINT_LOOPID(loop);
1590   fprintf (F, "\" label: \"");
1591   dump_loop_label(F, loop);
1592   fprintf (F, "\" ");
1593   dump_loop_info(F, loop);
1594   fprintf (F, "}\n");
1595
1596 }
1597
1598 static INLINE void
1599 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1600   assert(loop);
1601   fprintf (F, "edge: {sourcename: \"");
1602   PRINT_LOOPID(loop);
1603   fprintf (F, "\" targetname: \"");
1604   PRINT_NODEID(get_loop_node(loop, i));
1605   fprintf (F, "\" color: green");
1606   fprintf (F, "}\n");
1607 }
1608
1609 static INLINE void
1610 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1611   assert(loop);
1612   fprintf (F, "edge: {sourcename: \"");
1613   PRINT_LOOPID(loop);
1614   fprintf (F, "\" targetname: \"");
1615   PRINT_LOOPID(get_loop_son(loop, i));
1616   fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1617        get_loop_element_pos(loop, get_loop_son(loop, i)));
1618 }
1619
1620 static
1621 void dump_loops(FILE *F, ir_loop *loop) {
1622   int i;
1623   /* dump this loop node */
1624   dump_loop_node(F, loop);
1625
1626   /* dump edges to nodes in loop -- only if it is a real loop */
1627   if (get_loop_depth(loop) != 0) {
1628     for (i = 0; i < get_loop_n_nodes(loop); i++) {
1629       dump_loop_node_edge(F, loop, i);
1630     }
1631   }
1632   for (i = 0; i < get_loop_n_sons(loop); i++) {
1633     dump_loops(F, get_loop_son(loop, i));
1634     dump_loop_son_edge(F, loop, i);
1635   }
1636 }
1637
1638 static INLINE
1639 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1640   ir_graph *rem = current_ir_graph;
1641   current_ir_graph = irg;
1642
1643   if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1644
1645   current_ir_graph = rem;
1646 }
1647
1648
1649 /**
1650  * dumps the VCG header
1651  */
1652 static INLINE void
1653 dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1654   char *label;
1655
1656   if (edge_label) {
1657     label = "yes";
1658   } else {
1659     label = "no";
1660   }
1661
1662   if (!orientation) orientation = "bottom_to_top";
1663
1664   /* print header */
1665   fprintf (F,
1666        "graph: { title: \"ir graph of %s\"\n"
1667        "display_edge_labels: %s\n"
1668        "layoutalgorithm: mindepth\n"
1669        "manhattan_edges: yes\n"
1670        "port_sharing: no\n"
1671        "orientation: %s\n"
1672        "classname 1:  \"intrablock Data\"\n"
1673        "classname 16: \"interblock Data\"\n"
1674        "classname 2:  \"Block\"\n"
1675        "classname 13: \"Control Flow\"\n"
1676        "classname 14: \"intrablock Memory\"\n"
1677        "classname 17: \"interblock Memory\"\n"
1678        "classname 15: \"Dominators\"\n"
1679        "classname 3:  \"Entity type\"\n"
1680        "classname 4:  \"Entity owner\"\n"
1681        "classname 5:  \"Method Param\"\n"
1682        "classname 6:  \"Method Res\"\n"
1683        "classname 7:  \"Super\"\n"
1684        "classname 8:  \"Union\"\n"
1685        "classname 9:  \"Points-to\"\n"
1686        "classname 10: \"Array Element Type\"\n"
1687        "classname 11: \"Overwrites\"\n"
1688        "classname 12: \"Member\"\n"
1689        "infoname 1: \"Attribute\"\n"
1690        "infoname 2: \"Verification errors\"\n",
1691        name, label, orientation);
1692
1693   /* don't use all, the range is too whith/black. */
1694   n_colors   = 18;
1695   base_color = 105;
1696   fprintf (F,
1697        "colorentry 100:    0   0    0\n"
1698        "colorentry 101:   20   0    0\n"
1699        "colorentry 102:   40   0    0\n"
1700        "colorentry 103:   60   0    0\n"
1701        "colorentry 104:   80   0    0\n"
1702        "colorentry 105:  100   0    0\n"
1703        "colorentry 106:  120   0    0\n"
1704        "colorentry 107:  140   0    0\n"
1705        "colorentry 108:  150   0    0\n"
1706        "colorentry 109:  180   0    0\n"
1707        "colorentry 110:  200   0    0\n"
1708        "colorentry 111:  220   0    0\n"
1709        "colorentry 112:  240   0    0\n"
1710        "colorentry 113:  255   0    0\n"
1711        "colorentry 113:  255  20   20\n"
1712        "colorentry 114:  255  40   40\n"
1713        "colorentry 115:  255  60   60\n"
1714        "colorentry 116:  255  80   80\n"
1715        "colorentry 117:  255 100  100\n"
1716        "colorentry 118:  255 120  120\n"
1717        "colorentry 119:  255 140  140\n"
1718        "colorentry 120:  255 150  150\n"
1719        "colorentry 121:  255 180  180\n"
1720        "colorentry 122:  255 200  200\n"
1721        "colorentry 123:  255 220  220\n"
1722        "colorentry 124:  255 240  240\n"
1723        "colorentry 125:  255 250  250\n"
1724            );
1725
1726   fprintf (F, "\n");        /* a separator */
1727 }
1728
1729 /**
1730  * open a vcg file
1731  *
1732  * @param irg     The graph to be dumped
1733  * @param suffix1 first filename suffix
1734  * @param suffix2 second filename suffix
1735  */
1736 static FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1737   FILE *F;
1738   const char *nm = get_irg_dump_name(irg);
1739   int len = strlen(nm), i, j;
1740   char *fname;  /* filename to put the vcg information in */
1741
1742   if (!suffix1) suffix1 = "";
1743   if (!suffix2) suffix2 = "";
1744
1745   /* open file for vcg graph */
1746   fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1747
1748   /* strncpy (fname, nm, len); */     /* copy the filename */
1749   j = 0;
1750   for (i = 0; i < len; ++i) {  /* replase '/' in the name: escape by @. */
1751     if (nm[i] == '/') {
1752       fname[j] = '@'; j++; fname[j] = '1'; j++;
1753     } else if (nm[i] == '@') {
1754       fname[j] = '@'; j++; fname[j] = '2'; j++;
1755     } else {
1756       fname[j] = nm[i]; j++;
1757     }
1758   }
1759   fname[j] = '\0';
1760   strcat (fname, suffix1);  /* append file suffix */
1761   strcat (fname, suffix2);  /* append file suffix */
1762   strcat (fname, ".vcg");   /* append the .vcg suffix */
1763   F = fopen (fname, "w");   /* open file for writing */
1764   if (!F) {
1765     panic("cannot open %s for writing (%m)", fname);  /* not reached */
1766   }
1767   free(fname);
1768
1769   return F;
1770 }
1771
1772 /**
1773  * open a vcg file
1774  *
1775  * @param irg     The graph to be dumped
1776  * @param suffix  filename suffix
1777  */
1778 static FILE *vcg_open_name (const char *name, const char *suffix) {
1779   FILE *F;
1780   char *fname;  /* filename to put the vcg information in */
1781   int i, j, len = strlen(name);
1782
1783   if (!suffix) suffix = "";
1784
1785   /** open file for vcg graph */
1786   fname = malloc (len * 2 + 5 + strlen(suffix));
1787   /* strcpy (fname, name);*/    /* copy the filename */
1788   j = 0;
1789   for (i = 0; i < len; ++i) {  /* replase '/' in the name: escape by @. */
1790     if (name[i] == '/') {
1791       fname[j] = '@'; j++; fname[j] = '1'; j++;
1792     } else if (name[i] == '@') {
1793       fname[j] = '@'; j++; fname[j] = '2'; j++;
1794     } else {
1795       fname[j] = name[i]; j++;
1796     }
1797   }
1798   fname[j] = '\0';
1799   strcat (fname, suffix);
1800   strcat (fname, ".vcg");  /* append the .vcg suffix */
1801   F = fopen (fname, "w");  /* open file for writing */
1802   if (!F) {
1803     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
1804   }
1805   free(fname);
1806
1807   return F;
1808 }
1809
1810 /**
1811  * Dumps the vcg file footer
1812  */
1813 static INLINE void dump_vcg_footer (FILE *F) {
1814   fprintf (F, "}\n");
1815 }
1816
1817 /**
1818  * close the vcg file
1819  */
1820 static void
1821 vcg_close (FILE *F) {
1822   dump_vcg_footer(F);    /* print footer */
1823   fclose (F);           /* close vcg file */
1824 }
1825
1826 /************************************************************************/
1827 /************************************************************************/
1828 /* Routines that dump all or parts of the firm representation to a file */
1829 /************************************************************************/
1830 /************************************************************************/
1831
1832 /************************************************************************/
1833 /* Dump ir graphs, differnt formats and additional information.         */
1834 /************************************************************************/
1835
1836 /** Routine to dump a graph, blocks as conventional nodes.
1837  */
1838 void
1839 dump_ir_graph (ir_graph *irg, const char *suffix )
1840 {
1841   FILE *f;
1842   ir_graph *rem;
1843   char *suffix1;
1844   rem = current_ir_graph;
1845
1846   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1847   current_ir_graph = irg;
1848   if (interprocedural_view) suffix1 = "-pure-ip";
1849   else                      suffix1 = "-pure";
1850   f = vcg_open(irg, suffix, suffix1);
1851   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1852
1853   /* walk over the graph */
1854   /* dump_whole_node must be called in post visiting predecessors */
1855   irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1856
1857   /* dump the out edges in a separate walk */
1858   if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1859     irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1860   }
1861
1862   vcg_close(f);
1863
1864   current_ir_graph = rem;
1865 }
1866
1867
1868 void
1869 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1870 {
1871   FILE *f;
1872   int i;
1873   char *suffix1;
1874
1875   if(strncmp(get_entity_name(get_irg_entity(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1876   if (interprocedural_view) suffix1 = "-ip";
1877   else                      suffix1 = "";
1878   f = vcg_open(irg, suffix, suffix1);
1879   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1880
1881   construct_block_lists(irg);
1882
1883   for (i = 0; i < get_irp_n_irgs(); i++) {
1884     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1885     if (arr) {
1886       dump_graph(f, get_irp_irg(i));
1887       DEL_ARR_F(arr);
1888     }
1889   }
1890
1891   vcg_close(f);
1892 }
1893
1894 /** dumps a graph with type information
1895  */
1896 void
1897 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1898 {
1899   FILE *f;
1900   ir_graph *rem = current_ir_graph;
1901   char *suffix1;
1902
1903   /* if a filter is set, dump only the irg's that match the filter */
1904   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1905     return;
1906
1907   current_ir_graph = irg;
1908
1909   if (interprocedural_view) suffix1 = "-pure-wtypes-ip";
1910   else                      suffix1 = "-pure-wtypes";
1911   f = vcg_open(irg,suffix, suffix1);
1912   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1913
1914   /* dump common ir graph */
1915   irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1916   /* dump type info */
1917   type_walk_irg(irg, dump_type_info, NULL, f);
1918   inc_irg_visited(get_const_code_irg());
1919   /* dump edges from graph to type info */
1920   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1921
1922   vcg_close(f);
1923   current_ir_graph = rem;
1924 }
1925
1926 void
1927 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1928 {
1929   FILE *f;
1930   int i;
1931   char *suffix1;
1932   ir_graph *rem = current_ir_graph;
1933
1934   /* if a filter is set, dump only the irg's that match the filter */
1935   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1936     return;
1937
1938   if (interprocedural_view) suffix1 = "-wtypes-ip";
1939   else                      suffix1 = "-wtypes";
1940   f = vcg_open(irg, suffix, suffix1);
1941   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1942
1943   /* dump common blocked ir graph */
1944   construct_block_lists(irg);
1945
1946   for (i = 0; i < get_irp_n_irgs(); i++) {
1947     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1948     if (arr) {
1949       dump_graph(f, get_irp_irg(i));
1950       DEL_ARR_F(arr);
1951     }
1952   }
1953
1954   /* dump type info */
1955   current_ir_graph = irg;
1956   type_walk_irg(irg, dump_type_info, NULL, f);
1957   inc_irg_visited(get_const_code_irg());
1958
1959   /* dump edges from graph to type info */
1960   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1961
1962   current_ir_graph = rem;
1963   vcg_close(f);
1964 }
1965
1966 /***********************************************************************/
1967 /* The following routines dump a control flow graph.                   */
1968 /***********************************************************************/
1969
1970 static void
1971 dump_block_to_cfg(ir_node *block, void *env) {
1972   FILE *F = env;
1973   int i;
1974   ir_node *pred;
1975
1976   if (is_Block(block)) {
1977     /* This is a block. Dump a node for the block. */
1978     fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1979     fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1980     PRINT_NODEID(block);
1981     fprintf (F, "\" ");
1982     if (dump_dominator_information_flag)
1983       fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1984     fprintf (F, "}\n");
1985     /* Dump the edges */
1986     for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1987       if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1988     pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1989     fprintf (F, "edge: { sourcename: \"");
1990     PRINT_NODEID(block);
1991     fprintf (F, "\" targetname: \"");
1992     PRINT_NODEID(pred);
1993     fprintf (F, "\"}\n");
1994       }
1995
1996     /* Dump dominator edge */
1997     if (dump_dominator_information_flag && get_Block_idom(block)) {
1998       pred = get_Block_idom(block);
1999       fprintf (F, "edge: { sourcename: \"");
2000       PRINT_NODEID(block);
2001       fprintf (F, "\" targetname: \"");
2002       PRINT_NODEID(pred);
2003       fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2004     }
2005   }
2006 }
2007
2008 void
2009 dump_cfg (ir_graph *irg, const char *suffix)
2010 {
2011   FILE *f;
2012   ir_graph *rem = current_ir_graph;
2013   int ddif = dump_dominator_information_flag;
2014   int ipv = interprocedural_view;
2015
2016   /* if a filter is set, dump only the irg's that match the filter */
2017   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2018     return;
2019
2020   current_ir_graph = irg;
2021
2022   f = vcg_open(irg, suffix, "-cfg");
2023   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2024
2025   if (interprocedural_view) {
2026     printf("Warning: dumping cfg not in interprocedural view!\n");
2027     interprocedural_view = 0;
2028   }
2029
2030   if (get_irg_dom_state(irg) != dom_consistent)
2031     dump_dominator_information_flag = 0;
2032
2033   /* walk over the blocks in the graph */
2034   irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2035   dump_node(f, get_irg_bad(irg));
2036
2037   dump_dominator_information_flag = ddif;
2038   interprocedural_view = ipv;
2039   vcg_close(f);
2040   current_ir_graph = rem;
2041 }
2042
2043 static int weight_overall(int rec, int loop) {
2044   return 2*rec + loop;
2045 }
2046
2047 static int compute_color (int my, int max) {
2048   int color;
2049   if (!max) {
2050     color = 0;
2051   } else {
2052     /* if small, scale to the full color range. */
2053     if (max < n_colors)
2054       my = my * (n_colors/max);
2055
2056     int step = 1 + (max / n_colors);
2057
2058     color = my/step;
2059   }
2060   return base_color + n_colors - color;
2061 }
2062
2063 static int get_entity_color(entity *ent) {
2064   assert(get_entity_irg(ent));
2065   ir_graph *irg = get_entity_irg(ent);
2066
2067   int rec_depth     = get_irg_recursion_depth(irg);
2068   int loop_depth    = get_irg_loop_depth(irg);
2069   int overall_depth = weight_overall(rec_depth, loop_depth);
2070
2071   int max_rec_depth     = irp->max_callgraph_recursion_depth;
2072   int max_loop_depth    = irp->max_callgraph_loop_depth;
2073   int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2074
2075   int my_rec_color     = compute_color(rec_depth, max_rec_depth);
2076   int my_loop_color    = compute_color(loop_depth, max_loop_depth);
2077   int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2078
2079   return my_overall_color;
2080 }
2081
2082 void dump_callgraph(const char *suffix) {
2083   FILE *F;
2084   int i, n_irgs = get_irp_n_irgs();
2085   int rem = edge_label;
2086   edge_label = 1;
2087   //ident *prefix = new_id_from_str("java/");
2088
2089   F = vcg_open_name("Callgraph", suffix);
2090   dump_vcg_header(F, "Callgraph", NULL);
2091
2092   for (i = 0; i < n_irgs; ++i) {
2093     ir_graph *irg = get_irp_irg(i);
2094     entity *ent = get_irg_entity(irg);
2095     int j, n_callees = get_irg_n_callees(irg);
2096
2097     /* Do not dump runtime system. */
2098     //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2099
2100     dump_entity_node(F, ent, get_entity_color(ent));
2101     for (j = 0; j < n_callees; ++j) {
2102       entity *c = get_irg_entity(get_irg_callee(irg, j));
2103       //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2104       int be = is_irg_callee_backedge(irg, j);
2105       char *attr;
2106       attr = (be) ?
2107         "label:\"recursion %d\" color: %d" :
2108         "label:\"calls %d\" color: %d";
2109       print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2110     }
2111   }
2112
2113   edge_label = rem;
2114   vcg_close(F);
2115 }
2116
2117 /* Dump all irgs in interprocedural view to a single file. */
2118 void dump_all_cg_block_graph(const char *suffix) {
2119   FILE *f;
2120   int i;
2121   int rem_view = interprocedural_view;
2122   interprocedural_view = 1;
2123
2124   f = vcg_open_name("All_graphs", suffix);
2125   dump_vcg_header(f, "All_graphs", NULL);
2126
2127   /* collect nodes in all irgs reachable in call graph*/
2128   for (i = 0; i < get_irp_n_irgs(); i++)
2129     ird_set_irg_link(get_irp_irg(i), NULL);
2130
2131   cg_walk(clear_link, collect_node, NULL);
2132
2133   /* dump all graphs */
2134   for (i = 0; i < get_irp_n_irgs(); i++) {
2135     current_ir_graph = get_irp_irg(i);
2136     assert(ird_get_irg_link(current_ir_graph));
2137     dump_graph(f, current_ir_graph);
2138     DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2139   }
2140
2141   vcg_close(f);
2142   interprocedural_view = rem_view;
2143 }
2144
2145 /***********************************************************************/
2146 /* the following routines dumps type information without any ir nodes. */
2147 /***********************************************************************/
2148
2149 void
2150 dump_type_graph (ir_graph *irg, const char *suffix)
2151 {
2152   FILE *f;
2153   ir_graph *rem;
2154   rem = current_ir_graph;
2155
2156   /* if a filter is set, dump only the irg's that match the filter */
2157   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2158
2159   current_ir_graph = irg;
2160
2161   f = vcg_open(irg, suffix, "-type");
2162   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2163
2164   /* walk over the blocks in the graph */
2165   type_walk_irg(irg, dump_type_info, NULL, f);
2166   /* The walker for the const code can be called several times for the
2167      same (sub) experssion.  So that no nodes are dumped several times
2168      we decrease the visited flag of the corresponding graph after each
2169      walk.  So now increase it finally. */
2170   inc_irg_visited(get_const_code_irg());
2171
2172   vcg_close(f);
2173   current_ir_graph = rem;
2174 }
2175
2176 void
2177 dump_all_types (const char *suffix)
2178 {
2179   FILE *f = vcg_open_name("All_types", suffix);
2180   dump_vcg_header(f, "All_types", NULL);
2181   type_walk(dump_type_info, NULL, f);
2182   inc_irg_visited(get_const_code_irg());
2183   vcg_close(f);
2184 }
2185
2186 void
2187 dump_class_hierarchy (bool entities, const char *suffix)
2188 {
2189   FILE *f = vcg_open_name("class_hierarchy", suffix);
2190   h_env_t env;
2191
2192   env.f = f;
2193   dump_vcg_header(f, "class_hierarchy", NULL);
2194   if (entities)
2195     env.dump_ent = 1;
2196   else
2197     env.dump_ent = 0;
2198   type_walk(dump_class_hierarchy_node, NULL, &env);
2199   vcg_close(f);
2200 }
2201
2202 /***********************************************************************/
2203 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
2204 /*  dump_ir_graph                                                      */
2205 /*  dump_ir_block_graph                                                */
2206 /*  dump_cfg                                                           */
2207 /*  dump_type_graph                                                    */
2208 /*  dump_ir_graph_w_types                                              */
2209 /***********************************************************************/
2210
2211 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2212   int i;
2213   for (i=0; i < get_irp_n_irgs(); i++) {
2214     dmp_grph(get_irp_irg(i), suffix);
2215   }
2216 }
2217
2218
2219 /**********************************************************************************
2220  * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes  *
2221  * packed together in one subgraph/box                                            *
2222  **********************************************************************************/
2223
2224 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2225   int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2226   loop_element le;
2227   ir_loop *son = NULL;
2228
2229   /* Dump a new loop node. */
2230   dump_loop_node(F, loop);
2231
2232   /* Dump the loop elements. */
2233
2234   for(i = 0; i < get_loop_n_elements(loop); i++) {
2235     le = get_loop_element(loop, i);
2236     son = le.son;
2237     if (get_kind(son) == k_ir_loop) {
2238
2239       /* We are a loop son -> Recurse */
2240
2241       if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2242         fprintf(F, "\" }\n");
2243         fprintf (F, "edge: {sourcename: \"");
2244         PRINT_LOOPID(loop);
2245         fprintf (F, "\" targetname: \"");
2246         PRINT_LOOPID(loop);
2247         fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2248         loop_node_started = 0;
2249       }
2250       dump_loop_son_edge(F, loop, son_number++);
2251       dump_loops_standalone(F, son);
2252     } else if (get_kind(son) == k_ir_node) {
2253         /* We are a loop node -> Collect firm nodes */
2254
2255       ir_node *n = le.node;
2256       int bad = 0;
2257
2258       if (!loop_node_started) {
2259         /* Start a new node which contains all firm nodes of the current loop */
2260         fprintf (F, "node: { title: \"");
2261         PRINT_LOOPID(loop);
2262         fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2263         loop_node_started = 1;
2264         first = i;
2265       }
2266       else
2267         fprintf(F, "\n");
2268
2269       bad |= dump_node_opcode(F, n);
2270       bad |= dump_node_mode(F, n);
2271       bad |= dump_node_typeinfo(F, n);
2272       fprintf (F, " ");
2273       bad |= dump_node_nodeattr(F, n);
2274       fprintf (F, " %ld", get_irn_node_nr(n));
2275       if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n));
2276     } else { /* for callgraph loop tree */
2277       assert(get_kind(son) == k_ir_graph);
2278       /* We are a loop node -> Collect firm graphs */
2279       ir_graph *n = (ir_graph *)le.node;
2280       if (!loop_node_started) {
2281         /* Start a new node which contains all firm nodes of the current loop */
2282         fprintf (F, "node: { title: \"");
2283         PRINT_LOOPID(loop);
2284         fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2285         loop_node_started = 1;
2286         first = i;
2287       }
2288       else
2289         fprintf(F, "\n");
2290       fprintf (F, " %s", get_irg_dump_name(n));
2291       /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2292     }
2293   }
2294
2295   if (loop_node_started) {
2296     fprintf(F, "\" }\n");
2297     fprintf (F, "edge: {sourcename: \"");
2298     PRINT_LOOPID(loop);
2299     fprintf (F, "\" targetname: \"");
2300     PRINT_LOOPID(loop);
2301     fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2302     loop_node_started = 0;
2303   }
2304 }
2305
2306 void dump_loop_tree(ir_graph *irg, const char *suffix)
2307 {
2308   FILE *f;
2309   ir_graph *rem = current_ir_graph;
2310   int el_rem = edge_label;
2311   edge_label = 1;
2312
2313   /* if a filter is set, dump only the irg's that match the filter */
2314   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2315     return;
2316
2317   current_ir_graph = irg;
2318
2319   f = vcg_open(irg, suffix, "-looptree");
2320   dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2321
2322   if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2323
2324   vcg_close(f);
2325
2326   edge_label = el_rem;
2327   current_ir_graph = rem;
2328 }
2329
2330 void dump_callgraph_loop_tree(const char *suffix) {
2331   FILE *F;
2332   F = vcg_open_name("Callgraph_looptree", suffix);
2333   dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2334   dump_loops_standalone(F, irp->outermost_cg_loop);
2335   vcg_close(F);
2336 }
2337
2338
2339 /*******************************************************************************/
2340 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2341 /*******************************************************************************/
2342
2343 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2344   int i, son_number = 0, node_number = 0;
2345
2346   if (dump_loop_information_flag) dump_loop_node(F, loop);
2347
2348   for (i = 0; i < get_loop_n_elements(loop); i++) {
2349     loop_element le = get_loop_element(loop, i);
2350     if (*(le.kind) == k_ir_loop) {
2351       if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2352       /* Recur */
2353       collect_nodeloop(F, le.son, loopnodes);
2354     } else {
2355       if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2356       eset_insert(loopnodes, le.node);
2357     }
2358   }
2359 }
2360
2361 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2362   int i, j, start;
2363
2364   for(i = 0; i < get_loop_n_elements(loop); i++) {
2365     loop_element le = get_loop_element(loop, i);
2366     if (*(le.kind) == k_ir_loop) {
2367       /* Recur */
2368       collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2369     } else {
2370       if (is_Block(le.node)) start = 0; else start = -1;
2371       for (j = start; j < get_irn_arity(le.node); j++) {
2372         ir_node *pred = get_irn_n(le.node, j);
2373         if (!eset_contains(loopnodes, pred)) {
2374           eset_insert(extnodes, pred);
2375           if (!is_Block(pred)) {
2376             pred = get_nodes_block(pred);
2377             if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2378           }
2379         }
2380       }
2381     }
2382   }
2383 }
2384
2385 void dump_loop(ir_loop *l, const char *suffix) {
2386   FILE *F;
2387   char name[50];
2388   eset *loopnodes = eset_create();
2389   eset *extnodes = eset_create();
2390   ir_node *n, *b;
2391
2392   snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2393   F = vcg_open_name (name, suffix);
2394   dump_vcg_header(F, name, NULL);
2395
2396   /* collect all nodes to dump */
2397   collect_nodeloop(F, l, loopnodes);
2398   collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2399
2400   /* build block lists */
2401   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2402     set_irn_link(n, NULL);
2403   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2404     set_irn_link(n, NULL);
2405   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2406     if (!is_Block(n)) {
2407       b = get_nodes_block(n);
2408       set_irn_link(n, get_irn_link(b));
2409       set_irn_link(b, n);
2410     }
2411   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2412     if (!is_Block(n)) {
2413       b = get_nodes_block(n);
2414       set_irn_link(n, get_irn_link(b));
2415       set_irn_link(b, n);
2416     }
2417
2418   for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2419     if (is_Block(b)) {
2420       fprintf(F, "graph: { title: \"");
2421       PRINT_NODEID(b);
2422       fprintf(F, "\"  label: \"");
2423       dump_node_opcode(F, b);
2424       fprintf (F, " %ld", get_irn_node_nr(b));
2425       fprintf(F, "\" status:clustered color:yellow\n");
2426
2427       /* dump the blocks edges */
2428       dump_ir_data_edges(F, b);
2429
2430       /* dump the nodes that go into the block */
2431       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2432         if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2433         dump_node(F, n);
2434         overrule_nodecolor = NULL;
2435         if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2436       }
2437
2438       /* Close the vcg information for the block */
2439       fprintf(F, "}\n");
2440       dump_const_node_local(F, b);
2441       fprintf(F, "\n");
2442     }
2443   for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2444     if (is_Block(b)) {
2445       fprintf(F, "graph: { title: \"");
2446       PRINT_NODEID(b);
2447       fprintf(F, "\"  label: \"");
2448       dump_node_opcode(F, b);
2449       fprintf (F, " %ld", get_irn_node_nr(b));
2450       fprintf(F, "\" status:clustered color:lightblue\n");
2451
2452       /* dump the nodes that go into the block */
2453       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2454         if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2455         dump_node(F, n);
2456         overrule_nodecolor = NULL;
2457         if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2458       }
2459
2460       /* Close the vcg information for the block */
2461       fprintf(F, "}\n");
2462       dump_const_node_local(F, b);
2463       fprintf(F, "\n");
2464     }
2465
2466   eset_destroy(loopnodes);
2467   eset_destroy(extnodes);
2468   vcg_close(F);
2469 }