reorganize backend headers (kill some _t variants in favor of a be_types.h)
[libfirm] / ir / be / bearch.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       Processor architecture specification.
23  * @author      Sebastian Hack
24  * @version     $Id$
25  */
26 #include "config.h"
27
28 #include <string.h>
29
30 #include "bearch.h"
31 #include "benode_t.h"
32 #include "beinfo.h"
33 #include "ircons_t.h"
34 #include "irnode_t.h"
35
36 #include "bitset.h"
37 #include "pset.h"
38 #include "raw_bitset.h"
39
40 #include "irprintf.h"
41
42 /* Initialize the architecture environment struct. */
43 arch_env_t *arch_env_init(const arch_isa_if_t *isa_if, FILE *file_handle, be_main_env_t *main_env)
44 {
45         arch_env_t *arch_env = isa_if->init(file_handle);
46         arch_env->main_env   = main_env;
47         return arch_env;
48 }
49
50 /**
51  * Get the isa responsible for a node.
52  * @param irn The node to get the responsible isa for.
53  * @return The irn operations given by the responsible isa.
54  */
55 static inline const arch_irn_ops_t *get_irn_ops(const ir_node *irn)
56 {
57         const ir_op          *ops;
58         const arch_irn_ops_t *be_ops;
59
60         if (is_Proj(irn)) {
61                 irn = get_Proj_pred(irn);
62                 assert(!is_Proj(irn));
63         }
64
65         ops    = get_irn_op(irn);
66         be_ops = get_op_ops(ops)->be_ops;
67
68         assert(be_ops);
69         return be_ops;
70 }
71
72 const arch_register_req_t *arch_get_register_req(const ir_node *irn, int pos)
73 {
74         const arch_irn_ops_t *ops = get_irn_ops(irn);
75         return ops->get_irn_reg_req(irn, pos);
76 }
77
78 void arch_set_frame_offset(ir_node *irn, int offset)
79 {
80         const arch_irn_ops_t *ops = get_irn_ops(irn);
81         ops->set_frame_offset(irn, offset);
82 }
83
84 ir_entity *arch_get_frame_entity(const ir_node *irn)
85 {
86         const arch_irn_ops_t *ops = get_irn_ops(irn);
87         return ops->get_frame_entity(irn);
88 }
89
90 void arch_set_frame_entity(ir_node *irn, ir_entity *ent)
91 {
92         const arch_irn_ops_t *ops = get_irn_ops(irn);
93         ops->set_frame_entity(irn, ent);
94 }
95
96 int arch_get_sp_bias(ir_node *irn)
97 {
98         const arch_irn_ops_t *ops = get_irn_ops(irn);
99         return ops->get_sp_bias(irn);
100 }
101
102 arch_inverse_t *arch_get_inverse(const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obstack)
103 {
104         const arch_irn_ops_t *ops = get_irn_ops(irn);
105
106         if(ops->get_inverse) {
107                 return ops->get_inverse(irn, i, inverse, obstack);
108         } else {
109                 return NULL;
110         }
111 }
112
113 int arch_possible_memory_operand(const ir_node *irn, unsigned int i)
114 {
115         const arch_irn_ops_t *ops = get_irn_ops(irn);
116
117         if(ops->possible_memory_operand) {
118                 return ops->possible_memory_operand(irn, i);
119         } else {
120                 return 0;
121         }
122 }
123
124 void arch_perform_memory_operand(ir_node *irn, ir_node *spill, unsigned int i)
125 {
126         const arch_irn_ops_t *ops = get_irn_ops(irn);
127
128         if(ops->perform_memory_operand) {
129                 ops->perform_memory_operand(irn, spill, i);
130         } else {
131                 return;
132         }
133 }
134
135 int arch_get_op_estimated_cost(const ir_node *irn)
136 {
137         const arch_irn_ops_t *ops = get_irn_ops(irn);
138
139         if(ops->get_op_estimated_cost) {
140                 return ops->get_op_estimated_cost(irn);
141         } else {
142                 return 1;
143         }
144 }
145
146 void arch_put_non_ignore_regs(const arch_register_class_t *cls, bitset_t *bs)
147 {
148         unsigned i;
149
150         for(i = 0; i < cls->n_regs; ++i) {
151                 if(!arch_register_type_is(&cls->regs[i], ignore))
152                         bitset_set(bs, i);
153         }
154 }
155
156 int arch_reg_is_allocatable(const ir_node *irn, int pos, const arch_register_t *reg)
157 {
158         const arch_register_req_t *req = arch_get_register_req(irn, pos);
159
160         if(req->type == arch_register_req_type_none)
161                 return 0;
162
163         if(arch_register_req_is(req, limited)) {
164                 assert(arch_register_get_class(reg) == req->cls);
165                 return rbitset_is_set(req->limited, arch_register_get_index(reg));
166         }
167
168         return req->cls == reg->reg_class;
169 }
170
171 const arch_register_class_t *arch_get_irn_reg_class(const ir_node *irn, int pos)
172 {
173         const arch_register_req_t *req = arch_get_register_req(irn, pos);
174
175         assert(req->type != arch_register_req_type_none || req->cls == NULL);
176
177         return req->cls;
178 }
179
180 static inline reg_out_info_t *get_out_info(const ir_node *node)
181 {
182         int                   pos  = 0;
183         const backend_info_t *info;
184
185         assert(get_irn_mode(node) != mode_T);
186         if (is_Proj(node)) {
187                 pos  = get_Proj_proj(node);
188                 node = get_Proj_pred(node);
189         }
190
191         info = be_get_info(node);
192         assert(pos >= 0 && pos < ARR_LEN(info->out_infos));
193         return &info->out_infos[pos];
194 }
195
196
197 static inline reg_out_info_t *get_out_info_n(const ir_node *node, int pos)
198 {
199         const backend_info_t *info = be_get_info(node);
200         assert(!is_Proj(node));
201         assert(pos >= 0 && pos < ARR_LEN(info->out_infos));
202         return &info->out_infos[pos];
203 }
204
205
206 const arch_register_t *arch_get_irn_register(const ir_node *node)
207 {
208         const reg_out_info_t *out = get_out_info(node);
209         return out->reg;
210 }
211
212 const arch_register_t *arch_irn_get_register(const ir_node *node, int pos)
213 {
214         const reg_out_info_t *out = get_out_info_n(node, pos);
215         return out->reg;
216 }
217
218 void arch_irn_set_register(ir_node *node, int pos, const arch_register_t *reg)
219 {
220         reg_out_info_t *out = get_out_info_n(node, pos);
221         out->reg            = reg;
222 }
223
224 void arch_set_irn_register(ir_node *node, const arch_register_t *reg)
225 {
226         reg_out_info_t *out = get_out_info(node);
227         out->reg = reg;
228 }
229
230 arch_irn_class_t arch_irn_classify(const ir_node *node)
231 {
232         const arch_irn_ops_t *ops = get_irn_ops(node);
233         return ops->classify(node);
234 }
235
236 arch_irn_flags_t arch_irn_get_flags(const ir_node *node)
237 {
238         backend_info_t *info = be_get_info(node);
239         return info->flags;
240 }
241
242 void arch_irn_set_flags(ir_node *node, arch_irn_flags_t flags)
243 {
244         backend_info_t *info = be_get_info(node);
245         info->flags = flags;
246 }
247
248 void arch_irn_add_flags(ir_node *node, arch_irn_flags_t flags)
249 {
250         backend_info_t *info = be_get_info(node);
251         info->flags |= flags;
252 }
253
254 extern char *arch_register_req_format(char *buf, size_t len,
255                                       const arch_register_req_t *req,
256                                       const ir_node *node)
257 {
258         char tmp[128];
259         snprintf(buf, len, "class: %s", req->cls->name);
260
261         if(arch_register_req_is(req, limited)) {
262                 unsigned n_regs = req->cls->n_regs;
263                 unsigned i;
264
265                 strncat(buf, " limited:", len);
266                 for(i = 0; i < n_regs; ++i) {
267                         if(rbitset_is_set(req->limited, i)) {
268                                 const arch_register_t *reg = &req->cls->regs[i];
269                                 strncat(buf, " ", len);
270                                 strncat(buf, reg->name, len);
271                         }
272                 }
273         }
274
275         if(arch_register_req_is(req, should_be_same)) {
276                 const unsigned other = req->other_same;
277                 int i;
278
279                 ir_snprintf(tmp, sizeof(tmp), " same to:");
280                 for (i = 0; 1U << i <= other; ++i) {
281                         if (other & (1U << i)) {
282                                 ir_snprintf(tmp, sizeof(tmp), " %+F", get_irn_n(skip_Proj_const(node), i));
283                                 strncat(buf, tmp, len);
284                         }
285                 }
286         }
287
288         if (arch_register_req_is(req, must_be_different)) {
289                 const unsigned other = req->other_different;
290                 int i;
291
292                 ir_snprintf(tmp, sizeof(tmp), " different from:");
293                 for (i = 0; 1U << i <= other; ++i) {
294                         if (other & (1U << i)) {
295                                 ir_snprintf(tmp, sizeof(tmp), " %+F", get_irn_n(skip_Proj_const(node), i));
296                                 strncat(buf, tmp, len);
297                         }
298                 }
299         }
300
301         if (arch_register_req_is(req, ignore)) {
302                 strncat(buf, " ignore", len);
303         }
304         if (arch_register_req_is(req, produces_sp)) {
305                 strncat(buf, " produces_sp", len);
306         }
307
308         return buf;
309 }
310
311 static const arch_register_req_t no_requirement = {
312         arch_register_req_type_none,
313         NULL,
314         NULL,
315         0,
316         0
317 };
318 const arch_register_req_t *arch_no_register_req = &no_requirement;