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