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