Follow-up to r22928: Remove arch_register_class_put().
[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_t.h"
31 #include "benode_t.h"
32 #include "ircons_t.h"
33 #include "irnode_t.h"
34
35 #include "bitset.h"
36 #include "pset.h"
37 #include "raw_bitset.h"
38
39 #include "irprintf.h"
40
41 /* Initialize the architecture environment struct. */
42 arch_env_t *arch_env_init(const arch_isa_if_t *isa_if, FILE *file_handle, be_main_env_t *main_env)
43 {
44         arch_env_t *arch_env = isa_if->init(file_handle);
45         arch_env->main_env   = main_env;
46         return arch_env;
47 }
48
49 /**
50  * Get the isa responsible for a node.
51  * @param irn The node to get the responsible isa for.
52  * @return The irn operations given by the responsible isa.
53  */
54 static inline const arch_irn_ops_t *get_irn_ops(const ir_node *irn)
55 {
56         const ir_op          *ops;
57         const arch_irn_ops_t *be_ops;
58
59         if (is_Proj(irn)) {
60                 irn = get_Proj_pred(irn);
61                 assert(!is_Proj(irn));
62         }
63
64         ops    = get_irn_op(irn);
65         be_ops = get_op_ops(ops)->be_ops;
66
67         assert(be_ops);
68         return be_ops;
69 }
70
71 const arch_register_req_t *arch_get_register_req(const ir_node *irn, int pos)
72 {
73         const arch_irn_ops_t *ops = get_irn_ops(irn);
74         return ops->get_irn_reg_req(irn, pos);
75 }
76
77 void arch_set_frame_offset(ir_node *irn, int offset)
78 {
79         const arch_irn_ops_t *ops = get_irn_ops(irn);
80         ops->set_frame_offset(irn, offset);
81 }
82
83 ir_entity *arch_get_frame_entity(const ir_node *irn)
84 {
85         const arch_irn_ops_t *ops = get_irn_ops(irn);
86         return ops->get_frame_entity(irn);
87 }
88
89 void arch_set_frame_entity(ir_node *irn, ir_entity *ent)
90 {
91         const arch_irn_ops_t *ops = get_irn_ops(irn);
92         ops->set_frame_entity(irn, ent);
93 }
94
95 int arch_get_sp_bias(ir_node *irn)
96 {
97         const arch_irn_ops_t *ops = get_irn_ops(irn);
98         return ops->get_sp_bias(irn);
99 }
100
101 arch_inverse_t *arch_get_inverse(const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obstack)
102 {
103         const arch_irn_ops_t *ops = get_irn_ops(irn);
104
105         if(ops->get_inverse) {
106                 return ops->get_inverse(irn, i, inverse, obstack);
107         } else {
108                 return NULL;
109         }
110 }
111
112 int arch_possible_memory_operand(const ir_node *irn, unsigned int i)
113 {
114         const arch_irn_ops_t *ops = get_irn_ops(irn);
115
116         if(ops->possible_memory_operand) {
117                 return ops->possible_memory_operand(irn, i);
118         } else {
119                 return 0;
120         }
121 }
122
123 void arch_perform_memory_operand(ir_node *irn, ir_node *spill, unsigned int i)
124 {
125         const arch_irn_ops_t *ops = get_irn_ops(irn);
126
127         if(ops->perform_memory_operand) {
128                 ops->perform_memory_operand(irn, spill, i);
129         } else {
130                 return;
131         }
132 }
133
134 int arch_get_op_estimated_cost(const ir_node *irn)
135 {
136         const arch_irn_ops_t *ops = get_irn_ops(irn);
137
138         if(ops->get_op_estimated_cost) {
139                 return ops->get_op_estimated_cost(irn);
140         } else {
141                 return 1;
142         }
143 }
144
145 void arch_put_non_ignore_regs(const arch_register_class_t *cls, bitset_t *bs)
146 {
147         unsigned i;
148
149         for(i = 0; i < cls->n_regs; ++i) {
150                 if(!arch_register_type_is(&cls->regs[i], ignore))
151                         bitset_set(bs, i);
152         }
153 }
154
155 int arch_reg_is_allocatable(const ir_node *irn, int pos, const arch_register_t *reg)
156 {
157         const arch_register_req_t *req = arch_get_register_req(irn, pos);
158
159         if(req->type == arch_register_req_type_none)
160                 return 0;
161
162         if(arch_register_req_is(req, limited)) {
163                 assert(arch_register_get_class(reg) == req->cls);
164                 return rbitset_is_set(req->limited, arch_register_get_index(reg));
165         }
166
167         return req->cls == reg->reg_class;
168 }
169
170 const arch_register_class_t *arch_get_irn_reg_class(const ir_node *irn, int pos)
171 {
172         const arch_register_req_t *req = arch_get_register_req(irn, pos);
173
174         assert(req->type != arch_register_req_type_none || req->cls == NULL);
175
176         return req->cls;
177 }
178
179 const arch_register_t *arch_get_irn_register(const ir_node *irn)
180 {
181         const arch_irn_ops_t *ops = get_irn_ops(irn);
182         return ops->get_irn_reg(irn);
183 }
184
185 void arch_set_irn_register(ir_node *irn, const arch_register_t *reg)
186 {
187         const arch_irn_ops_t *ops = get_irn_ops(irn);
188         ops->set_irn_reg(irn, reg);
189 }
190
191 arch_irn_class_t arch_irn_classify(const ir_node *irn)
192 {
193         const arch_irn_ops_t *ops = get_irn_ops(irn);
194         return ops->classify(irn);
195 }
196
197 arch_irn_flags_t arch_irn_get_flags(const ir_node *irn)
198 {
199         const arch_irn_ops_t *ops = get_irn_ops(irn);
200         return ops->get_flags(irn);
201 }
202
203 extern char *arch_register_req_format(char *buf, size_t len,
204                                       const arch_register_req_t *req,
205                                       const ir_node *node)
206 {
207         char tmp[128];
208         snprintf(buf, len, "class: %s", req->cls->name);
209
210         if(arch_register_req_is(req, limited)) {
211                 unsigned n_regs = req->cls->n_regs;
212                 unsigned i;
213
214                 strncat(buf, " limited:", len);
215                 for(i = 0; i < n_regs; ++i) {
216                         if(rbitset_is_set(req->limited, i)) {
217                                 const arch_register_t *reg = &req->cls->regs[i];
218                                 strncat(buf, " ", len);
219                                 strncat(buf, reg->name, len);
220                         }
221                 }
222         }
223
224         if(arch_register_req_is(req, should_be_same)) {
225                 const unsigned other = req->other_same;
226                 int i;
227
228                 ir_snprintf(tmp, sizeof(tmp), " same to:");
229                 for (i = 0; 1U << i <= other; ++i) {
230                         if (other & (1U << i)) {
231                                 ir_snprintf(tmp, sizeof(tmp), " %+F", get_irn_n(skip_Proj_const(node), i));
232                                 strncat(buf, tmp, len);
233                         }
234                 }
235         }
236
237         if (arch_register_req_is(req, must_be_different)) {
238                 const unsigned other = req->other_different;
239                 int i;
240
241                 ir_snprintf(tmp, sizeof(tmp), " different from:");
242                 for (i = 0; 1U << i <= other; ++i) {
243                         if (other & (1U << i)) {
244                                 ir_snprintf(tmp, sizeof(tmp), " %+F", get_irn_n(skip_Proj_const(node), i));
245                                 strncat(buf, tmp, len);
246                         }
247                 }
248         }
249
250         return buf;
251 }
252
253 static const arch_register_req_t no_requirement = {
254         arch_register_req_type_none,
255         NULL,
256         NULL,
257         0,
258         0
259 };
260 const arch_register_req_t *arch_no_register_req = &no_requirement;