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