simplify be_lv_foreach
[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         affinity_node_t *a;
88         co_gs_foreach_aff_node(co, a) {
89                 neighb_t *n;
90
91                 co_gs_foreach_neighb(a, n) {
92                         /* edges are bidirection, dumping one direction is enough */
93                         if (get_irn_node_nr(a->irn) >= get_irn_node_nr(n->irn))
94                                 continue;
95
96                         fprintf(F, "edge: {sourcename: ");
97                         print_nodeid(F, a->irn);
98                         fprintf(F, " targetname: ");
99                         print_nodeid(F, n->irn);
100                         fprintf(F, " arrowstyle:none");
101
102                         if (dump_costs)
103                                 fprintf(F, " label:\"%d\"", n->costs);
104                         if (dump_colors) {
105                                 const arch_register_t *ar = arch_get_irn_register(a->irn);
106                                 const arch_register_t *nr = arch_get_irn_register(n->irn);
107                                 const char *color = nr == ar ? "blue" : "red";
108                                 fprintf(F, " color:%s", color);
109                         }
110                         fprintf(F, " linestyle:dashed class:2");
111                         fprintf(F, "}\n");
112                 }
113         }
114 }
115
116 void be_dump_ifg_co(FILE *F, const copy_opt_t *co, bool dump_costs,
117                     bool dump_colors)
118 {
119         ir_graph *irg = co->irg;
120         be_ifg_t *ifg = co->cenv->ifg;
121
122         ir_fprintf(F,
123                 "graph: { title: \"interference graph of %+F\"\n"
124                 "layoutalgorithm: mindepth //$ \"circular\"\n"
125                 "classname 1: \"interference\"\n"
126                 "classname 2: \"affinity\"\n"
127                 , irg);
128         dump_vcg_infonames(F);
129         dump_vcg_header_colors(F);
130
131         dump_ifg_nodes(F, ifg);
132         dump_ifg_edges(F, ifg);
133         dump_affinity_edges(F, co, dump_costs, dump_colors);
134
135         fprintf(F, "}\n");
136 }
137
138 static const char *lv_flags_to_str(unsigned flags)
139 {
140         static const char *states[] = {
141                 "---",
142                 "i--",
143                 "-e-",
144                 "ie-",
145                 "--o",
146                 "i-o",
147                 "-eo",
148                 "ieo"
149         };
150
151         return states[flags & 7];
152 }
153
154 void be_dump_liveness_block(void *context, FILE *F, const ir_node *bl)
155 {
156         if (is_Block(bl)) {
157                 be_lv_t *lv = (be_lv_t*)context;
158                 be_lv_info_t *info = (be_lv_info_t*)ir_nodehashmap_get(&lv->map, bl);
159
160                 fprintf(F, "liveness:\n");
161                 if (info != NULL) {
162                         unsigned n = info[0].head.n_members;
163                         unsigned i;
164
165                         for (i = 0; i < n; ++i) {
166                                 be_lv_info_node_t *n = &info[i+1].node;
167                                 ir_fprintf(F, "%s %+F\n", lv_flags_to_str(n->flags), get_idx_irn(lv->irg, n->idx));
168                         }
169                 }
170         }
171 }
172
173 typedef struct lv_walker_t {
174         be_lv_t *lv;
175         void *data;
176 } lv_walker_t;
177
178 static void lv_dump_block_walker(ir_node *irn, void *data)
179 {
180         lv_walker_t *w = (lv_walker_t*)data;
181         if (!is_Block(irn))
182                 return;
183         be_dump_liveness_block(w->lv, (FILE*)w->data, irn);
184 }
185
186 void be_liveness_dump(FILE *F, const be_lv_t *lv)
187 {
188         lv_walker_t w;
189
190         w.lv   = (be_lv_t *) lv;
191         w.data = F;
192         irg_block_walk_graph(lv->irg, lv_dump_block_walker, NULL, &w);
193 }