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