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