beifg: Let be_ifg_foreach_node() declare the node variable.
[libfirm] / ir / be / bedump.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       Code for dumping backend datastructures (i.e. interference graphs)
23  * @author      Matthias Braun
24  */
25 #include "config.h"
26
27 #include "bedump.h"
28
29 #include "irdump_t.h"
30 #include "irgwalk.h"
31 #include "beifg.h"
32 #include "becopyopt_t.h"
33 #include "belive_t.h"
34
35 static void dump_ifg_nodes(FILE *F, const be_ifg_t *ifg)
36 {
37         nodes_iter_t ifg_iter;
38         be_ifg_foreach_node(ifg, &ifg_iter, node) {
39                 dump_node(F, node);
40         }
41 }
42
43 static void dump_ifg_edges(FILE *F, const be_ifg_t *ifg)
44 {
45         nodes_iter_t ifg_iter;
46
47         be_ifg_foreach_node(ifg, &ifg_iter, node) {
48                 neighbours_iter_t neigh_iter;
49
50                 be_ifg_foreach_neighbour(ifg, &neigh_iter, node, neighbour) {
51                         /* interference is bidirectional, but it's enough to dump 1
52                          * direction */
53                         if (get_irn_node_nr(node) >= get_irn_node_nr(neighbour))
54                                 continue;
55
56                         fprintf(F, "edge: {sourcename: ");
57                         print_nodeid(F, node);
58                         fprintf(F, " targetname: ");
59                         print_nodeid(F, neighbour);
60                         fprintf(F, " arrowstyle:none class:1}\n");
61                 }
62         }
63 }
64
65 void be_dump_ifg(FILE *F, ir_graph *irg, const be_ifg_t *ifg)
66 {
67         ir_fprintf(F,
68                 "graph: { title: \"interference graph of %+F\"\n"
69                 "layoutalgorithm: mindepth //$ \"circular\"\n"
70                 "classname 1: \"interference\"\n"
71                 , irg);
72         dump_vcg_infonames(F);
73         dump_vcg_header_colors(F);
74
75         dump_ifg_nodes(F, ifg);
76         dump_ifg_edges(F, ifg);
77
78         fprintf(F, "}\n");
79 }
80
81 static void dump_affinity_edges(FILE *F, const copy_opt_t *co,
82                                 bool dump_costs, bool dump_colors)
83 {
84         co_gs_foreach_aff_node(co, a) {
85                 co_gs_foreach_neighb(a, n) {
86                         /* edges are bidirection, dumping one direction is enough */
87                         if (get_irn_node_nr(a->irn) >= get_irn_node_nr(n->irn))
88                                 continue;
89
90                         fprintf(F, "edge: {sourcename: ");
91                         print_nodeid(F, a->irn);
92                         fprintf(F, " targetname: ");
93                         print_nodeid(F, n->irn);
94                         fprintf(F, " arrowstyle:none");
95
96                         if (dump_costs)
97                                 fprintf(F, " label:\"%d\"", n->costs);
98                         if (dump_colors) {
99                                 const arch_register_t *ar = arch_get_irn_register(a->irn);
100                                 const arch_register_t *nr = arch_get_irn_register(n->irn);
101                                 const char *color = nr == ar ? "blue" : "red";
102                                 fprintf(F, " color:%s", color);
103                         }
104                         fprintf(F, " linestyle:dashed class:2");
105                         fprintf(F, "}\n");
106                 }
107         }
108 }
109
110 void be_dump_ifg_co(FILE *F, const copy_opt_t *co, bool dump_costs,
111                     bool dump_colors)
112 {
113         ir_graph *irg = co->irg;
114         be_ifg_t *ifg = co->cenv->ifg;
115
116         ir_fprintf(F,
117                 "graph: { title: \"interference graph of %+F\"\n"
118                 "layoutalgorithm: mindepth //$ \"circular\"\n"
119                 "classname 1: \"interference\"\n"
120                 "classname 2: \"affinity\"\n"
121                 , irg);
122         dump_vcg_infonames(F);
123         dump_vcg_header_colors(F);
124
125         dump_ifg_nodes(F, ifg);
126         dump_ifg_edges(F, ifg);
127         dump_affinity_edges(F, co, dump_costs, dump_colors);
128
129         fprintf(F, "}\n");
130 }
131
132 static const char *lv_flags_to_str(unsigned flags)
133 {
134         static const char *states[] = {
135                 "---",
136                 "i--",
137                 "-e-",
138                 "ie-",
139                 "--o",
140                 "i-o",
141                 "-eo",
142                 "ieo"
143         };
144
145         return states[flags & 7];
146 }
147
148 void be_dump_liveness_block(be_lv_t *lv, FILE *F, const ir_node *bl)
149 {
150         be_lv_info_t *info = ir_nodehashmap_get(be_lv_info_t, &lv->map, bl);
151
152         fprintf(F, "liveness:\n");
153         if (info != NULL) {
154                 unsigned n = info[0].head.n_members;
155                 unsigned i;
156
157                 for (i = 0; i < n; ++i) {
158                         be_lv_info_node_t *n = &info[i+1].node;
159                         ir_fprintf(F, "%s %+F\n", lv_flags_to_str(n->flags), n->node);
160                 }
161         }
162 }
163
164 typedef struct lv_walker_t {
165         be_lv_t *lv;
166         FILE    *out;
167 } lv_walker_t;
168
169 static void lv_dump_block_walker(ir_node *irn, void *data)
170 {
171         lv_walker_t *w = (lv_walker_t*)data;
172         if (!is_Block(irn))
173                 return;
174         be_dump_liveness_block(w->lv, w->out, irn);
175 }
176
177 void be_liveness_dump(FILE *F, const be_lv_t *lv)
178 {
179         lv_walker_t w;
180
181         w.lv  = (be_lv_t *) lv;
182         w.out = F;
183         irg_block_walk_graph(lv->irg, lv_dump_block_walker, NULL, &w);
184 }