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