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