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