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