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