Removed the irn_handler stack.
[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 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <string.h>
31
32 #include "bearch_t.h"
33 #include "benode_t.h"
34 #include "ircons_t.h"
35 #include "irnode_t.h"
36 #include "xmalloc.h"
37
38 #include "bitset.h"
39 #include "pset.h"
40 #include "raw_bitset.h"
41
42 #include "irprintf.h"
43
44 /* Initialize the architecture environment struct. */
45 arch_env_t *arch_env_init(arch_env_t *env, const arch_isa_if_t *isa_if, FILE *file_handle, be_main_env_t *main_env)
46 {
47         memset(env, 0, sizeof(*env));
48         env->isa                  = isa_if->init(file_handle);
49         env->isa->main_env        = main_env;
50         return env;
51 }
52
53 void arch_env_set_irn_handler(arch_env_t *env, arch_get_irn_ops_t *handler)
54 {
55         env->arch_handler = handler;
56 }
57
58 static const arch_irn_ops_t *fallback_irn_ops = NULL;
59
60 int arch_register_class_put(const arch_register_class_t *cls, bitset_t *bs)
61 {
62         if(bs) {
63                 int i, n;
64                 for(i = 0, n = cls->n_regs; i < n; ++i)
65                         bitset_set(bs, i);
66         }
67
68         return cls->n_regs;
69 }
70
71 /**
72  * Get the isa responsible for a node.
73  * @param env The arch environment with the isa stack.
74  * @param irn The node to get the responsible isa for.
75  * @return The irn operations given by the responsible isa.
76  */
77 static INLINE const arch_irn_ops_t *
78 get_irn_ops(const arch_env_t *env, const ir_node *irn)
79 {
80         const arch_irn_ops_t *ops = be_node_get_irn_ops(irn);
81
82         if (ops)
83                 return ops;
84         ops = env->arch_handler(irn);
85
86         return ops != NULL ? ops : fallback_irn_ops;
87 }
88
89 const arch_irn_ops_t *arch_get_irn_ops(const arch_env_t *env, const ir_node *irn) {
90         return get_irn_ops(env, irn);
91 }
92
93 const arch_register_req_t *arch_get_register_req(const arch_env_t *env,
94                                                  const ir_node *irn, int pos)
95 {
96         const arch_irn_ops_t *ops = get_irn_ops(env, irn);
97         return ops->impl->get_irn_reg_req(ops, irn, pos);
98 }
99
100 void arch_set_frame_offset(const arch_env_t *env, ir_node *irn, int offset)
101 {
102         const arch_irn_ops_t *ops = get_irn_ops(env, irn);
103         ops->impl->set_frame_offset(ops, irn, offset);
104 }
105
106 ir_entity *arch_get_frame_entity(const arch_env_t *env, const ir_node *irn)
107 {
108         const arch_irn_ops_t *ops = get_irn_ops(env, irn);
109         return ops->impl->get_frame_entity(ops, irn);
110 }
111
112 void arch_set_frame_entity(const arch_env_t *env, ir_node *irn, ir_entity *ent)
113 {
114         const arch_irn_ops_t *ops = get_irn_ops(env, irn);
115         ops->impl->set_frame_entity(ops, irn, ent);
116 }
117
118 int arch_get_sp_bias(const arch_env_t *env, ir_node *irn)
119 {
120         const arch_irn_ops_t *ops = get_irn_ops(env, irn);
121         return ops->impl->get_sp_bias(ops, irn);
122 }
123
124 arch_inverse_t *arch_get_inverse(const arch_env_t *env, const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obstack)
125 {
126         const arch_irn_ops_t *ops = get_irn_ops(env, irn);
127
128         if(ops->impl->get_inverse) {
129                 return ops->impl->get_inverse(ops, irn, i, inverse, obstack);
130         } else {
131                 return NULL;
132         }
133 }
134
135 int arch_possible_memory_operand(const arch_env_t *env, const ir_node *irn, unsigned int i) {
136         const arch_irn_ops_t *ops = get_irn_ops(env, irn);
137
138         if(ops->impl->possible_memory_operand) {
139                 return ops->impl->possible_memory_operand(ops, irn, i);
140         } else {
141                 return 0;
142         }
143 }
144
145 void arch_perform_memory_operand(const arch_env_t *env, ir_node *irn, ir_node *spill, unsigned int i) {
146         const arch_irn_ops_t *ops = get_irn_ops(env, irn);
147
148         if(ops->impl->perform_memory_operand) {
149                 ops->impl->perform_memory_operand(ops, irn, spill, i);
150         } else {
151                 return;
152         }
153 }
154
155 int arch_get_op_estimated_cost(const arch_env_t *env, const ir_node *irn)
156 {
157         const arch_irn_ops_t *ops = get_irn_ops(env, irn);
158
159         if(ops->impl->get_op_estimated_cost) {
160                 return ops->impl->get_op_estimated_cost(ops, irn);
161         } else {
162                 return 1;
163         }
164 }
165
166 int arch_is_possible_memory_operand(const arch_env_t *env, const ir_node *irn, int i)
167 {
168         const arch_irn_ops_t *ops = get_irn_ops(env, irn);
169
170         if(ops->impl->possible_memory_operand) {
171                 return ops->impl->possible_memory_operand(ops, irn, i);
172         } else {
173                 return 0;
174         }
175 }
176
177 int arch_get_allocatable_regs(const arch_env_t *env, const ir_node *irn, int pos, bitset_t *bs)
178 {
179         const arch_irn_ops_t *ops = get_irn_ops(env, irn);
180         const arch_register_req_t *req = ops->impl->get_irn_reg_req(ops, irn, pos);
181
182         if(req->type == arch_register_req_type_none) {
183                 bitset_clear_all(bs);
184                 return 0;
185         }
186
187         if(arch_register_req_is(req, limited)) {
188                 rbitset_copy_to_bitset(req->limited, bs);
189                 return bitset_popcnt(bs);
190         }
191
192         arch_register_class_put(req->cls, bs);
193         return req->cls->n_regs;
194 }
195
196 void arch_put_non_ignore_regs(const arch_env_t *env,
197                               const arch_register_class_t *cls, bitset_t *bs)
198 {
199         unsigned i;
200         (void) env;
201
202         for(i = 0; i < cls->n_regs; ++i) {
203                 if(!arch_register_type_is(&cls->regs[i], ignore))
204                         bitset_set(bs, i);
205         }
206 }
207
208 int arch_count_non_ignore_regs(const arch_env_t *env,
209                                const arch_register_class_t *cls)
210 {
211         unsigned i;
212         int result = 0;
213         (void) env;
214
215         for(i = 0; i < cls->n_regs; ++i) {
216                 if(!arch_register_type_is(&cls->regs[i], ignore))
217                         result++;
218         }
219
220         return result;
221 }
222
223 int arch_is_register_operand(const arch_env_t *env,
224     const ir_node *irn, int pos)
225 {
226         const arch_irn_ops_t *ops = get_irn_ops(env, irn);
227         const arch_register_req_t *req = ops->impl->get_irn_reg_req(ops, irn, pos);
228
229         return req != NULL;
230 }
231
232 int arch_reg_is_allocatable(const arch_env_t *env, const ir_node *irn,
233     int pos, const arch_register_t *reg)
234 {
235         const arch_register_req_t *req;
236
237         req = arch_get_register_req(env, irn, pos);
238
239         if(req->type == arch_register_req_type_none)
240                 return 0;
241
242         if(arch_register_req_is(req, limited)) {
243                 assert(arch_register_get_class(reg) == req->cls);
244                 return rbitset_is_set(req->limited, arch_register_get_index(reg));
245         }
246
247         return req->cls == reg->reg_class;
248 }
249
250 const arch_register_class_t *
251 arch_get_irn_reg_class(const arch_env_t *env, const ir_node *irn, int pos)
252 {
253         const arch_irn_ops_t *ops = get_irn_ops(env, irn);
254         const arch_register_req_t *req = ops->impl->get_irn_reg_req(ops, irn, pos);
255
256         assert(req->type != arch_register_req_type_none || req->cls == NULL);
257
258         return req->cls;
259 }
260
261 extern const arch_register_t *
262 arch_get_irn_register(const arch_env_t *env, const ir_node *irn)
263 {
264         const arch_irn_ops_t *ops = get_irn_ops(env, irn);
265         return ops->impl->get_irn_reg(ops, irn);
266 }
267
268 extern void arch_set_irn_register(const arch_env_t *env,
269     ir_node *irn, const arch_register_t *reg)
270 {
271         const arch_irn_ops_t *ops = get_irn_ops(env, irn);
272         ops->impl->set_irn_reg(ops, irn, reg);
273 }
274
275 extern arch_irn_class_t arch_irn_classify(const arch_env_t *env, const ir_node *irn)
276 {
277         const arch_irn_ops_t *ops = get_irn_ops(env, irn);
278         return ops->impl->classify(ops, irn);
279 }
280
281 extern arch_irn_flags_t arch_irn_get_flags(const arch_env_t *env, const ir_node *irn)
282 {
283         const arch_irn_ops_t *ops = get_irn_ops(env, irn);
284         return ops->impl->get_flags(ops, irn);
285 }
286
287 extern const char *arch_irn_flag_str(arch_irn_flags_t fl)
288 {
289         switch(fl) {
290 #define XXX(x) case arch_irn_flags_ ## x: return #x;
291                 XXX(dont_spill);
292                 XXX(ignore);
293                 XXX(rematerializable);
294                 XXX(modify_sp);
295                 XXX(modify_flags);
296                 XXX(none);
297 #undef XXX
298         }
299         return "n/a";
300 }
301
302 extern char *arch_register_req_format(char *buf, size_t len,
303                                       const arch_register_req_t *req,
304                                       const ir_node *node)
305 {
306         char tmp[128];
307         snprintf(buf, len, "class: %s", req->cls->name);
308
309         if(arch_register_req_is(req, limited)) {
310                 unsigned n_regs = req->cls->n_regs;
311                 unsigned i;
312
313                 strncat(buf, " limited:", len);
314                 for(i = 0; i < n_regs; ++i) {
315                         if(rbitset_is_set(req->limited, i)) {
316                                 const arch_register_t *reg = &req->cls->regs[i];
317                                 strncat(buf, " ", len);
318                                 strncat(buf, reg->name, len);
319                         }
320                 }
321         }
322
323         if(arch_register_req_is(req, should_be_same)) {
324                 const unsigned other = req->other_same;
325                 int i;
326
327                 ir_snprintf(tmp, sizeof(tmp), " same to:");
328                 for (i = 0; 1U << i <= other; ++i) {
329                         if (other & (1U << i)) {
330                                 ir_snprintf(tmp, sizeof(tmp), " %+F", get_irn_n(skip_Proj_const(node), i));
331                                 strncat(buf, tmp, len);
332                         }
333                 }
334         }
335
336         if(arch_register_req_is(req, should_be_different)) {
337                 const unsigned other = req->other_different;
338                 int i;
339
340                 ir_snprintf(tmp, sizeof(tmp), " different from:");
341                 for (i = 0; 1U << i <= other; ++i) {
342                         if (other & (1U << i)) {
343                                 ir_snprintf(tmp, sizeof(tmp), " %+F", get_irn_n(skip_Proj_const(node), i));
344                                 strncat(buf, tmp, len);
345                         }
346                 }
347         }
348
349         return buf;
350 }
351
352 static const arch_register_req_t no_requirement = {
353         arch_register_req_type_none,
354         NULL,
355         NULL,
356         0,
357         0
358 };
359 const arch_register_req_t *arch_no_register_req = &no_requirement;