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