9f94510468024c7ff2d4252491d88406cada2bcf
[libfirm] / ir / ir / irdump.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   Write vcg representation of firm to file.
23  * @author  Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Hubert Schmidt
24  * @version $Id$
25  */
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #ifdef HAVE_STRING_H
31 #include <string.h>
32 #endif
33 #ifdef HAVE_STDLIB_H
34 #include <stdlib.h>
35 #endif
36 #include <stdarg.h>
37
38 #include "firm_common_t.h"
39
40 #include "list.h"
41
42 #include "irnode_t.h"
43 #include "irgraph_t.h"
44 #include "irprog_t.h"
45 #include "entity_t.h"
46 #include "irop.h"
47
48 #include "irdump_t.h"
49
50 #include "irgwalk.h"
51 #include "tv_t.h"
52 #include "irouts.h"
53 #include "iredges.h"
54 #include "irdom.h"
55 #include "irloop_t.h"
56 #include "callgraph.h"
57 #include "irextbb_t.h"
58 #include "irhooks.h"
59 #include "dbginfo_t.h"
60 #include "irtools.h"
61 #include "irprintf.h"
62
63 #include "irvrfy.h"
64
65 #include "error.h"
66 #include "array.h"
67 #include "pmap.h"
68 #include "eset.h"
69 #include "pset.h"
70
71 #if DO_HEAPANALYSIS
72 extern void dump_irn_chi_term(FILE *FL, ir_node *n);
73 extern void dump_irn_state(FILE *FL, ir_node *n);
74 extern int  get_opt_dump_abstvals(void);
75 typedef unsigned long SeqNo;
76 extern SeqNo get_Block_seqno(ir_node *n);
77 #endif
78
79 /** Dump only irgs with names that start with this prefix. */
80 static ident *dump_file_filter_id = NULL;
81
82 #define ERROR_TXT       "<ERROR>"
83
84 /*******************************************************************/
85 /* flags to steer output                                           */
86 /*******************************************************************/
87
88 /** An option to turn off edge labels */
89 static int edge_label = 1;
90 /** An option to turn off dumping values of constant entities */
91 static int const_entities = 1;
92 /** An option to dump the keep alive edges */
93 static int dump_keepalive = 1;
94 /** An option to dump the new out edges */
95 static int dump_new_edges_flag = 0;
96 /** An option to dump ld_names instead of names. */
97 static int dump_ld_name = 1;
98 /** Compiler options to dump analysis information in dump_ir_graph */
99 static int dump_out_edge_flag = 0;
100 static int dump_loop_information_flag = 0;
101 static int dump_backedge_information_flag = 1;
102 /** An option to dump const-like nodes locally. */
103 static int dump_const_local = 1;
104 /** An option to dump the node index number. */
105 static int dump_node_idx_labels = 0;
106 /** An option to dump all graph anchors */
107 static int dump_anchors = 0;
108 /** An option to dump the macro block edges. */
109 static int dump_macro_block_edges = 0;
110 /** An option to dump block marker in the block title */
111 static int dump_block_marker = 0;
112
113 int dump_dominator_information_flag = 0;
114 int opt_dump_analysed_type_info = 1;
115 int opt_dump_pointer_values_to_info = 0;  /* default off: for test compares!! */
116
117 static ird_color_t overrule_nodecolor = ird_color_default_node;
118
119 /** The vcg node attribute hook. */
120 static DUMP_IR_GRAPH_FUNC dump_ir_graph_hook = NULL;
121 /** The vcg node attribute hook. */
122 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
123 /** The vcg edge attribute hook. */
124 static DUMP_EDGE_VCGATTR_FUNC dump_edge_vcgattr_hook = NULL;
125 /** The vcg dump block edge hook */
126 static DUMP_NODE_EDGE_FUNC dump_block_edge_hook = NULL;
127 /** The vcg dump node edge hook. */
128 static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
129
130 /* Set the hook to be called to dump additional edges to a node. */
131 void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func) {
132         dump_node_edge_hook = func;
133 }
134
135 /* Get the additional edge dump hook. */
136 DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void) {
137         return dump_node_edge_hook;
138 }
139
140 /* Set the hook to be called to dump additional edges to a block. */
141 void set_dump_block_edge_hook(DUMP_NODE_EDGE_FUNC func) {
142         dump_block_edge_hook = func;
143 }
144
145 /* Get the additional block edge dump hook. */
146 DUMP_NODE_EDGE_FUNC get_dump_block_edge_hook(void) {
147         return dump_node_edge_hook;
148 }
149
150 /* set the ir graph hook */
151 void set_dump_ir_graph_hook(DUMP_IR_GRAPH_FUNC hook) {
152         dump_ir_graph_hook = hook;
153 }
154
155 /* set the node attribute hook */
156 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
157         dump_node_vcgattr_hook = hook;
158 }
159
160 /* set the edge attribute hook */
161 void set_dump_edge_vcgattr_hook(DUMP_EDGE_VCGATTR_FUNC hook) {
162         dump_edge_vcgattr_hook = hook;
163 }
164
165 /** Returns 0 if dump_out_edge_flag or dump_loop_information_flag
166  * are set, else returns dump_const_local_flag.
167  */
168 static int get_opt_dump_const_local(void) {
169         if (dump_out_edge_flag || dump_loop_information_flag || (dump_new_edges_flag && edges_activated(current_ir_graph)))
170                 return 0;
171         return dump_const_local;
172 }
173
174 /* Set a prefix filter for output functions. */
175 void only_dump_method_with_name(ident *name) {
176         dump_file_filter_id = name;
177 }
178
179 /* Returns the prefix filter set with only_dump_method_with_name(). */
180 ident *get_dump_file_filter_ident(void) {
181         return dump_file_filter_id;
182 }
183
184 /* Returns non-zero if dump file filter is not set, or if it is a prefix of name. */
185 int is_filtered_dump_name(ident *name) {
186         if (!dump_file_filter_id) return 1;
187         return id_is_prefix(dump_file_filter_id, name);
188 }
189
190 /* To turn off display of edge labels.  Edge labels often cause xvcg to
191    abort with a segmentation fault. */
192 void turn_off_edge_labels(void) {
193         edge_label = 0;
194 }
195
196 void dump_consts_local(int flag) {
197         dump_const_local = flag;
198 }
199
200 void dump_node_idx_label(int flag) {
201         dump_node_idx_labels = flag;
202 }
203
204 void dump_constant_entity_values(int flag) {
205         const_entities = flag;
206 }
207
208 void dump_keepalive_edges(int flag) {
209         dump_keepalive = flag;
210 }
211
212 void dump_new_edges(int flag) {
213         dump_new_edges_flag = flag;
214 }
215
216 int get_opt_dump_keepalive_edges(void) {
217         return dump_keepalive;
218 }
219
220 void dump_out_edges(int flag) {
221         dump_out_edge_flag = flag;
222 }
223
224 void dump_dominator_information(int flag) {
225         dump_dominator_information_flag = flag;
226 }
227
228 void dump_loop_information(int flag) {
229         dump_loop_information_flag = flag;
230 }
231
232 void dump_backedge_information(int flag) {
233         dump_backedge_information_flag = flag;
234 }
235
236 /* Dump the information of type field specified in ana/irtypeinfo.h.
237  * If the flag is set, the type name is output in [] in the node label,
238  * else it is output as info.
239  */
240 void set_opt_dump_analysed_type_info(int flag) {
241         opt_dump_analysed_type_info = flag;
242 }
243
244 void dump_pointer_values_to_info(int flag) {
245         opt_dump_pointer_values_to_info = flag;
246 }
247
248 void dump_ld_names(int flag) {
249         dump_ld_name = flag;
250 }
251
252 void dump_all_anchors(int flag) {
253         dump_anchors = flag;
254 }
255
256 void dump_macroblock_edges(int flag) {
257         dump_macro_block_edges = flag;
258 }
259
260 void dump_block_marker_in_title(int flag) {
261         dump_block_marker = flag;
262 }
263
264 /* -------------- some extended helper functions ----------------- */
265
266 /**
267  * returns the name of a mode or ERROR_TXT if mode is NOT a mode object.
268  * in the later case, sets bad.
269  */
270 const char *get_mode_name_ex(ir_mode *mode, int *bad) {
271         if (is_mode(mode))
272                 return get_mode_name(mode);
273         *bad |= 1;
274         return ERROR_TXT;
275 }
276
277 /**
278  * returns the name of a type or <ERROR> if mode is NOT a mode object.
279  * in the later case, sets bad
280  */
281 const char *get_type_name_ex(ir_type *tp, int *bad) {
282         if (is_type(tp))
283                 return get_type_name(tp);
284         *bad |= 1;
285         return ERROR_TXT;
286 }
287
288 #define CUSTOM_COLOR_BASE    100
289 static const char *color_names[ird_color_count];
290 static const char *color_rgb[ird_color_count];
291 static struct obstack color_obst;
292
293 static void custom_color(int num, const char *rgb_def)
294 {
295         assert(num < ird_color_count);
296         obstack_printf(&color_obst, "%d", CUSTOM_COLOR_BASE + num);
297         obstack_1grow(&color_obst, '\0');
298
299         color_rgb[num]   = rgb_def;
300         color_names[num] = obstack_finish(&color_obst);
301 }
302
303 static void named_color(int num, const char *name)
304 {
305         assert(num < ird_color_count);
306         color_rgb[num]   = NULL;
307         color_names[num] = name;
308 }
309
310 static void init_colors(void)
311 {
312         static int initialized = 0;
313         if(initialized)
314                 return;
315
316         obstack_init(&color_obst);
317
318         custom_color(ird_color_prog_background,       "204 204 204");
319         custom_color(ird_color_block_background,      "255 255 0");
320         custom_color(ird_color_dead_block_background, "190 150 150");
321         named_color(ird_color_block_inout,            "lightblue");
322         named_color(ird_color_default_node,           "white");
323         custom_color(ird_color_memory,                "153 153 255");
324         custom_color(ird_color_controlflow,           "255 153 153");
325         custom_color(ird_color_const,                 "204 255 255");
326         custom_color(ird_color_proj,                  "255 255 153");
327         custom_color(ird_color_uses_memory,           "153 153 255");
328         custom_color(ird_color_phi,                   "105 255 105");
329         custom_color(ird_color_anchor,                "100 100 255");
330         named_color(ird_color_error,                  "red");
331         custom_color(ird_color_entity,                "204 204 255");
332
333         initialized = 1;
334 }
335
336 /**
337  * Prints the VCG color to a file.
338  */
339 static void print_vcg_color(FILE *F, ird_color_t color) {
340         assert(color < ird_color_count);
341         fprintf(F, "color:%s", color_names[color]);
342 }
343
344 /**
345  * Prints the edge from a type S to a type T with additional info fmt, ...
346  * to the file F.
347  */
348 static void print_type_type_edge(FILE *F, ir_type *S, ir_type *T, const char *fmt, ...)
349 {
350         va_list ap;
351
352         va_start(ap, fmt);
353         fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
354         fprintf(F, " targetname: "); PRINT_TYPEID(T);
355         vfprintf(F, fmt, ap);
356         fprintf(F,"}\n");
357         va_end(ap);
358 }
359
360 /**
361  * Prints the edge from a type T to an entity E with additional info fmt, ...
362  * to the file F.
363  */
364 static void print_type_ent_edge(FILE *F, ir_type *T, ir_entity *E, const char *fmt, ...)
365 {
366         va_list ap;
367
368         va_start(ap, fmt);
369         fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
370         fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
371         vfprintf(F, fmt, ap);
372         fprintf(F, "}\n");
373         va_end(ap);
374 }
375
376 /**
377  * Prints the edge from an entity E to an entity T with additional info fmt, ...
378  * to the file F.
379  */
380 static void print_ent_ent_edge(FILE *F, ir_entity *E, ir_entity *T, int backedge, ird_color_t color, const char *fmt, ...)
381 {
382         va_list ap;
383
384         va_start(ap, fmt);
385         if (backedge)
386                 fprintf(F, "backedge: { sourcename: \"");
387         else
388                 fprintf(F, "edge: { sourcename: \"");
389         PRINT_ENTID(E);
390         fprintf(F, "\" targetname: \""); PRINT_ENTID(T);  fprintf(F, "\"");
391         vfprintf(F, fmt, ap);
392         fprintf(F, " ");
393         if (color != (ird_color_t) -1)
394                 print_vcg_color(F, color);
395         fprintf(F, "}\n");
396         va_end(ap);
397 }
398
399 /**
400  * Prints the edge from an entity E to a type T with additional info fmt, ...
401  * to the file F.
402  */
403 static void print_ent_type_edge(FILE *F, ir_entity *E, ir_type *T, const char *fmt, ...)
404 {
405         va_list ap;
406
407         va_start(ap, fmt);
408         fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
409         fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
410         vfprintf(F, fmt, ap);
411         fprintf(F,"}\n");
412         va_end(ap);
413 }
414
415 /**
416  * Prints the edge from a node N to a type T with additional info fmt, ...
417  * to the file F.
418  */
419 static void print_node_type_edge(FILE *F, const ir_node *N, ir_type *T, const char *fmt, ...)
420 {
421         va_list ap;
422
423         va_start(ap, fmt);
424         fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
425         fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
426         vfprintf(F, fmt, ap);
427         fprintf(F,"}\n");
428         va_end(ap);
429 }
430
431 /**
432  * Prints the edge from a node N to an entity E with additional info fmt, ...
433  * to the file F.
434  */
435 static void print_node_ent_edge(FILE *F, const ir_node *N, ir_entity *E, const char *fmt, ...)
436 {
437         va_list ap;
438
439         va_start(ap, fmt);
440         fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
441         fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
442         fprintf(F, "\"");
443         vfprintf(F, fmt, ap);
444         fprintf(F,"}\n");
445         va_end(ap);
446 }
447
448 /**
449  * Prints the edge from an entity E to a node N with additional info fmt, ...
450  * to the file F.
451  */
452 static void print_ent_node_edge(FILE *F, ir_entity *E, const ir_node *N, const char *fmt, ...)
453 {
454         va_list ap;
455
456         va_start(ap, fmt);
457         fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
458         fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
459         vfprintf(F, fmt, ap);
460         fprintf(F,"}\n");
461         va_end(ap);
462 }
463
464 /**
465  * Prints the edge from a type E to an enumeration item item with additional info fmt, ...
466  * to the file F.
467  */
468 static void print_enum_item_edge(FILE *F, ir_type *E, int item, const char *fmt, ...)
469 {
470         va_list ap;
471
472         va_start(ap, fmt);
473         fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
474         fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
475         vfprintf(F, fmt, ap);
476         fprintf(F,"}\n");
477         va_end(ap);
478 }
479
480 /*-----------------------------------------------------------------*/
481 /* global and ahead declarations                                   */
482 /*-----------------------------------------------------------------*/
483
484 static void dump_whole_node(ir_node *n, void *env);
485 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
486
487 /*-----------------------------------------------------------------*/
488 /* Helper functions.                                                */
489 /*-----------------------------------------------------------------*/
490
491 /**
492  * This map is used as a private link attr to be able to call dumper
493  * anywhere without destroying link fields.
494  */
495 static pmap *irdump_link_map = NULL;
496
497 /** NOT A STANDARD LIBFIRM INIT METHOD
498  *
499  * We do not want to integrate dumping into libfirm, i.e., if the dumpers
500  * are off, we want to have as few interferences as possible.  Therefore the
501  * initialization is performed lazily and not called from within init_firm.
502  *
503  * Creates the link attribute map. */
504 static void init_irdump(void) {
505         /* We need a new, empty map. */
506         if (irdump_link_map) pmap_destroy(irdump_link_map);
507         irdump_link_map = pmap_create();
508         if (!dump_file_filter_id)
509                 dump_file_filter_id = new_id_from_str("");
510 }
511
512 /**
513  * Returns the private link field.
514  */
515 static void *ird_get_irn_link(ir_node *n) {
516         void *res = NULL;
517         if (!irdump_link_map) return NULL;
518
519         if (pmap_contains(irdump_link_map, (void *)n))
520                 res = pmap_get(irdump_link_map, (void *)n);
521         return res;
522 }
523
524 /**
525  * Sets the private link field.
526  */
527 static void ird_set_irn_link(ir_node *n, void *x) {
528         if (!irdump_link_map)
529                 init_irdump();
530         pmap_insert(irdump_link_map, (void *)n, x);
531 }
532
533 /**
534  * Gets the private link field of an irg.
535  */
536 static void *ird_get_irg_link(ir_graph *irg) {
537         void *res = NULL;
538         if (!irdump_link_map) return NULL;
539
540         if (pmap_contains(irdump_link_map, (void *)irg))
541                 res = pmap_get(irdump_link_map, (void *)irg);
542         return res;
543 }
544
545 /**
546  * Sets the private link field of an irg.
547  */
548 static void ird_set_irg_link(ir_graph *irg, void *x) {
549         if (!irdump_link_map) init_irdump();
550         pmap_insert(irdump_link_map, (void *)irg, x);
551 }
552
553 /**
554  * Walker, clears the private link field.
555  */
556 static void clear_link(ir_node * node, void * env) {
557         (void) env;
558         ird_set_irn_link(node, NULL);
559 }
560
561 /**
562  * If the entity has a ld_name, returns it if the dump_ld_name is set,
563  * else returns the name of the entity.
564  */
565 static const char *_get_ent_dump_name(ir_entity *ent, int dump_ld_name) {
566         if (!ent)
567                 return "<NULL entity>";
568         if (dump_ld_name) {
569                 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
570                 if (ent->ld_name) return get_id_str(ent->ld_name);
571         }
572         return get_id_str(ent->name);
573 }
574
575 /**
576  * If the entity has a ld_name, returns it if the option dump_ld_name is set,
577  * else returns the name of the entity.
578  */
579 const char *get_ent_dump_name(ir_entity *ent) {
580         return _get_ent_dump_name(ent, dump_ld_name);
581 }
582
583 /* Returns the name of an IRG. */
584 const char *get_irg_dump_name(ir_graph *irg) {
585         /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
586         return _get_ent_dump_name(get_irg_entity(irg), 1);
587 }
588
589 /**
590  * Returns non-zero if a node is in floating state.
591  */
592 static int node_floats(ir_node *n) {
593         return ((get_irn_pinned(n) == op_pin_state_floats) &&
594                 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
595 }
596
597 /**
598  *  Walker that visits the anchors
599  */
600 static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
601         if (dump_anchors || (dump_new_edges_flag && edges_activated(irg))) {
602                 irg_walk_anchors(irg, pre, post, env);
603         } else {
604                 irg_walk_graph(irg, pre, post, env);
605         }
606 }
607
608 /**
609  * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
610  */
611 static void collect_node(ir_node * node, void *env) {
612         (void) env;
613         if (is_Block(node)
614             || node_floats(node)
615             || (get_op_flags(get_irn_op(node)) & irop_flag_dump_noblock)) {
616                 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
617                 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
618                 ARR_APP1(ir_node *, arr, node);
619                 ird_set_irg_link(get_irn_irg(node), arr);    /* arr is an l-value, APP_ARR might change it! */
620         } else {
621                 ir_node * block = get_nodes_block(node);
622
623                 if (is_Bad(block)) {
624                         /* this node is in a Bad block, so we must place it into the graph's list */
625                         ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
626                         if (!arr) arr = NEW_ARR_F(ir_node *, 0);
627                         ARR_APP1(ir_node *, arr, node);
628                         ird_set_irg_link(get_irn_irg(node), arr);    /* arr is an l-value, APP_ARR might change it! */
629                 } else {
630                         ird_set_irn_link(node, ird_get_irn_link(block));
631                         ird_set_irn_link(block, node);
632                 }
633         }
634 }
635
636 /** Construct lists to walk ir block-wise.
637  *
638  * Collects all blocks, nodes not op_pin_state_pinned,
639  * Bad, NoMem and Unknown into a flexible array in link field of
640  * irg they belong to.  Sets the irg link field to NULL in all
641  * graphs not visited.
642  * Free the list with DEL_ARR_F().
643  */
644 static ir_node **construct_block_lists(ir_graph *irg) {
645         int      i;
646 #ifdef INTERPROCEDURAL_VIEW
647         int      rem_view  = get_interprocedural_view();
648 #endif
649         int      walk_flag = ir_resources_reserved(irg) & IR_RESOURCE_IRN_VISITED;
650         ir_graph *rem      = current_ir_graph;
651
652         current_ir_graph = irg;
653
654         if(walk_flag)
655                 ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
656
657         for (i = get_irp_n_irgs() - 1; i >= 0; --i)
658                 ird_set_irg_link(get_irp_irg(i), NULL);
659
660         ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
661
662 #ifdef INTERPROCEDURAL_VIEW
663         /* Collect also EndReg and EndExcept. We do not want to change the walker. */
664         set_interprocedural_view(0);
665 #endif
666
667         set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
668         irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
669         set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
670         irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
671
672 #ifdef INTERPROCEDURAL_VIEW
673         set_interprocedural_view(rem_view);
674 #endif
675
676         if(walk_flag)
677                 ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
678
679         current_ir_graph = rem;
680         return ird_get_irg_link(irg);
681 }
682
683 typedef struct _list_tuple {
684         ir_node **blk_list;
685         ir_extblk **extbb_list;
686 } list_tuple;
687
688 /** Construct lists to walk IR extended block-wise.
689  * Free the lists in the tuple with DEL_ARR_F().
690  * Sets the irg link field to NULL in all
691  * graphs not visited.
692  */
693 static list_tuple *construct_extblock_lists(ir_graph *irg) {
694         ir_node **blk_list = construct_block_lists(irg);
695         int i;
696         ir_graph *rem = current_ir_graph;
697         list_tuple *lists = xmalloc(sizeof(*lists));
698
699         current_ir_graph = irg;
700
701         lists->blk_list   = NEW_ARR_F(ir_node *, 0);
702         lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
703
704         inc_irg_block_visited(irg);
705         for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
706                 ir_extblk *ext;
707
708                 if (is_Block(blk_list[i])) {
709                         ext = get_Block_extbb(blk_list[i]);
710
711                         if (extbb_not_visited(ext)) {
712                                 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
713                                 mark_extbb_visited(ext);
714                         }
715                 } else
716                         ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
717         }
718         DEL_ARR_F(blk_list);
719
720         current_ir_graph = rem;
721         ird_set_irg_link(irg, lists);
722         return lists;
723 }
724
725 /*-----------------------------------------------------------------*/
726 /* Routines to dump information about a single ir node.            */
727 /*-----------------------------------------------------------------*/
728
729 /*
730  * dump the name of a node n to the File F.
731  */
732 int dump_node_opcode(FILE *F, ir_node *n)
733 {
734         int bad = 0;
735         const ir_op_ops *ops = get_op_ops(get_irn_op(n));
736
737         /* call the dump_node operation if available */
738         if (ops->dump_node)
739                 return ops->dump_node(n, F, dump_node_opcode_txt);
740
741         /* implementation for default nodes */
742         switch (get_irn_opcode(n)) {
743
744         case iro_Const:
745                 ir_fprintf(F, "%T", get_Const_tarval(n));
746                 break;
747
748         case iro_SymConst:
749                 switch (get_SymConst_kind(n)) {
750                 case symconst_addr_name:
751                         /* don't use get_SymConst_ptr_info as it mangles the name. */
752                         fprintf(F, "SymC %s", get_id_str(get_SymConst_name(n)));
753                         break;
754                 case symconst_addr_ent:
755                         fprintf(F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
756                         break;
757                 case symconst_ofs_ent:
758                         fprintf(F, "SymC %s offset", get_entity_name(get_SymConst_entity(n)));
759                         break;
760                 case symconst_type_tag:
761                         fprintf(F, "SymC %s tag", get_type_name_ex(get_SymConst_type(n), &bad));
762                         break;
763                 case symconst_type_size:
764                         fprintf(F, "SymC %s size", get_type_name_ex(get_SymConst_type(n), &bad));
765                         break;
766                 case symconst_type_align:
767                         fprintf(F, "SymC %s align", get_type_name_ex(get_SymConst_type(n), &bad));
768                         break;
769                 case symconst_enum_const:
770                         fprintf(F, "SymC %s enum", get_enumeration_name(get_SymConst_enum(n)));
771                         break;
772                 case symconst_label:
773                         fprintf(F, "SymC %lu label", get_SymConst_label(n));
774                         break;
775                 }
776                 break;
777
778         case iro_Filter:
779                 if (!get_interprocedural_view())
780                         fprintf(F, "Proj'");
781                 else
782                         goto default_case;
783                 break;
784
785         case iro_Proj: {
786                 ir_node *pred = get_Proj_pred(n);
787
788                 if (get_irn_opcode(pred) == iro_Cond
789                         && get_Proj_proj(n) == get_Cond_defaultProj(pred)
790                         && get_irn_mode(get_Cond_selector(pred)) != mode_b)
791                         fprintf(F, "defProj");
792                 else
793                         goto default_case;
794         } break;
795         case iro_Start:
796         case iro_End:
797         case iro_EndExcept:
798         case iro_EndReg:
799                 if (get_interprocedural_view()) {
800                         fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
801                         break;
802                 } else
803                         goto default_case;
804
805         case iro_CallBegin: {
806                 ir_node *addr = get_CallBegin_ptr(n);
807                 ir_entity *ent = NULL;
808                 if (is_Sel(addr))
809                         ent = get_Sel_entity(addr);
810                 else if (is_Global(addr))
811                         ent = get_Global_entity(addr);
812                 fprintf(F, "%s", get_irn_opname(n));
813                 if (ent) fprintf(F, " %s", get_entity_name(ent));
814                 break;
815         }
816         case iro_Load:
817                 if (get_Load_align(n) == align_non_aligned)
818                         fprintf(F, "ua");
819                 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
820                 break;
821         case iro_Store:
822                 if (get_Store_align(n) == align_non_aligned)
823                         fprintf(F, "ua");
824                 fprintf(F, "%s", get_irn_opname(n));
825                 break;
826         case iro_Block:
827                 fprintf(F, "%s%s%s",
828                         is_Block_dead(n) ? "Dead " : "", get_irn_opname(n),
829                         dump_block_marker ? (get_Block_mark(n) ? "*" : "") : "");
830                 break;
831         case iro_Conv:
832                 if (get_Conv_strict(n))
833                         fprintf(F, "strict");
834                 fprintf(F, "%s", get_irn_opname(n));
835                 break;
836         case iro_Div:
837                 fprintf(F, "%s", get_irn_opname(n));
838                 if (is_Div_remainderless(n))
839                         fprintf(F, "RL");
840                 fprintf(F, "[%s]", get_mode_name_ex(get_Div_resmode(n), &bad));
841                 break;
842         case iro_Mod:
843                 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Mod_resmode(n), &bad));
844                 break;
845         case iro_DivMod:
846                 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_DivMod_resmode(n), &bad));
847                 break;
848
849         default:
850 default_case:
851                 fprintf(F, "%s", get_irn_opname(n));
852
853         }  /* end switch */
854         return bad;
855 }
856
857 /**
858  * Dump the mode of a node n to a file F.
859  * Ignore modes that are "always known".
860  */
861 static int dump_node_mode(FILE *F, ir_node *n)
862 {
863         int bad = 0;
864         const ir_op_ops *ops = get_op_ops(get_irn_op(n));
865         ir_opcode iro;
866
867         /* call the dump_node operation if available */
868         if (ops->dump_node)
869                 return ops->dump_node(n, F, dump_node_mode_txt);
870
871         /* default implementation */
872         iro = get_irn_opcode(n);
873         switch (iro) {
874         case iro_SymConst:
875         case iro_Sel:
876         case iro_End:
877         case iro_Return:
878         case iro_Free:
879         case iro_Sync:
880         case iro_Jmp:
881         case iro_NoMem:
882                 break;
883         default: {
884                 ir_mode *mode = get_irn_mode(n);
885
886                 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
887                         (mode != mode_T || iro == iro_Proj))
888                         fprintf(F, "%s", get_mode_name_ex(mode, &bad));
889         }
890         }
891
892         return bad;
893 }
894
895 /**
896  * Dump the type of a node n to a file F if it's known.
897  */
898 static int dump_node_typeinfo(FILE *F, ir_node *n) {
899         int bad = 0;
900
901         if (opt_dump_analysed_type_info) {
902                 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent  ||
903                         get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
904                         ir_type *tp = get_irn_typeinfo_type(n);
905                         if (tp != firm_none_type)
906                                 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
907                         else
908                                 fprintf(F, "[] ");
909                 }
910         }
911         return bad;
912 }
913
914 typedef struct _pns_lookup {
915         long       nr;      /**< the proj number */
916         const char *name;   /**< the name of the Proj */
917 } pns_lookup_t;
918
919 typedef struct _proj_lookup {
920         ir_opcode          code;      /**< the opcode of the Proj predecessor */
921         unsigned           num_data;  /**< number of data entries */
922         const pns_lookup_t *data;     /**< the data */
923 } proj_lookup_t;
924
925 #define ARR_SIZE(a)       (sizeof(a)/sizeof(a[0]))
926
927 /** the lookup table for Proj(Start) names */
928 static const pns_lookup_t start_lut[] = {
929 #define X(a)    { pn_Start_##a, #a }
930         X(X_initial_exec),
931         X(P_frame_base),
932         X(P_tls),
933         X(T_args),
934         X(P_value_arg_base)
935 #undef X
936 };
937
938 /** the lookup table for Proj(Cond) names */
939 static const pns_lookup_t cond_lut[] = {
940 #define X(a)    { pn_Cond_##a, #a }
941         X(false),
942         X(true)
943 #undef X
944 };
945
946 /** the lookup table for Proj(Call) names */
947 static const pns_lookup_t call_lut[] = {
948 #define X(a)    { pn_Call_##a, #a }
949         X(M_regular),
950         X(X_regular),
951         X(X_except),
952         X(T_result),
953         X(M_except),
954         X(P_value_res_base)
955 #undef X
956 };
957
958 /** the lookup table for Proj(Quot) names */
959 static const pns_lookup_t quot_lut[] = {
960 #define X(a)    { pn_Quot_##a, #a }
961         X(M),
962         X(X_regular),
963         X(X_except),
964         X(res)
965 #undef X
966 };
967
968 /** the lookup table for Proj(DivMod) names */
969 static const pns_lookup_t divmod_lut[] = {
970 #define X(a)    { pn_DivMod_##a, #a }
971         X(M),
972         X(X_regular),
973         X(X_except),
974         X(res_div),
975         X(res_mod)
976 #undef X
977 };
978
979 /** the lookup table for Proj(Div) names */
980 static const pns_lookup_t div_lut[] = {
981 #define X(a)    { pn_Div_##a, #a }
982         X(M),
983         X(X_regular),
984         X(X_except),
985         X(res)
986 #undef X
987 };
988
989 /** the lookup table for Proj(Mod) names */
990 static const pns_lookup_t mod_lut[] = {
991 #define X(a)    { pn_Mod_##a, #a }
992         X(M),
993         X(X_regular),
994         X(X_except),
995         X(res)
996 #undef X
997 };
998
999 /** the lookup table for Proj(Load) names */
1000 static const pns_lookup_t load_lut[] = {
1001 #define X(a)    { pn_Load_##a, #a }
1002         X(M),
1003         X(X_regular),
1004         X(X_except),
1005         X(res)
1006 #undef X
1007 };
1008
1009 /** the lookup table for Proj(Store) names */
1010 static const pns_lookup_t store_lut[] = {
1011 #define X(a)    { pn_Store_##a, #a }
1012         X(M),
1013         X(X_regular),
1014         X(X_except)
1015 #undef X
1016 };
1017
1018 /** the lookup table for Proj(Alloc) names */
1019 static const pns_lookup_t alloc_lut[] = {
1020 #define X(a)    { pn_Alloc_##a, #a }
1021         X(M),
1022         X(X_regular),
1023         X(X_except),
1024         X(res)
1025 #undef X
1026 };
1027
1028 /** the lookup table for Proj(CopyB) names */
1029 static const pns_lookup_t copyb_lut[] = {
1030 #define X(a)    { pn_CopyB_##a, #a }
1031         X(M),
1032         X(X_regular),
1033         X(X_except),
1034         X(M_except)
1035 #undef X
1036 };
1037
1038 /** the lookup table for Proj(InstOf) names */
1039 static const pns_lookup_t instof_lut[] = {
1040 #define X(a)    { pn_InstOf_##a, #a }
1041         X(M),
1042         X(X_regular),
1043         X(X_except),
1044         X(res),
1045         X(M_except),
1046 #undef X
1047 };
1048
1049 /** the lookup table for Proj(Raise) names */
1050 static const pns_lookup_t raise_lut[] = {
1051 #define X(a)    { pn_Raise_##a, #a }
1052         X(M),
1053         X(X),
1054 #undef X
1055 };
1056
1057 /** the lookup table for Proj(Bound) names */
1058 static const pns_lookup_t bound_lut[] = {
1059 #define X(a)    { pn_Bound_##a, #a }
1060         X(M),
1061         X(X_regular),
1062         X(X_except),
1063         X(res),
1064 #undef X
1065 };
1066
1067 /** the Proj lookup table */
1068 static const proj_lookup_t proj_lut[] = {
1069 #define E(a)  ARR_SIZE(a), a
1070         { iro_Start,   E(start_lut) },
1071         { iro_Cond,    E(cond_lut) },
1072         { iro_Call,    E(call_lut) },
1073         { iro_Quot,    E(quot_lut) },
1074         { iro_DivMod,  E(divmod_lut) },
1075         { iro_Div,     E(div_lut) },
1076         { iro_Mod,     E(mod_lut) },
1077         { iro_Load,    E(load_lut) },
1078         { iro_Store,   E(store_lut) },
1079         { iro_Alloc,   E(alloc_lut) },
1080         { iro_CopyB,   E(copyb_lut) },
1081         { iro_InstOf,  E(instof_lut) },
1082         { iro_Raise,   E(raise_lut) },
1083         { iro_Bound,   E(bound_lut) }
1084 #undef E
1085 };
1086
1087 /**
1088  * Dump additional node attributes of some nodes to a file F.
1089  */
1090 static int
1091 dump_node_nodeattr(FILE *F, ir_node *n)
1092 {
1093         int bad = 0;
1094         ir_node *pred;
1095         ir_opcode code;
1096         long proj_nr;
1097         const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1098
1099         /* call the dump_node operation if available */
1100         if (ops->dump_node)
1101                 return ops->dump_node(n, F, dump_node_nodeattr_txt);
1102
1103         switch (get_irn_opcode(n)) {
1104         case iro_Start:
1105                 if (0 && get_interprocedural_view()) {
1106                         fprintf(F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
1107                 }
1108                 break;
1109
1110         case iro_Proj:
1111                 pred    = get_Proj_pred(n);
1112                 proj_nr = get_Proj_proj(n);
1113 handle_lut:
1114                 code    = get_irn_opcode(pred);
1115
1116                 if (code == iro_Cmp)
1117                         fprintf(F, "%s ", get_pnc_string(get_Proj_proj(n)));
1118                 else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
1119                         fprintf(F, "Arg %ld ", proj_nr);
1120                 else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
1121                         fprintf(F, "%ld ", proj_nr);
1122                 else {
1123                         unsigned i, j, f = 0;
1124
1125                         for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
1126                                 if (code == proj_lut[i].code) {
1127                                         for (j = 0; j < proj_lut[i].num_data; ++j) {
1128                                                 if (proj_nr == proj_lut[i].data[j].nr) {
1129                                                         fprintf(F, "%s ", proj_lut[i].data[j].name);
1130                                                         f = 1;
1131                                                         break;
1132                                                 }
1133                                         }
1134                                         break;
1135                                 }
1136                         }
1137                         if (! f)
1138                                 fprintf(F, "%ld ", proj_nr);
1139                         if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
1140                                 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
1141                                         fprintf(F, "PRED ");
1142                                 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
1143                                         fprintf(F, "PRED ");
1144                         }
1145                 }
1146                 break;
1147         case iro_Filter:
1148                 proj_nr = get_Filter_proj(n);
1149                 if (! get_interprocedural_view()) {
1150                         /* it's a Proj' */
1151                         pred    = get_Filter_pred(n);
1152                         goto handle_lut;
1153                 } else
1154                         fprintf(F, "%ld ", proj_nr);
1155                 break;
1156         case iro_Sel:
1157                 fprintf(F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
1158                 break;
1159         case iro_Cast:
1160                 fprintf(F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
1161                 break;
1162         case iro_Confirm:
1163                 fprintf(F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
1164                 break;
1165         case iro_CopyB:
1166                 fprintf(F, "(%s) ", get_type_name_ex(get_CopyB_type(n), &bad));
1167                 break;
1168
1169         default:
1170                 ;
1171         } /* end switch */
1172
1173         return bad;
1174 }
1175
1176 #include <math.h>
1177 #include "execution_frequency.h"
1178
1179 static void dump_node_ana_vals(FILE *F, ir_node *n) {
1180         (void) F;
1181         (void) n;
1182         return;
1183 #ifdef INTERPROCEDURAL_VIEW
1184         fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
1185                 get_irn_exec_freq(n),
1186                 get_irg_method_execution_frequency(get_irn_irg(n)),
1187                 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
1188                 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
1189         );
1190 #endif
1191 }
1192
1193
1194 /* Dumps a node label without the enclosing ". */
1195 int dump_node_label(FILE *F, ir_node *n) {
1196         int bad = 0;
1197
1198         bad |= dump_node_opcode(F, n);
1199         bad |= dump_node_mode(F, n);
1200         fprintf(F, " ");
1201         bad |= dump_node_typeinfo(F, n);
1202         bad |= dump_node_nodeattr(F, n);
1203         if(dump_node_idx_labels) {
1204                 fprintf(F, "%ld:%d", get_irn_node_nr(n), get_irn_idx(n));
1205         } else {
1206                 fprintf(F, "%ld", get_irn_node_nr(n));
1207         }
1208
1209         return bad;
1210 }
1211
1212 /**
1213  * Dumps the attributes of a node n into the file F.
1214  * Currently this is only the color of a node.
1215  */
1216 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
1217 {
1218         ir_mode *mode;
1219         ir_node *n;
1220
1221         if (bad) {
1222                 print_vcg_color(F, ird_color_error);
1223                 return;
1224         }
1225
1226         if (dump_node_vcgattr_hook)
1227                 if (dump_node_vcgattr_hook(F, node, local))
1228                         return;
1229
1230         n = local ? local : node;
1231
1232         if (overrule_nodecolor != ird_color_default_node) {
1233                 print_vcg_color(F, overrule_nodecolor);
1234                 return;
1235         }
1236
1237         mode = get_irn_mode(node);
1238         if(mode == mode_M) {
1239                 print_vcg_color(F, ird_color_memory);
1240                 return;
1241         }
1242         if(mode == mode_X) {
1243                 print_vcg_color(F, ird_color_controlflow);
1244                 return;
1245         }
1246
1247         switch (get_irn_opcode(n)) {
1248         case iro_Start:
1249         case iro_EndReg:
1250         case iro_EndExcept:
1251         case iro_End:
1252                 print_vcg_color(F, ird_color_anchor);
1253                 break;
1254         case iro_Bad:
1255                 print_vcg_color(F, ird_color_error);
1256                 break;
1257         case iro_Block:
1258                 if (is_Block_dead(n))
1259                         print_vcg_color(F, ird_color_dead_block_background);
1260                 else
1261                         print_vcg_color(F, ird_color_block_background);
1262                 break;
1263         case iro_Phi:
1264                 print_vcg_color(F, ird_color_phi);
1265                 break;
1266         case iro_Pin:
1267                 print_vcg_color(F, ird_color_memory);
1268                 break;
1269         case iro_SymConst:
1270         case iro_Const:
1271                 print_vcg_color(F, ird_color_const);
1272                 break;
1273         case iro_Proj:
1274                 print_vcg_color(F, ird_color_proj);
1275                 break;
1276         default: {
1277                 ir_op *op = get_irn_op(node);
1278
1279                 if(is_op_constlike(op)) {
1280                         print_vcg_color(F, ird_color_const);
1281                 } else if(is_op_uses_memory(op)) {
1282                         print_vcg_color(F, ird_color_uses_memory);
1283                 } else if(is_op_cfopcode(op) || is_op_forking(op)) {
1284                         print_vcg_color(F, ird_color_controlflow);
1285                 } else {
1286                         PRINT_DEFAULT_NODE_ATTR;
1287                 }
1288         }
1289         }
1290 }
1291
1292 /* Adds a new node info dumper callback. */
1293 void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
1294 {
1295         hook_entry_t *info = xmalloc(sizeof(*info));
1296
1297         info->hook._hook_node_info = cb;
1298         info->context              = data;
1299         register_hook(hook_node_info, info);
1300
1301         return info;
1302 }
1303
1304 /* Remove a previously added info dumper callback. */
1305 void dump_remv_node_info_callback(void *handle)
1306 {
1307         hook_entry_t *info = handle;
1308         unregister_hook(hook_node_info, info);
1309         xfree(info);
1310 }
1311
1312 /**
1313  * Dump the node information of a node n to a file F.
1314  */
1315 static INLINE int dump_node_info(FILE *F, ir_node *n)
1316 {
1317         int bad = 0;
1318         const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1319
1320         fprintf(F, " info1: \"");
1321         bad = dump_irnode_to_file(F, n);
1322         /* call the dump_node operation if available */
1323         if (ops->dump_node)
1324                 bad = ops->dump_node(n, F, dump_node_info_txt);
1325
1326         /* allow additional info to be added */
1327         hook_node_info(F, n);
1328         fprintf(F, "\"\n");
1329
1330         return bad;
1331 }
1332
1333 static INLINE int is_constlike_node(const ir_node *node)
1334 {
1335         const ir_op *op = get_irn_op(node);
1336         return is_op_constlike(op);
1337 }
1338
1339
1340 /** outputs the predecessors of n, that are constants, local.  I.e.,
1341    generates a copy of the constant predecessors for each node called with. */
1342 static void dump_const_node_local(FILE *F, ir_node *n) {
1343         int i;
1344         if (!get_opt_dump_const_local()) return;
1345
1346         /* Use visited flag to avoid outputting nodes twice.
1347         initialize it first. */
1348         for (i = 0; i < get_irn_arity(n); i++) {
1349                 ir_node *con = get_irn_n(n, i);
1350                 if (is_constlike_node(con)) {
1351                         set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1352                 }
1353         }
1354
1355         for (i = 0; i < get_irn_arity(n); i++) {
1356                 ir_node *con = get_irn_n(n, i);
1357                 if (is_constlike_node(con) && irn_not_visited(con)) {
1358                         int bad = 0;
1359
1360                         mark_irn_visited(con);
1361                         /* Generate a new name for the node by appending the names of
1362                         n and const. */
1363                         fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1364                         fprintf(F, " label: \"");
1365                         bad |= dump_node_label(F, con);
1366                         fprintf(F, "\" ");
1367                         bad |= dump_node_info(F, con);
1368                         dump_node_vcgattr(F, n, con, bad);
1369                         fprintf(F, "}\n");
1370                 }
1371         }
1372 }
1373
1374 /** If the block of an edge is a const_like node, dump it local with an edge */
1375 static void dump_const_block_local(FILE *F, ir_node *n) {
1376         ir_node *blk;
1377
1378         if (!get_opt_dump_const_local()) return;
1379
1380         blk = get_nodes_block(n);
1381         if (is_constlike_node(blk)) {
1382                 int bad = 0;
1383
1384                 /* Generate a new name for the node by appending the names of
1385                 n and blk. */
1386                 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1387                 fprintf(F, "\" label: \"");
1388                 bad |= dump_node_label(F, blk);
1389                 fprintf(F, "\" ");
1390                 bad |= dump_node_info(F, blk);
1391                 dump_node_vcgattr(F, n, blk, bad);
1392                 fprintf(F, "}\n");
1393
1394                 fprintf(F, "edge: { sourcename: \"");
1395                 PRINT_NODEID(n);
1396                 fprintf(F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1397
1398                 if (dump_edge_vcgattr_hook) {
1399                         fprintf(F, "\" ");
1400                         if (dump_edge_vcgattr_hook(F, n, -1)) {
1401                                 fprintf(F, "}\n");
1402                                 return;
1403                         } else {
1404                                 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1405                                 return;
1406                         }
1407                 }
1408
1409                 fprintf(F, "\" "   BLOCK_EDGE_ATTR "}\n");
1410         }
1411 }
1412
1413 /**
1414  * prints the error message of a node to a file F as info2.
1415  */
1416 static void print_node_error(FILE *F, const char *err_msg)
1417 {
1418         if (! err_msg)
1419                 return;
1420
1421         fprintf(F, " info2: \"%s\"", err_msg);
1422 }
1423
1424 /**
1425  * prints debug messages of a node to file F as info3.
1426  */
1427 static void print_dbg_info(FILE *F, dbg_info *dbg)
1428 {
1429         char buf[1024];
1430
1431         if (__dbg_info_snprint) {
1432                 buf[0] = '\0';
1433                 if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1434                         fprintf(F, " info3: \"%s\"\n", buf);
1435         }
1436 }
1437
1438 /**
1439  * Dump a node
1440  */
1441 static void dump_node(FILE *F, ir_node *n)
1442 {
1443         int bad = 0;
1444         const char *p;
1445
1446         if (get_opt_dump_const_local() && is_constlike_node(n))
1447                 return;
1448
1449         /* dump this node */
1450         fputs("node: {title: \"", F);
1451         PRINT_NODEID(n);
1452         fputs("\"", F);
1453
1454         fputs(" label: \"", F);
1455         bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1456         bad |= dump_node_label(F, n);
1457         dump_node_ana_vals(F, n);
1458         //dump_node_ana_info(F, n);
1459         fputs("\" ", F);
1460
1461         if (get_op_flags(get_irn_op(n)) & irop_flag_dump_noinput) {
1462                 //fputs(" node_class:23", F);
1463         }
1464
1465         bad |= dump_node_info(F, n);
1466         print_node_error(F, p);
1467         print_dbg_info(F, get_irn_dbg_info(n));
1468         dump_node_vcgattr(F, n, NULL, bad);
1469         fputs("}\n", F);
1470         dump_const_node_local(F, n);
1471
1472         if(dump_node_edge_hook)
1473                 dump_node_edge_hook(F, n);
1474 #if DO_HEAPANALYSIS
1475         dump_irn_chi_term(F, n);
1476         dump_irn_state(F, n);
1477 #endif
1478 }
1479
1480 /** dump the edge to the block this node belongs to */
1481 static void
1482 dump_ir_block_edge(FILE *F, ir_node *n)  {
1483         if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1484         if (is_no_Block(n)) {
1485                 ir_node *block = get_nodes_block(n);
1486
1487                 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1488                         dump_const_block_local(F, n);
1489                 } else {
1490                         fprintf(F, "edge: { sourcename: \"");
1491                         PRINT_NODEID(n);
1492                         fprintf(F, "\" targetname: ");
1493                         fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1494
1495                         if (dump_edge_vcgattr_hook) {
1496                                 fprintf(F, " ");
1497                                 if (dump_edge_vcgattr_hook(F, n, -1)) {
1498                                         fprintf(F, "}\n");
1499                                         return;
1500                                 } else {
1501                                         fprintf(F, " "  BLOCK_EDGE_ATTR "}\n");
1502                                         return;
1503                                 }
1504                         }
1505
1506                         fprintf(F, " "   BLOCK_EDGE_ATTR "}\n");
1507                 }
1508         }
1509 }
1510
1511 static void
1512 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1513         /*
1514          * do not use get_nodes_block() here, will fail
1515          * if the irg is not pinned.
1516          */
1517         if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1518                 fprintf(F, INTRA_DATA_EDGE_ATTR);
1519         else
1520                 fprintf(F, INTER_DATA_EDGE_ATTR);
1521 }
1522
1523 static void
1524 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1525         /*
1526          * do not use get_nodes_block() here, will fail
1527          * if the irg is not pinned.
1528          */
1529         if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1530                 fprintf(F, INTRA_MEM_EDGE_ATTR);
1531         else
1532                 fprintf(F, INTER_MEM_EDGE_ATTR);
1533 }
1534
1535 /** Print the vcg attributes for the edge from node from to it's to's input */
1536 static void print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1537         assert(from);
1538
1539         if (dump_edge_vcgattr_hook)
1540                 if (dump_edge_vcgattr_hook(F, from, to))
1541                         return;
1542
1543         if (dump_backedge_information_flag && is_backedge(from, to))
1544                 fprintf(F, BACK_EDGE_ATTR);
1545
1546         switch (get_irn_opcode(from)) {
1547         case iro_Block:
1548                 fprintf(F, CF_EDGE_ATTR);
1549                 break;
1550         case iro_Start:  break;
1551         case iro_End:
1552                 if (to >= 0) {
1553                         if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1554                                 fprintf(F, KEEP_ALIVE_CF_EDGE_ATTR);
1555                         else
1556                                 fprintf(F, KEEP_ALIVE_DF_EDGE_ATTR);
1557                 }
1558                 break;
1559         default:
1560                 if (is_Proj(from)) {
1561                         if (get_irn_mode(from) == mode_M)
1562                                 print_mem_edge_vcgattr(F, from, to);
1563                         else if (get_irn_mode(from) == mode_X)
1564                                 fprintf(F, CF_EDGE_ATTR);
1565                         else
1566                                 print_data_edge_vcgattr(F, from, to);
1567                 }
1568                 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1569                         print_mem_edge_vcgattr(F, from, to);
1570                 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1571                         fprintf(F, CF_EDGE_ATTR);
1572                 else
1573                         print_data_edge_vcgattr(F, from, to);
1574         }
1575 }
1576
1577 /** dump edges to our inputs */
1578 static void dump_ir_data_edges(FILE *F, ir_node *n)  {
1579         int i, num;
1580         ir_visited_t visited = get_irn_visited(n);
1581
1582         if (!dump_keepalive && is_End(n)) {
1583                 /* the End node has only keep-alive edges */
1584                 return;
1585         }
1586
1587         /* dump the dependency edges. */
1588         num = get_irn_deps(n);
1589         for (i = 0; i < num; ++i) {
1590                 ir_node *dep = get_irn_dep(n, i);
1591
1592                 if (dep) {
1593                         fprintf(F, "edge: {sourcename: \"");
1594                         PRINT_NODEID(n);
1595                         fprintf(F, "\" targetname: ");
1596                         if ((get_opt_dump_const_local()) && is_constlike_node(dep)) {
1597                                 PRINT_CONSTID(n, dep);
1598                         } else {
1599                                 fprintf(F, "\"");
1600                                 PRINT_NODEID(dep);
1601                                 fprintf(F, "\"");
1602                         }
1603                         fprintf(F, " label: \"%d\" ", i);
1604                         fprintf(F, " color: darkgreen}\n");
1605                 }
1606         }
1607
1608         num = get_irn_arity(n);
1609         for (i = 0; i < num; i++) {
1610                 ir_node *pred = get_irn_n(n, i);
1611                 assert(pred);
1612
1613                 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1614                         continue; /* pred not dumped */
1615
1616                 if (dump_backedge_information_flag && is_backedge(n, i))
1617                         fprintf(F, "backedge: {sourcename: \"");
1618                 else
1619                         fprintf(F, "edge: {sourcename: \"");
1620                 PRINT_NODEID(n);
1621                 fprintf(F, "\" targetname: ");
1622                 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1623                         PRINT_CONSTID(n, pred);
1624                 } else {
1625                         fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1626                 }
1627                 fprintf(F, " label: \"%d\" ", i);
1628                 print_edge_vcgattr(F, n, i);
1629                 fprintf(F, "}\n");
1630         }
1631
1632         if (dump_macro_block_edges && is_Block(n)) {
1633                 ir_node *mb = get_Block_MacroBlock(n);
1634                 fprintf(F, "edge: {sourcename: \"");
1635                 PRINT_NODEID(n);
1636                 fprintf(F, "\" targetname: \"");
1637                 PRINT_NODEID(mb);
1638                 fprintf(F, "\" label: \"mb\" " MACROBLOCK_EDGE_ATTR);
1639                 fprintf(F, "}\n");
1640         }
1641 }
1642
1643 /**
1644  * Dump the ir_edges
1645  */
1646 static void
1647 dump_ir_edges(FILE *F, ir_node *n) {
1648         const ir_edge_t *edge;
1649         int i = 0;
1650
1651         foreach_out_edge(n, edge) {
1652                 ir_node *succ = get_edge_src_irn(edge);
1653
1654                 fprintf(F, "edge: {sourcename: \"");
1655                 PRINT_NODEID(n);
1656                 fprintf(F, "\" targetname: \"");
1657                 PRINT_NODEID(succ);
1658                 fprintf(F, "\"");
1659
1660                 fprintf(F, " label: \"%d\" ", i);
1661                 fprintf(F, OUT_EDGE_ATTR);
1662                 fprintf(F, "}\n");
1663                 ++i;
1664         }
1665 }
1666
1667
1668 /** Dumps a node and its edges but not the block edge  */
1669 static void dump_node_wo_blockedge(ir_node *n, void *env) {
1670         FILE *F = env;
1671         dump_node(F, n);
1672         dump_ir_data_edges(F, n);
1673 }
1674
1675 /** Dumps a node and its edges. */
1676 static void dump_whole_node(ir_node *n, void *env) {
1677         FILE *F = env;
1678         dump_node_wo_blockedge(n, env);
1679         if (!node_floats(n))
1680                 dump_ir_block_edge(F, n);
1681         if (dump_new_edges_flag && edges_activated(current_ir_graph))
1682                 dump_ir_edges(F, n);
1683 }
1684
1685 /** Dumps a const-like node. */
1686 static void dump_const_node(ir_node *n, void *env) {
1687         if (is_Block(n)) return;
1688         dump_node_wo_blockedge(n, env);
1689 }
1690
1691 /***********************************************************************/
1692 /* the following routines dump the nodes/irgs bracketed to graphs.     */
1693 /***********************************************************************/
1694
1695 /** Dumps a constant expression as entity initializer, array bound ...
1696  */
1697 static void dump_const_expression(FILE *F, ir_node *value) {
1698         ir_graph *rem = current_ir_graph;
1699         int rem_dump_const_local = dump_const_local;
1700         dump_const_local = 0;
1701         current_ir_graph = get_const_code_irg();
1702         irg_walk(value, dump_const_node, NULL, F);
1703         /* Decrease visited flag so that we walk with the same flag for the next
1704            expression.  This guarantees that we don't dump the same node twice,
1705            as for const expressions cse is performed to save memory. */
1706         set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1707         current_ir_graph = rem;
1708         dump_const_local = rem_dump_const_local;
1709 }
1710
1711 /** Dump a block as graph containing its nodes.
1712  *
1713  *  Expects to find nodes belonging to the block as list in its
1714  *  link field.
1715  *  Dumps the edges of all nodes including itself. */
1716 static void dump_whole_block(FILE *F, ir_node *block) {
1717         ir_node *node;
1718         ird_color_t color = ird_color_block_background;
1719
1720         assert(is_Block(block));
1721
1722         fprintf(F, "graph: { title: \"");
1723         PRINT_NODEID(block);
1724         fprintf(F, "\"  label: \"");
1725         dump_node_label(F, block);
1726 #if DO_HEAPANALYSIS
1727         if (get_opt_dump_abstvals())
1728                 fprintf(F, " seqno: %d", (int)get_Block_seqno(block));
1729 #endif
1730
1731         /* colorize blocks */
1732         if (! get_Block_matured(block))
1733                 color = ird_color_block_background;
1734         if (is_Block_dead(block))
1735                 color = ird_color_dead_block_background;
1736
1737         fprintf(F, "\" status:clustered ");
1738         print_vcg_color(F, color);
1739         fprintf(F, "\n");
1740
1741         /* yComp can show attributes for blocks, XVCG parses but ignores them */
1742         dump_node_info(F, block);
1743         print_dbg_info(F, get_irn_dbg_info(block));
1744
1745         /* dump the blocks edges */
1746         dump_ir_data_edges(F, block);
1747
1748         if (dump_block_edge_hook)
1749                 dump_block_edge_hook(F, block);
1750
1751         /* dump the nodes that go into the block */
1752         for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1753                 dump_node(F, node);
1754                 dump_ir_data_edges(F, node);
1755         }
1756
1757         /* Close the vcg information for the block */
1758         fprintf(F, "}\n");
1759         dump_const_node_local(F, block);
1760 #if DO_HEAPANALYSIS
1761         dump_irn_chi_term(F, block);
1762 #endif
1763         fprintf(F, "\n");
1764 }
1765
1766 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1767  *  The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1768 static void
1769 dump_block_graph(FILE *F, ir_graph *irg) {
1770         int i;
1771         ir_graph *rem = current_ir_graph;
1772         ir_node **arr = ird_get_irg_link(irg);
1773         current_ir_graph = irg;
1774
1775         for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1776                 ir_node * node = arr[i];
1777                 if (is_Block(node)) {
1778                 /* Dumps the block and all the nodes in the block, which are to
1779                         be found in Block->link. */
1780                         dump_whole_block(F, node);
1781                 } else {
1782                         /* Nodes that are not in a Block. */
1783                         dump_node(F, node);
1784                         if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1785                                 dump_const_block_local(F, node);
1786                         }
1787                         dump_ir_data_edges(F, node);
1788                 }
1789                 if (dump_new_edges_flag && edges_activated(irg))
1790                         dump_ir_edges(F, node);
1791         }
1792
1793         if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1794                 dump_loop_nodes_into_graph(F, irg);
1795
1796         current_ir_graph = rem;
1797 }
1798
1799 /**
1800  * Dump the info for an irg.
1801  * Parsed by XVCG but not shown. use yComp.
1802  */
1803 static void dump_graph_info(FILE *F, ir_graph *irg) {
1804         fprintf(F, "info1: \"");
1805         dump_entity_to_file(F, get_irg_entity(irg), dump_verbosity_entattrs | dump_verbosity_entconsts);
1806         fprintf(F, "\"\n");
1807 }
1808
1809 /** Dumps an irg as a graph clustered by block nodes.
1810  *  If interprocedural view edges can point to nodes out of this graph.
1811  */
1812 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1813         ir_entity *ent = get_irg_entity(irg);
1814
1815         fprintf(F, "graph: { title: \"");
1816         PRINT_IRGID(irg);
1817         fprintf(F, "\" label: \"%s\" status:clustered color:%s \n",
1818           get_ent_dump_name(ent), color_names[ird_color_prog_background]);
1819
1820         dump_graph_info(F, irg);
1821         print_dbg_info(F, get_entity_dbg_info(ent));
1822
1823         dump_block_graph(F, irg);
1824
1825         /* Close the vcg information for the irg */
1826         fprintf(F, "}\n\n");
1827 }
1828
1829 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1830  *  The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1831 static void
1832 dump_extblock_graph(FILE *F, ir_graph *irg) {
1833         int i;
1834         ir_graph *rem = current_ir_graph;
1835         ir_extblk **arr = ird_get_irg_link(irg);
1836         current_ir_graph = irg;
1837
1838         for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1839                 ir_extblk *extbb = arr[i];
1840                 ir_node *leader = get_extbb_leader(extbb);
1841                 int j;
1842
1843                 fprintf(F, "graph: { title: \"");
1844                 PRINT_EXTBBID(leader);
1845                 fprintf(F, "\"  label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1846                         get_irn_node_nr(leader));
1847
1848                 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1849                         ir_node * node = extbb->blks[j];
1850                         if (is_Block(node)) {
1851                         /* Dumps the block and all the nodes in the block, which are to
1852                                 be found in Block->link. */
1853                                 dump_whole_block(F, node);
1854                         } else {
1855                                 /* Nodes that are not in a Block. */
1856                                 dump_node(F, node);
1857                                 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1858                                         dump_const_block_local(F, node);
1859                                 }
1860                                 dump_ir_data_edges(F, node);
1861                         }
1862                 }
1863                 fprintf(F, "}\n");
1864         }
1865
1866         if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1867                 dump_loop_nodes_into_graph(F, irg);
1868
1869         current_ir_graph = rem;
1870         free_extbb(irg);
1871 }
1872
1873
1874 /*******************************************************************/
1875 /* Basic type and entity nodes and edges.                          */
1876 /*******************************************************************/
1877
1878 /** dumps the edges between nodes and their type or entity attributes. */
1879 static void dump_node2type_edges(ir_node *n, void *env)
1880 {
1881         FILE *F = env;
1882         assert(n);
1883
1884         switch (get_irn_opcode(n)) {
1885         case iro_Const :
1886                 /* @@@ some consts have an entity */
1887                 break;
1888         case iro_SymConst:
1889                 if (SYMCONST_HAS_TYPE(get_SymConst_kind(n)))
1890                         print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1891                 break;
1892         case iro_Sel:
1893                 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1894                 break;
1895         case iro_Call:
1896                 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1897                 break;
1898         case iro_Alloc:
1899                 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1900                 break;
1901         case iro_Free:
1902                 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1903                 break;
1904         case iro_Cast:
1905                 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1906                 break;
1907         default:
1908                 break;
1909         }
1910 }
1911
1912 #if 0
1913 static int print_type_info(FILE *F, ir_type *tp) {
1914         int bad = 0;
1915
1916         if (get_type_state(tp) == layout_undefined) {
1917                 fprintf(F, "state: layout_undefined\n");
1918         } else {
1919                 fprintf(F, "state: layout_fixed,\n");
1920         }
1921         if (get_type_mode(tp))
1922                 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1923         fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1924
1925         return bad;
1926 }
1927
1928 static void print_typespecific_info(FILE *F, ir_type *tp) {
1929         switch (get_type_tpop_code(tp)) {
1930         case tpo_class:
1931                 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1932                 break;
1933         case tpo_struct:
1934                 break;
1935         case tpo_method:
1936                 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1937                 fprintf(F, "params: %d\n", get_method_n_params(tp));
1938                 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1939                 break;
1940         case tpo_union:
1941                 break;
1942         case tpo_array:
1943                 break;
1944         case tpo_enumeration:
1945                 break;
1946         case tpo_pointer:
1947                 break;
1948         case tpo_primitive:
1949                 break;
1950         default:
1951                 break;
1952         } /* switch type */
1953 }
1954 #endif
1955
1956 static void print_typespecific_vcgattr(FILE *F, ir_type *tp) {
1957         switch (get_type_tpop_code(tp)) {
1958         case tpo_class:
1959                 if (peculiarity_existent == get_class_peculiarity(tp))
1960                         fprintf(F, " " TYPE_CLASS_NODE_ATTR);
1961                 else
1962                         fprintf(F, " " TYPE_DESCRIPTION_NODE_ATTR);
1963                 break;
1964         case tpo_struct:
1965                 fprintf(F, " " TYPE_METH_NODE_ATTR);
1966                 break;
1967         case tpo_method:
1968                 break;
1969         case tpo_union:
1970                 break;
1971         case tpo_array:
1972                 break;
1973         case tpo_enumeration:
1974                 break;
1975         case tpo_pointer:
1976                 break;
1977         case tpo_primitive:
1978                 break;
1979         default:
1980                 break;
1981         } /* switch type */
1982 }
1983
1984
1985 int dump_type_node(FILE *F, ir_type *tp)
1986 {
1987         int bad = 0;
1988
1989         fprintf(F, "node: {title: ");
1990         PRINT_TYPEID(tp);
1991         fprintf(F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1992         fprintf(F, " info1: \"");
1993 #if 0
1994         bad |= print_type_info(F, tp);
1995         print_typespecific_info(F, tp);
1996 #else
1997         dump_type_to_file(F, tp, dump_verbosity_max);
1998 #endif
1999         fprintf(F, "\"\n");
2000         print_dbg_info(F, get_type_dbg_info(tp));
2001         print_typespecific_vcgattr(F, tp);
2002         fprintf(F, "}\n");
2003
2004         return bad;
2005 }
2006
2007
2008 void dump_entity_node(FILE *F, ir_entity *ent)
2009 {
2010         fprintf(F, "node: {title: \"");
2011         PRINT_ENTID(ent); fprintf(F, "\"");
2012         fprintf(F, DEFAULT_TYPE_ATTRIBUTE);
2013         fprintf(F, "label: ");
2014         fprintf(F, "\"%s\" ", get_ent_dump_name(ent));
2015
2016         print_vcg_color(F, ird_color_entity);
2017         fprintf(F, "\n info1: \"");
2018
2019         dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
2020
2021         fprintf(F, "\"\n");
2022         print_dbg_info(F, get_entity_dbg_info(ent));
2023         fprintf(F, "}\n");
2024 }
2025
2026 static void dump_enum_item(FILE *F, ir_type *tp, int pos)
2027 {
2028         char buf[1024];
2029         ir_enum_const *ec = get_enumeration_const(tp, pos);
2030         ident         *id = get_enumeration_nameid(ec);
2031         tarval        *tv = get_enumeration_value(ec);
2032
2033         if (tv)
2034                 tarval_snprintf(buf, sizeof(buf), tv);
2035         else
2036                 strncpy(buf, "<not set>", sizeof(buf));
2037         fprintf(F, "node: {title: \"");
2038         PRINT_ITEMID(tp, pos); fprintf(F, "\"");
2039         fprintf(F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
2040         fprintf(F, "label: ");
2041         fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
2042         fprintf(F, "\n info1: \"value: %s\"}\n", buf);
2043 }
2044
2045 /* dumps a type or entity and it's edges. */
2046 static void
2047 dump_type_info(type_or_ent tore, void *env) {
2048         FILE *F = env;
2049         int i = 0;  /* to shutup gcc */
2050
2051         /* dump this type or entity */
2052
2053         switch (get_kind(tore.ent)) {
2054         case k_entity: {
2055                 ir_entity *ent = tore.ent;
2056                 ir_node *value;
2057                 /* The node */
2058                 dump_entity_node(F, ent);
2059                 /* The Edges */
2060                 /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
2061                 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
2062                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
2063                 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
2064                 if (is_Class_type(get_entity_owner(ent))) {
2065                         for(i = 0; i < get_entity_n_overwrites(ent); i++)
2066                                 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, -1, ENT_OVERWRITES_EDGE_ATTR);
2067                 }
2068                 /* attached subgraphs */
2069                 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
2070                         if (is_atomic_entity(ent)) {
2071                                 value = get_atomic_ent_value(ent);
2072                                 if (value) {
2073                                         print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
2074                                         /* DDMN(value);  $$$ */
2075                                         dump_const_expression(F, value);
2076                                 }
2077                         }
2078                         if (is_compound_entity(ent)) {
2079                                 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
2080                                         value = get_compound_ent_value(ent, i);
2081                                         if (value) {
2082                                                 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
2083                                                 dump_const_expression(F, value);
2084                                                 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, -1, ENT_CORR_EDGE_ATTR, i);
2085                                                 /*
2086                                                 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
2087                                                 ENT_CORR_EDGE_ATTR  "}\n", GET_ENTID(ent),
2088                                                 get_compound_ent_value_member(ent, i), i);
2089                                                 */
2090                                         }
2091                                 }
2092                         }
2093                 }
2094                 break;
2095         }
2096         case k_type: {
2097                 ir_type *tp = tore.typ;
2098                 dump_type_node(F, tp);
2099                 /* and now the edges */
2100                 switch (get_type_tpop_code(tp)) {
2101                 case tpo_class:
2102                         for (i=0; i < get_class_n_supertypes(tp); i++)
2103                                 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
2104                         for (i=0; i < get_class_n_members(tp); i++)
2105                                 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
2106                         break;
2107                 case tpo_struct:
2108                         for (i=0; i < get_struct_n_members(tp); i++)
2109                                 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
2110                         break;
2111                 case tpo_method:
2112                         for (i = 0; i < get_method_n_params(tp); i++)
2113                                 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
2114                         for (i = 0; i < get_method_n_ress(tp); i++)
2115                                 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
2116                         break;
2117                 case tpo_union:
2118                         for (i = 0; i < get_union_n_members(tp); i++)
2119                                 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
2120                         break;
2121                 case tpo_array:
2122                         print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
2123                         print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
2124                         for (i = 0; i < get_array_n_dimensions(tp); i++) {
2125                                 ir_node *upper = get_array_upper_bound(tp, i);
2126                                 ir_node *lower = get_array_lower_bound(tp, i);
2127                                 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
2128                                 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
2129                                 dump_const_expression(F, upper);
2130                                 dump_const_expression(F, lower);
2131                         }
2132                         break;
2133                 case tpo_enumeration:
2134                         for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
2135                                 dump_enum_item(F, tp, i);
2136                                 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
2137                         }
2138                         break;
2139                 case tpo_pointer:
2140                         print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
2141                         break;
2142                 case tpo_primitive:
2143                         break;
2144                 default:
2145                         break;
2146                 } /* switch type */
2147                 break; /* case k_type */
2148         }
2149         default:
2150                 printf(" *** irdump,  dump_type_info(l.%i), faulty type.\n", __LINE__);
2151         } /* switch kind_or_entity */
2152 }
2153
2154 typedef struct _h_env {
2155         int dump_ent;
2156         FILE *f;
2157 } h_env_t;
2158
2159 /** For dumping class hierarchies.
2160  * Dumps a class type node and a superclass edge.
2161  * If env->dump_ent dumps entities of classes and overwrites edges.
2162  */
2163 static void
2164 dump_class_hierarchy_node(type_or_ent tore, void *ctx) {
2165         h_env_t *env = ctx;
2166         FILE *F = env->f;
2167         int i = 0;  /* to shutup gcc */
2168
2169         /* dump this type or entity */
2170         switch (get_kind(tore.ent)) {
2171         case k_entity: {
2172                 ir_entity *ent = tore.ent;
2173                 if (get_entity_owner(ent) == get_glob_type()) break;
2174                 if (!is_Method_type(get_entity_type(ent)))
2175                         break;  /* GL */
2176                 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
2177                         /* The node */
2178                         dump_entity_node(F, ent);
2179                         /* The edges */
2180                         print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
2181                         for(i = 0; i < get_entity_n_overwrites(ent); i++)
2182                                 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, -1, ENT_OVERWRITES_EDGE_ATTR);
2183                 }
2184                 break;
2185         }
2186         case k_type: {
2187                 ir_type *tp = tore.typ;
2188                 if (tp == get_glob_type())
2189                         break;
2190                 switch (get_type_tpop_code(tp)) {
2191                 case tpo_class:
2192                         dump_type_node(F, tp);
2193                         /* and now the edges */
2194                         for (i=0; i < get_class_n_supertypes(tp); i++) {
2195                                 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
2196                         }
2197                         break;
2198                 default: break;
2199                 } /* switch type */
2200                 break; /* case k_type */
2201         }
2202         default:
2203                 printf(" *** irdump,  dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
2204         } /* switch kind_or_entity */
2205 }
2206
2207 /*******************************************************************/
2208 /* dump analysis information that is expressed in graph terms.     */
2209 /*******************************************************************/
2210
2211 /* dump out edges */
2212 static void
2213 dump_out_edge(ir_node *n, void *env) {
2214         FILE *F = env;
2215         int i;
2216         for (i = 0; i < get_irn_n_outs(n); i++) {
2217                 assert(get_irn_out(n, i));
2218                 fprintf(F, "edge: {sourcename: \"");
2219                 PRINT_NODEID(n);
2220                 fprintf(F, "\" targetname: \"");
2221                 PRINT_NODEID(get_irn_out(n, i));
2222                 fprintf(F, "\" color: red linestyle: dashed");
2223                 fprintf(F, "}\n");
2224         }
2225 }
2226
2227 static INLINE void
2228 dump_loop_label(FILE *F, ir_loop *loop) {
2229         fprintf(F, "loop %d, %d sons, %d nodes",
2230                 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
2231 }
2232
2233 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
2234         fprintf(F, " info1: \"");
2235         fprintf(F, " loop nr: %d", get_loop_loop_nr(loop));
2236 #ifdef DEBUG_libfirm   /* GL @@@ debug analyses */
2237         fprintf(F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
2238 #endif
2239         fprintf(F, "\"");
2240 }
2241
2242 static INLINE void
2243 dump_loop_node(FILE *F, ir_loop *loop) {
2244         fprintf(F, "node: {title: \"");
2245         PRINT_LOOPID(loop);
2246         fprintf(F, "\" label: \"");
2247         dump_loop_label(F, loop);
2248         fprintf(F, "\" ");
2249         dump_loop_info(F, loop);
2250         fprintf(F, "}\n");
2251 }
2252
2253 static INLINE void
2254 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
2255         assert(loop);
2256         fprintf(F, "edge: {sourcename: \"");
2257         PRINT_LOOPID(loop);
2258         fprintf(F, "\" targetname: \"");
2259         PRINT_NODEID(get_loop_node(loop, i));
2260         fprintf(F, "\" color: green");
2261         fprintf(F, "}\n");
2262 }
2263
2264 static INLINE void
2265 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
2266         assert(loop);
2267         fprintf(F, "edge: {sourcename: \"");
2268         PRINT_LOOPID(loop);
2269         fprintf(F, "\" targetname: \"");
2270         PRINT_LOOPID(get_loop_son(loop, i));
2271         fprintf(F, "\" color: darkgreen label: \"%d\"}\n",
2272                 get_loop_element_pos(loop, get_loop_son(loop, i)));
2273 }
2274
2275 static
2276 void dump_loops(FILE *F, ir_loop *loop) {
2277         int i;
2278         /* dump this loop node */
2279         dump_loop_node(F, loop);
2280
2281         /* dump edges to nodes in loop -- only if it is a real loop */
2282         if (get_loop_depth(loop) != 0) {
2283                 for (i = 0; i < get_loop_n_nodes(loop); i++) {
2284                         dump_loop_node_edge(F, loop, i);
2285                 }
2286         }
2287         for (i = 0; i < get_loop_n_sons(loop); i++) {
2288                 dump_loops(F, get_loop_son(loop, i));
2289                 dump_loop_son_edge(F, loop, i);
2290         }
2291 }
2292
2293 static INLINE
2294 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
2295         ir_graph *rem = current_ir_graph;
2296         current_ir_graph = irg;
2297
2298         if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
2299
2300         current_ir_graph = rem;
2301 }
2302
2303
2304 /**
2305  * dumps the VCG header
2306  */
2307 void dump_vcg_header(FILE *F, const char *name, const char *layout, const char *orientation) {
2308         int   i;
2309         char *label;
2310
2311         init_colors();
2312
2313         label = edge_label ? "yes" : "no";
2314         if (! layout)     layout = "Compilergraph";
2315         if (!orientation) orientation = "bottom_to_top";
2316
2317         /* print header */
2318         fprintf(F,
2319                 "graph: { title: \"ir graph of %s\"\n"
2320                 "display_edge_labels: %s\n"
2321                 "layoutalgorithm: mindepth //$ \"%s\"\n"
2322                 "manhattan_edges: yes\n"
2323                 "port_sharing: no\n"
2324                 "orientation: %s\n"
2325                 "classname 1:  \"intrablock Data\"\n"
2326                 "classname 2:  \"Block\"\n"
2327                 "classname 3:  \"Entity type\"\n"
2328                 "classname 4:  \"Entity owner\"\n"
2329                 "classname 5:  \"Method Param\"\n"
2330                 "classname 6:  \"Method Res\"\n"
2331                 "classname 7:  \"Super\"\n"
2332                 "classname 8:  \"Union\"\n"
2333                 "classname 9:  \"Points-to\"\n"
2334                 "classname 10: \"Array Element Type\"\n"
2335                 "classname 11: \"Overwrites\"\n"
2336                 "classname 12: \"Member\"\n"
2337                 "classname 13: \"Control Flow\"\n"
2338                 "classname 14: \"intrablock Memory\"\n"
2339                 "classname 15: \"Dominators\"\n"
2340                 "classname 16: \"interblock Data\"\n"
2341                 "classname 17: \"interblock Memory\"\n"
2342                 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2343                 "classname 19: \"Postdominators\"\n"
2344                 "classname 20: \"Keep Alive\"\n"
2345                 "classname 21: \"Out Edges\"\n"
2346                 "classname 22: \"Macro Block Edges\"\n"
2347                 //"classname 23: \"NoInput Nodes\"\n"
2348                 "infoname 1: \"Attribute\"\n"
2349                 "infoname 2: \"Verification errors\"\n"
2350                 "infoname 3: \"Debug info\"\n",
2351                 name, label, layout, orientation);
2352
2353         for (i = 0; i < ird_color_count; ++i) {
2354                 if (color_rgb[i] != NULL) {
2355                         fprintf(F, "colorentry %s: %s\n", color_names[i], color_rgb[i]);
2356                 }
2357         }
2358         fprintf(F, "\n");        /* a separator */
2359 }
2360
2361 /**
2362  * open a vcg file
2363  *
2364  * @param irg     The graph to be dumped
2365  * @param suffix1 first filename suffix
2366  * @param suffix2 second filename suffix
2367  */
2368 FILE *vcg_open(ir_graph *irg, const char * suffix1, const char *suffix2) {
2369         FILE *F;
2370         const char *nm = get_irg_dump_name(irg);
2371         int len = strlen(nm), i, j;
2372         char *fname;  /* filename to put the vcg information in */
2373
2374         if (!suffix1) suffix1 = "";
2375         if (!suffix2) suffix2 = "";
2376
2377         /* open file for vcg graph */
2378         fname = xmalloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2379
2380         /* strncpy (fname, nm, len); */     /* copy the filename */
2381         j = 0;
2382         for (i = 0; i < len; ++i) {  /* replace '/' in the name: escape by @. */
2383                 if (nm[i] == '/') {
2384                         fname[j] = '@'; j++; fname[j] = '1'; j++;
2385                 } else if (nm[i] == '@') {
2386                         fname[j] = '@'; j++; fname[j] = '2'; j++;
2387                 } else {
2388                         fname[j] = nm[i]; j++;
2389                 }
2390         }
2391         fname[j] = '\0';
2392         strcat(fname, suffix1);  /* append file suffix */
2393         strcat(fname, suffix2);  /* append file suffix */
2394         strcat(fname, ".vcg");   /* append the .vcg suffix */
2395
2396         /* vcg really expect only a <CR> at end of line, so
2397          * the "b"inary mode is what you mean (and even needed for Win32)
2398          */
2399         F = fopen(fname, "wb");  /* open file for writing */
2400         if (!F) {
2401                 perror(fname);
2402         }
2403         free(fname);
2404
2405         return F;
2406 }
2407
2408 /**
2409  * open a vcg file
2410  *
2411  * @param name    prefix file name
2412  * @param suffix  filename suffix
2413  */
2414 FILE *vcg_open_name(const char *name, const char *suffix) {
2415         FILE *F;
2416         char *fname;  /* filename to put the vcg information in */
2417         int i, j, len = strlen(name);
2418
2419         if (!suffix) suffix = "";
2420
2421         /** open file for vcg graph */
2422         fname = xmalloc(len * 2 + 5 + strlen(suffix));
2423         /* strcpy (fname, name);*/    /* copy the filename */
2424         j = 0;
2425         for (i = 0; i < len; ++i) {  /* replace '/' in the name: escape by @. */
2426                 if (name[i] == '/') {
2427                         fname[j] = '@'; j++; fname[j] = '1'; j++;
2428                 } else if (name[i] == '@') {
2429                         fname[j] = '@'; j++; fname[j] = '2'; j++;
2430                 } else {
2431                         fname[j] = name[i]; j++;
2432                 }
2433         }
2434         fname[j] = '\0';
2435         strcat(fname, suffix);
2436         strcat(fname, ".vcg");  /* append the .vcg suffix */
2437
2438         /* vcg really expect only a <CR> at end of line, so
2439          * the "b"inary mode is what you mean (and even needed for Win32)
2440          */
2441         F = fopen(fname, "wb");  /* open file for writing */
2442         if (!F) {
2443                 perror(fname);
2444         }
2445         free(fname);
2446
2447         return F;
2448 }
2449
2450 /**
2451  * Dumps the vcg file footer
2452  */
2453 void dump_vcg_footer(FILE *F) {
2454         fprintf(F, "}\n");
2455 }
2456
2457 /************************************************************************/
2458 /************************************************************************/
2459 /* Routines that dump all or parts of the firm representation to a file */
2460 /************************************************************************/
2461 /************************************************************************/
2462
2463 /************************************************************************/
2464 /* Dump ir graphs, different formats and additional information.        */
2465 /************************************************************************/
2466
2467 typedef void (*do_dump_graph_func) (ir_graph *irg, FILE *out);
2468
2469 static void do_dump(ir_graph *irg, const char *suffix, const char *suffix_ip,
2470                     const char *suffix_nonip, do_dump_graph_func dump_func)
2471 {
2472         FILE       *out;
2473         ir_graph   *rem;
2474         const char *suffix1;
2475
2476         if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2477                 return;
2478
2479         rem = current_ir_graph;
2480         current_ir_graph = irg;
2481         if (get_interprocedural_view())
2482                 suffix1 = suffix_ip;
2483         else
2484                 suffix1 = suffix_nonip;
2485         current_ir_graph = rem;
2486
2487         out = vcg_open(irg, suffix, suffix1);
2488         if (out != NULL) {
2489                 dump_func(irg, out);
2490                 fclose(out);
2491         }
2492 }
2493
2494 void dump_ir_graph_file(ir_graph *irg, FILE *out)
2495 {
2496         if (dump_backedge_information_flag
2497                         && get_irg_loopinfo_state(irg) != loopinfo_consistent) {
2498                 construct_backedges(irg);
2499         }
2500
2501         dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2502
2503         /* call the dump graph hook */
2504         if (dump_ir_graph_hook) {
2505                 if (dump_ir_graph_hook(out, irg)) {
2506                         return;
2507                 }
2508         }
2509
2510         /* walk over the graph */
2511         /* dump_whole_node must be called in post visiting predecessors */
2512         ird_walk_graph(irg, NULL, dump_whole_node, out);
2513
2514         /* dump the out edges in a separate walk */
2515         if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2516                 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, out);
2517         }
2518
2519         dump_vcg_footer(out);
2520 }
2521
2522 /** Routine to dump a graph, blocks as conventional nodes.  */
2523 void dump_ir_graph(ir_graph *irg, const char *suffix )
2524 {
2525         do_dump(irg, suffix, "-pure-ip", "-pure", dump_ir_graph_file);
2526 }
2527
2528 void dump_ir_block_graph_file(ir_graph *irg, FILE *out)
2529 {
2530         int i;
2531
2532         dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2533
2534         construct_block_lists(irg);
2535
2536         /*
2537          * If we are in the interprocedural view, we dump not
2538          * only the requested irg but also all irgs that can be reached
2539          * from irg.
2540          */
2541         for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2542                 ir_graph *g = get_irp_irg(i);
2543                 ir_node **arr = ird_get_irg_link(g);
2544                 if (arr) {
2545                         dump_graph_from_list(out, g);
2546                         DEL_ARR_F(arr);
2547                 }
2548         }
2549
2550         dump_vcg_footer(out);
2551 }
2552
2553 /* Dump a firm graph without explicit block nodes. */
2554 void dump_ir_block_graph(ir_graph *irg, const char *suffix)
2555 {
2556         do_dump(irg, suffix, "-ip", "", dump_ir_block_graph_file);
2557 }
2558
2559 void dump_ir_extblock_graph_file(ir_graph *irg, FILE *F)
2560 {
2561         int        i;
2562         ir_entity *ent = get_irg_entity(irg);
2563
2564         if (get_irg_extblk_state(irg) != extblk_valid)
2565                 compute_extbb(irg);
2566
2567         dump_vcg_header(F, get_irg_dump_name(irg), NULL, NULL);
2568
2569         construct_extblock_lists(irg);
2570
2571         fprintf(F, "graph: { title: \"");
2572         PRINT_IRGID(irg);
2573         fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2574                 get_ent_dump_name(ent));
2575
2576         dump_graph_info(F, irg);
2577         print_dbg_info(F, get_entity_dbg_info(ent));
2578
2579         for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2580                 ir_graph *irg     = get_irp_irg(i);
2581                 list_tuple *lists = ird_get_irg_link(irg);
2582
2583                 if (lists) {
2584                         /* dump the extended blocks first */
2585                         if (ARR_LEN(lists->extbb_list)) {
2586                                 ird_set_irg_link(irg, lists->extbb_list);
2587                                 dump_extblock_graph(F, irg);
2588                         }
2589
2590                         /* we may have blocks without extended blocks, bad for instance */
2591                         if (ARR_LEN(lists->blk_list)) {
2592                                 ird_set_irg_link(irg, lists->blk_list);
2593                                 dump_block_graph(F, irg);
2594                         }
2595
2596                         DEL_ARR_F(lists->extbb_list);
2597                         DEL_ARR_F(lists->blk_list);
2598                         xfree(lists);
2599                 }
2600         }
2601
2602         /* Close the vcg information for the irg */
2603         fprintf(F, "}\n\n");
2604
2605         dump_vcg_footer(F);
2606         free_extbb(irg);
2607 }
2608
2609 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2610 void dump_ir_extblock_graph(ir_graph *irg, const char *suffix)
2611 {
2612         do_dump(irg, suffix, "-ip", "", dump_ir_extblock_graph_file);
2613 }
2614
2615 void dump_ir_graph_w_types_file(ir_graph *irg, FILE *out)
2616 {
2617         ir_graph *rem = current_ir_graph;
2618         int       rem_dump_const_local;
2619
2620         rem                  = current_ir_graph;
2621         current_ir_graph     = irg;
2622         rem_dump_const_local = dump_const_local;
2623         /* dumping types does not work with local nodes */
2624         dump_const_local = 0;
2625
2626         dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2627
2628         /* dump common ir graph */
2629         irg_walk(get_irg_end(irg), NULL, dump_whole_node, out);
2630         /* dump type info */
2631         type_walk_irg(irg, dump_type_info, NULL, out);
2632         inc_irg_visited(get_const_code_irg());
2633         /* dump edges from graph to type info */
2634         irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, out);
2635
2636         dump_vcg_footer(out);
2637         dump_const_local = rem_dump_const_local;
2638         current_ir_graph = rem;
2639 }
2640
2641 /* dumps a graph with type information */
2642 void dump_ir_graph_w_types(ir_graph *irg, const char *suffix)
2643 {
2644         do_dump(irg, suffix, "-pure-wtypes-ip", "-pure-wtypes",
2645                 dump_ir_graph_w_types_file);
2646 }
2647
2648 void dump_ir_block_graph_w_types_file(ir_graph *irg, FILE *out)
2649 {
2650         int       i;
2651         int       rem_dump_const_local;
2652         ir_graph *rem = current_ir_graph;
2653
2654         rem_dump_const_local = dump_const_local;
2655         /* dumping types does not work with local nodes */
2656         dump_const_local = 0;
2657
2658         dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2659
2660         /* dump common blocked ir graph */
2661         construct_block_lists(irg);
2662
2663         for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2664                 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2665                 if (arr) {
2666                         dump_graph_from_list(out, get_irp_irg(i));
2667                         DEL_ARR_F(arr);
2668                 }
2669         }
2670
2671         /* dump type info */
2672         current_ir_graph = irg;
2673         type_walk_irg(irg, dump_type_info, NULL, out);
2674         inc_irg_visited(get_const_code_irg());
2675
2676         /* dump edges from graph to type info */
2677         irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, out);
2678
2679         dump_vcg_footer(out);
2680         dump_const_local = rem_dump_const_local;
2681         current_ir_graph = rem;
2682 }
2683
2684 void dump_ir_block_graph_w_types(ir_graph *irg, const char *suffix)
2685 {
2686         do_dump(irg, suffix, "-wtypes-ip", "-wtypes",
2687                 dump_ir_block_graph_w_types_file);
2688 }
2689
2690 /*---------------------------------------------------------------------*/
2691 /* The following routines dump a control flow graph.                   */
2692 /*---------------------------------------------------------------------*/
2693
2694 static void
2695 dump_block_to_cfg(ir_node *block, void *env) {
2696         FILE *F = env;
2697         int i, fl = 0;
2698         ir_node *pred;
2699
2700         if (is_Block(block)) {
2701                 /* This is a block. Dump a node for the block. */
2702                 fprintf(F, "node: {title: \""); PRINT_NODEID(block);
2703                 fprintf(F, "\" label: \"");
2704                 if (block == get_irg_start_block(get_irn_irg(block)))
2705                         fprintf(F, "Start ");
2706                 if (block == get_irg_end_block(get_irn_irg(block)))
2707                         fprintf(F, "End ");
2708
2709                 fprintf(F, "%s ", get_op_name(get_irn_op(block)));
2710                 PRINT_NODEID(block);
2711                 fprintf(F, "\" ");
2712                 fprintf(F, "info1:\"");
2713
2714                 /* the generic version. */
2715                 dump_irnode_to_file(F, block);
2716
2717                 /* Check whether we have bad predecessors to color the block. */
2718                 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2719                         if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2720                                 break;
2721
2722                 fprintf(F, "\"");  /* closing quote of info */
2723
2724                 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2725                         (block == get_irg_end_block(get_irn_irg(block)))     )
2726                         fprintf(F, " color:blue ");
2727                 else if (fl)
2728                         fprintf(F, " color:yellow ");
2729
2730                 fprintf(F, "}\n");
2731                 /* Dump the edges */
2732                 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2733                         if (!is_Bad(skip_Proj(get_Block_cfgpred(block, i)))) {
2734                                 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2735                                 fprintf(F, "edge: { sourcename: \"");
2736                                 PRINT_NODEID(block);
2737                                 fprintf(F, "\" targetname: \"");
2738                                 PRINT_NODEID(pred);
2739                                 fprintf(F, "\"}\n");
2740                         }
2741
2742                 /* Dump dominator/postdominator edge */
2743                 if (dump_dominator_information_flag) {
2744                         if (get_irg_dom_state(current_ir_graph) == dom_consistent && get_Block_idom(block)) {
2745                                 pred = get_Block_idom(block);
2746                                 fprintf(F, "edge: { sourcename: \"");
2747                                 PRINT_NODEID(block);
2748                                 fprintf(F, "\" targetname: \"");
2749                                 PRINT_NODEID(pred);
2750                                 fprintf(F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2751                         }
2752                         if (get_irg_postdom_state(current_ir_graph) == dom_consistent && get_Block_ipostdom(block)) {
2753                                 pred = get_Block_ipostdom(block);
2754                                 fprintf(F, "edge: { sourcename: \"");
2755                                 PRINT_NODEID(block);
2756                                 fprintf(F, "\" targetname: \"");
2757                                 PRINT_NODEID(pred);
2758                                 fprintf(F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2759                         }
2760                 }
2761         }
2762 }
2763
2764 void dump_cfg(ir_graph *irg, const char *suffix)
2765 {
2766         FILE *f;
2767         /* if a filter is set, dump only the irg's that match the filter */
2768         if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2769                 return;
2770
2771         f = vcg_open(irg, suffix, "-cfg");
2772         if (f != NULL) {
2773                 ir_graph *rem = current_ir_graph;
2774 #ifdef INTERPROCEDURAL_VIEW
2775                 int ipv = get_interprocedural_view();
2776 #endif
2777
2778                 current_ir_graph = irg;
2779                 dump_vcg_header(f, get_irg_dump_name(irg), NULL, NULL);
2780
2781 #ifdef INTERPROCEDURAL_VIEW
2782                 if (ipv) {
2783                         printf("Warning: dumping cfg not in interprocedural view!\n");
2784                         set_interprocedural_view(0);
2785                 }
2786 #endif
2787
2788                 /* walk over the blocks in the graph */
2789                 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2790                 dump_node(f, get_irg_bad(irg));
2791
2792 #ifdef INTERPROCEDURAL_VIEW
2793                 set_interprocedural_view(ipv);
2794 #endif
2795                 dump_vcg_footer(f);
2796                 fclose(f);
2797                 current_ir_graph = rem;
2798         }
2799 }
2800
2801
2802 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2803         if (pset_find_ptr(mark_set, n)) return;
2804
2805         pset_insert_ptr(mark_set, n);
2806
2807         if (depth > 0) {
2808                 int i, start = is_Block(n) ? 0 : -1;
2809                 dump_whole_node(n, F);
2810                 for (i = start; i < get_irn_arity(n); ++i)
2811                         descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2812         } else {
2813                 dump_node(F, n);
2814                 /* Don't dump edges to nodes further out.  These might be edges to
2815                    nodes we already dumped, if there is a shorter path to these. */
2816         }
2817 }
2818
2819 static int subgraph_counter = 0;
2820 void dump_subgraph(ir_node *root, int depth, const char *suffix) {
2821         FILE *F;
2822         char buf[32];
2823
2824         sprintf(buf, "-subg_%03d", subgraph_counter++);
2825         F = vcg_open(get_irn_irg(root), suffix, buf);
2826         if (F != NULL) {
2827                 pset *mark_set = pset_new_ptr(1);
2828                 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL, NULL);
2829                 descend_and_dump(F, root, depth, mark_set);
2830                 dump_vcg_footer(F);
2831                 fclose(F);
2832                 del_pset(mark_set);
2833         }
2834 }
2835
2836 void dump_callgraph(const char *suffix) {
2837         FILE *F = vcg_open_name("Callgraph", suffix);
2838
2839         if (F != NULL) {
2840                 int i, rem = edge_label;
2841                 //int colorize;
2842                 edge_label = 1;
2843                 dump_vcg_header(F, "Callgraph", "Hierarchiv", NULL);
2844
2845                 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2846                         ir_graph *irg = get_irp_irg(i);
2847                         ir_entity *ent = get_irg_entity(irg);
2848                         int j;
2849                         int n_callees = get_irg_n_callees(irg);
2850
2851                         dump_entity_node(F, ent);
2852                         for (j = 0; j < n_callees; ++j) {
2853                                 ir_entity *c = get_irg_entity(get_irg_callee(irg, j));
2854                                 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2855                                 int be = is_irg_callee_backedge(irg, j);
2856                                 char *attr;
2857                                 attr = (be) ?
2858                                         "label:\"recursion %d\"" :
2859                                 "label:\"calls %d\"";
2860                                 print_ent_ent_edge(F, ent, c, be, ird_color_entity, attr, get_irg_callee_loop_depth(irg, j));
2861                         }
2862                 }
2863
2864                 edge_label = rem;
2865                 dump_vcg_footer(F);
2866                 fclose(F);
2867         }
2868 }
2869
2870 #if 0
2871 /* Dump all irgs in interprocedural view to a single file. */
2872 void dump_all_cg_block_graph(const char *suffix) {
2873         FILE *f = vcg_open_name("All_graphs", suffix);
2874
2875         if (f != NULL) {
2876                 int i;
2877                 int rem_view = get_interprocedural_view();
2878
2879                 set_interprocedural_view(1);
2880                 dump_vcg_header(f, "All_graphs", NULL);
2881
2882                 /* collect nodes in all irgs reachable in call graph*/
2883                 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2884                         ird_set_irg_link(get_irp_irg(i), NULL);
2885
2886                 cg_walk(clear_link, collect_node, NULL);
2887
2888                 /* dump all graphs */
2889                 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2890                         current_ir_graph = get_irp_irg(i);
2891                         assert(ird_get_irg_link(current_ir_graph));
2892                         dump_graph_from_list(f, current_ir_graph);
2893                         DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2894                 }
2895
2896                 dump_vcg_footer(f);
2897                 fclose(f);
2898                 set_interprocedural_view(rem_view);
2899         }
2900 }
2901 #endif
2902
2903 /*---------------------------------------------------------------------*/
2904 /* the following routines dumps type information without any ir nodes. */
2905 /*---------------------------------------------------------------------*/
2906
2907 void
2908 dump_type_graph(ir_graph *irg, const char *suffix)
2909 {
2910         FILE *f;
2911
2912         /* if a filter is set, dump only the irg's that match the filter */
2913         if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2914
2915         f = vcg_open(irg, suffix, "-type");
2916         if (f != NULL) {
2917                 ir_graph *rem = current_ir_graph;
2918                 current_ir_graph = irg;
2919
2920                 dump_vcg_header(f, get_irg_dump_name(irg), "Hierarchic", NULL);
2921
2922                 /* walk over the blocks in the graph */
2923                 type_walk_irg(irg, dump_type_info, NULL, f);
2924                 /* The walker for the const code can be called several times for the
2925                    same (sub) expression.  So that no nodes are dumped several times
2926                    we decrease the visited flag of the corresponding graph after each
2927                    walk.  So now increase it finally. */
2928                 inc_irg_visited(get_const_code_irg());
2929
2930                 dump_vcg_footer(f);
2931                 fclose(f);
2932                 current_ir_graph = rem;
2933         }
2934 }
2935
2936 void
2937 dump_all_types(const char *suffix)
2938 {
2939         FILE *f = vcg_open_name("All_types", suffix);
2940         if (f) {
2941                 dump_vcg_header(f, "All_types", "Hierarchic", NULL);
2942                 type_walk(dump_type_info, NULL, f);
2943                 inc_irg_visited(get_const_code_irg());
2944
2945                 dump_vcg_footer(f);
2946                 fclose(f);
2947         }
2948 }
2949
2950 void
2951 dump_class_hierarchy(int entities, const char *suffix)
2952 {
2953         FILE *f = vcg_open_name("class_hierarchy", suffix);
2954
2955         if (f != NULL) {
2956                 h_env_t env;
2957                 env.f        = f;
2958                 env.dump_ent = entities;
2959                 dump_vcg_header(f, "class_hierarchy", "Hierarchic", NULL);
2960                 type_walk(dump_class_hierarchy_node, NULL, &env);
2961
2962                 dump_vcg_footer(f);
2963                 fclose(f);
2964         }
2965 }
2966
2967 /*---------------------------------------------------------------------*/
2968 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
2969 /*  dump_ir_graph                                                      */
2970 /*  dump_ir_block_graph                                                */
2971 /*  dump_cfg                                                           */
2972 /*  dump_type_graph                                                    */
2973 /*  dump_ir_graph_w_types                                              */
2974 /*---------------------------------------------------------------------*/
2975
2976 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2977         int i;
2978         for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2979                 dmp_grph(get_irp_irg(i), suffix);
2980 }
2981
2982
2983 /*--------------------------------------------------------------------------------*
2984  * Dumps a stand alone loop graph with firm nodes which belong to one loop node   *
2985  * packed together in one subgraph/box                                            *
2986  *--------------------------------------------------------------------------------*/
2987
2988 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2989         int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2990         loop_element le;
2991         ir_loop *son = NULL;
2992
2993         /* Dump a new loop node. */
2994         dump_loop_node(F, loop);
2995
2996         /* Dump the loop elements. */
2997         for (i = 0; i < get_loop_n_elements(loop); i++) {
2998                 le = get_loop_element(loop, i);
2999                 son = le.son;
3000                 if (get_kind(son) == k_ir_loop) {
3001
3002                         /* We are a loop son -> Recurse */
3003
3004                         if (loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
3005                                 fprintf(F, "\" }\n");
3006                                 fprintf(F, "edge: {sourcename: \"");
3007                                 PRINT_LOOPID(loop);
3008                                 fprintf(F, "\" targetname: \"");
3009                                 PRINT_LOOPID(loop);
3010                                 fprintf(F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
3011                                 loop_node_started = 0;
3012                         }
3013                         dump_loop_son_edge(F, loop, son_number++);
3014                         dump_loops_standalone(F, son);
3015                 } else if (get_kind(son) == k_ir_node) {
3016                         /* We are a loop node -> Collect firm nodes */
3017
3018                         ir_node *n = le.node;
3019                         int bad = 0;
3020
3021                         if (!loop_node_started) {
3022                                 /* Start a new node which contains all firm nodes of the current loop */
3023                                 fprintf(F, "node: { title: \"");
3024                                 PRINT_LOOPID(loop);
3025                                 fprintf(F, "-%d-nodes\" color: lightyellow label: \"", i);
3026                                 loop_node_started = 1;
3027                                 first = i;
3028                         } else
3029                                 fprintf(F, "\n");
3030
3031                         bad |= dump_node_label(F, n);
3032                         /* Causes indeterministic output: if (is_Block(n)) fprintf(F, "\t ->%d", (int)get_irn_link(n)); */
3033                         if (has_backedges(n)) fprintf(F, "\t loop head!");
3034                 } else { /* for callgraph loop tree */
3035                         ir_graph *n;
3036                         assert(get_kind(son) == k_ir_graph);
3037
3038                         /* We are a loop node -> Collect firm graphs */
3039                         n = le.irg;
3040                         if (!loop_node_started) {
3041                                 /* Start a new node which contains all firm nodes of the current loop */
3042                                 fprintf(F, "node: { title: \"");
3043                                 PRINT_LOOPID(loop);
3044                                 fprintf(F, "-%d-nodes\" color: lightyellow label: \"", i);
3045                                 loop_node_started = 1;
3046                                 first = i;
3047                         } else
3048                                 fprintf(F, "\n");
3049                         fprintf(F, " %s", get_irg_dump_name(n));
3050                         /* fprintf(F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
3051                 }
3052         }
3053
3054         if (loop_node_started) {
3055                 fprintf(F, "\" }\n");
3056                 fprintf(F, "edge: {sourcename: \"");
3057                 PRINT_LOOPID(loop);
3058                 fprintf(F, "\" targetname: \"");
3059                 PRINT_LOOPID(loop);
3060                 fprintf(F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
3061                 loop_node_started = 0;
3062         }
3063 }
3064
3065 void dump_loop_tree(ir_graph *irg, const char *suffix)
3066 {
3067         FILE *f;
3068
3069         /* if a filter is set, dump only the irg's that match the filter */
3070         if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
3071
3072         f = vcg_open(irg, suffix, "-looptree");
3073         if (f != NULL) {
3074                 ir_graph *rem = current_ir_graph;
3075                 int el_rem = edge_label;
3076
3077                 current_ir_graph = irg;
3078                 edge_label = 1;
3079
3080                 dump_vcg_header(f, get_irg_dump_name(irg), "Tree", "top_to_bottom");
3081
3082                 if (get_irg_loop(irg))
3083                         dump_loops_standalone(f, get_irg_loop(irg));
3084
3085                 dump_vcg_footer(f);
3086                 fclose(f);
3087
3088                 edge_label = el_rem;
3089                 current_ir_graph = rem;
3090         }
3091 }
3092
3093 void dump_callgraph_loop_tree(const char *suffix) {
3094         FILE *F;
3095         F = vcg_open_name("Callgraph_looptree", suffix);
3096         dump_vcg_header(F, "callgraph looptree", "Tree", "top_to_bottom");
3097         dump_loops_standalone(F, irp->outermost_cg_loop);
3098         dump_vcg_footer(F);
3099         fclose(F);
3100 }
3101
3102
3103 /*----------------------------------------------------------------------------*/
3104 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes.*/
3105 /*----------------------------------------------------------------------------*/
3106
3107 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
3108         int i, son_number = 0, node_number = 0;
3109
3110         if (dump_loop_information_flag) dump_loop_node(F, loop);
3111
3112         for (i = 0; i < get_loop_n_elements(loop); i++) {
3113                 loop_element le = get_loop_element(loop, i);
3114                 if (*(le.kind) == k_ir_loop) {
3115                         if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
3116                         /* Recur */
3117                         collect_nodeloop(F, le.son, loopnodes);
3118                 } else {
3119                         if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
3120                         eset_insert(loopnodes, le.node);
3121                 }
3122         }
3123 }
3124
3125 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
3126         int i, j, start;
3127
3128         for(i = 0; i < get_loop_n_elements(loop); i++) {
3129                 loop_element le = get_loop_element(loop, i);
3130                 if (*(le.kind) == k_ir_loop) {
3131                         /* Recur */
3132                         collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
3133                 } else {
3134                         if (is_Block(le.node)) start = 0; else start = -1;
3135                         for (j = start; j < get_irn_arity(le.node); j++) {
3136                                 ir_node *pred = get_irn_n(le.node, j);
3137                                 if (!eset_contains(loopnodes, pred)) {
3138                                         eset_insert(extnodes, pred);
3139                                         if (!is_Block(pred)) {
3140                                                 pred = get_nodes_block(pred);
3141                                                 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
3142                                         }
3143                                 }
3144                         }
3145                 }
3146         }
3147 }
3148
3149 void dump_loop(ir_loop *l, const char *suffix) {
3150         FILE *F;
3151         char name[50];
3152
3153         snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
3154         F = vcg_open_name(name, suffix);
3155         if (F != NULL) {
3156                 eset *loopnodes = eset_create();
3157                 eset *extnodes = eset_create();
3158                 ir_node *n, *b;
3159
3160                 dump_vcg_header(F, name, NULL, NULL);
3161
3162                 /* collect all nodes to dump */
3163                 collect_nodeloop(F, l, loopnodes);
3164                 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
3165
3166                 /* build block lists */
3167                 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3168                         set_irn_link(n, NULL);
3169                 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3170                         set_irn_link(n, NULL);
3171                 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes)) {
3172                         if (!is_Block(n)) {
3173                                 b = get_nodes_block(n);
3174                                 set_irn_link(n, get_irn_link(b));
3175                                 set_irn_link(b, n);
3176                         }
3177                 }
3178                 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes)) {
3179                         if (!is_Block(n)) {
3180                                 b = get_nodes_block(n);
3181                                 set_irn_link(n, get_irn_link(b));
3182                                 set_irn_link(b, n);
3183                         }
3184                 }
3185
3186                 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes)) {
3187                         if (is_Block(b)) {
3188                                 fprintf(F, "graph: { title: \"");
3189                                 PRINT_NODEID(b);
3190                                 fprintf(F, "\"  label: \"");
3191                                 dump_node_opcode(F, b);
3192                                 fprintf(F, " %ld:%d", get_irn_node_nr(b), get_irn_idx(b));
3193                                 fprintf(F, "\" status:clustered color:yellow\n");
3194
3195                                 /* dump the blocks edges */
3196                                 dump_ir_data_edges(F, b);
3197
3198                                 /* dump the nodes that go into the block */
3199                                 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3200                                         if (eset_contains(extnodes, n))
3201                                                 overrule_nodecolor = ird_color_block_inout;
3202                                         dump_node(F, n);
3203                                         overrule_nodecolor = ird_color_default_node;
3204                                         if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
3205                                 }
3206
3207                                 /* Close the vcg information for the block */
3208                                 fprintf(F, "}\n");
3209                                 dump_const_node_local(F, b);
3210                                 fprintf(F, "\n");
3211                         }
3212                 }
3213                 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes)) {
3214                         if (is_Block(b)) {
3215                                 fprintf(F, "graph: { title: \"");
3216                                 PRINT_NODEID(b);
3217                                 fprintf(F, "\"  label: \"");
3218                                 dump_node_opcode(F, b);
3219                                 fprintf(F, " %ld:%d", get_irn_node_nr(b), get_irn_idx(b));
3220                                 fprintf(F, "\" status:clustered color:lightblue\n");
3221
3222                                 /* dump the nodes that go into the block */
3223                                 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3224                                         if (!eset_contains(loopnodes, n))
3225                                                 overrule_nodecolor = ird_color_block_inout;
3226                                         dump_node(F, n);
3227                                         overrule_nodecolor = ird_color_default_node;
3228                                         if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
3229                                 }
3230
3231                                 /* Close the vcg information for the block */
3232                                 fprintf(F, "}\n");
3233                                 dump_const_node_local(F, b);
3234                                 fprintf(F, "\n");
3235                         }
3236                 }
3237                 eset_destroy(loopnodes);
3238                 eset_destroy(extnodes);
3239
3240                 dump_vcg_footer(F);
3241                 fclose(F);
3242         }
3243 }