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