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