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