save input requirements in be_info without complicated callback
[libfirm] / ir / be / TEMPLATE / TEMPLATE_transform.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 selection (transform FIRM into TEMPLATE FIRM)
23  * @version $Id$
24  */
25 #include "config.h"
26
27 #include "irnode_t.h"
28 #include "irgraph_t.h"
29 #include "irmode_t.h"
30 #include "irgmod.h"
31 #include "iredges.h"
32 #include "ircons.h"
33 #include "iropt_t.h"
34 #include "debug.h"
35 #include "error.h"
36
37 #include "../benode.h"
38 #include "../betranshlp.h"
39 #include "bearch_TEMPLATE_t.h"
40
41 #include "TEMPLATE_nodes_attr.h"
42 #include "TEMPLATE_transform.h"
43 #include "TEMPLATE_new_nodes.h"
44
45 #include "gen_TEMPLATE_regalloc_if.h"
46
47 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
48
49 typedef ir_node* (*new_binop_func)(dbg_info *dbgi, ir_node *block,
50                                    ir_node *left, ir_node *right);
51
52 static ir_node *transform_binop(ir_node *node, new_binop_func new_func)
53 {
54         ir_node  *block     = get_nodes_block(node);
55         ir_node  *new_block = be_transform_node(block);
56         dbg_info *dbgi      = get_irn_dbg_info(node);
57         ir_node  *left      = get_binop_left(node);
58         ir_node  *new_left  = be_transform_node(left);
59         ir_node  *right     = get_binop_right(node);
60         ir_node  *new_right = be_transform_node(right);
61
62         return new_func(dbgi, new_block, new_left, new_right);
63 }
64
65 static ir_node *gen_And(ir_node *node)
66 {
67         return transform_binop(node, new_bd_TEMPLATE_And);
68 }
69
70 static ir_node *gen_Or(ir_node *node)
71 {
72         return transform_binop(node, new_bd_TEMPLATE_Or);
73 }
74
75 static ir_node *gen_Eor(ir_node *node)
76 {
77         return transform_binop(node, new_bd_TEMPLATE_Xor);
78 }
79
80 static ir_node *gen_Quot(ir_node *node)
81 {
82         return transform_binop(node, new_bd_TEMPLATE_fDiv);
83 }
84
85 static ir_node *gen_Shl(ir_node *node)
86 {
87         return transform_binop(node, new_bd_TEMPLATE_Shl);
88 }
89
90 static ir_node *gen_Shr(ir_node *node)
91 {
92         return transform_binop(node, new_bd_TEMPLATE_Shr);
93 }
94
95 static ir_node *gen_Add(ir_node *node)
96 {
97         ir_mode *mode = get_irn_mode(node);
98
99         if (mode_is_float(mode)) {
100                 return transform_binop(node, new_bd_TEMPLATE_fAdd);
101         }
102         return transform_binop(node, new_bd_TEMPLATE_Add);
103 }
104
105 static ir_node *gen_Sub(ir_node *node)
106 {
107         ir_mode *mode = get_irn_mode(node);
108
109         if (mode_is_float(mode)) {
110                 return transform_binop(node, new_bd_TEMPLATE_fSub);
111         }
112         return transform_binop(node, new_bd_TEMPLATE_Sub);
113 }
114
115 static ir_node *gen_Mul(ir_node *node)
116 {
117         ir_mode *mode = get_irn_mode(node);
118
119         if (mode_is_float(mode)) {
120                 return transform_binop(node, new_bd_TEMPLATE_fMul);
121         }
122         return transform_binop(node, new_bd_TEMPLATE_Mul);
123 }
124
125
126 typedef ir_node* (*new_unop_func)(dbg_info *dbgi, ir_node *block, ir_node *op);
127
128 static ir_node *transform_unop(ir_node *node, new_unop_func new_func)
129 {
130         ir_node  *block     = get_nodes_block(node);
131         ir_node  *new_block = be_transform_node(block);
132         dbg_info *dbgi      = get_irn_dbg_info(node);
133         ir_node  *op        = get_unop_op(node);
134         ir_node  *new_op    = be_transform_node(op);
135
136         return new_func(dbgi, new_block, new_op);
137 }
138
139 static ir_node *gen_Minus(ir_node *node)
140 {
141         ir_mode *mode = get_irn_mode(node);
142
143         if (mode_is_float(mode)) {
144                 return transform_unop(node, new_bd_TEMPLATE_fMinus);
145         }
146         return transform_unop(node, new_bd_TEMPLATE_Minus);
147 }
148
149 static ir_node *gen_Not(ir_node *node)
150 {
151         return transform_unop(node, new_bd_TEMPLATE_Not);
152 }
153
154 static ir_node *gen_Const(ir_node *node)
155 {
156         ir_node  *block     = get_nodes_block(node);
157         ir_node  *new_block = be_transform_node(block);
158         dbg_info *dbgi      = get_irn_dbg_info(node);
159         tarval   *value     = get_Const_tarval(node);
160         ir_node  *result;
161
162         result = new_bd_TEMPLATE_Const(dbgi, new_block, value);
163
164         /* make sure the node does not float above the barrier into the prologue */
165         be_dep_on_frame(result);
166
167         return result;
168 }
169
170 static ir_node *gen_Load(ir_node *node)
171 {
172         ir_node  *block     = get_nodes_block(node);
173         ir_node  *new_block = be_transform_node(block);
174         dbg_info *dbgi      = get_irn_dbg_info(node);
175         ir_node  *ptr       = get_Load_ptr(node);
176         ir_node  *new_ptr   = be_transform_node(ptr);
177         ir_node  *mem       = get_Load_mem(node);
178         ir_node  *new_mem   = be_transform_node(mem);
179         ir_mode  *mode      = get_irn_mode(node);
180
181         if (mode_is_float(mode)) {
182                 return new_bd_TEMPLATE_fLoad(dbgi, new_block, new_ptr, new_mem, mode);
183         }
184         return new_bd_TEMPLATE_Load(dbgi, new_block, new_ptr, new_mem, mode);
185 }
186
187 static ir_node *gen_Store(ir_node *node)
188 {
189         ir_node  *block     = get_nodes_block(node);
190         ir_node  *new_block = be_transform_node(block);
191         dbg_info *dbgi      = get_irn_dbg_info(node);
192         ir_node  *ptr       = get_Store_ptr(node);
193         ir_node  *new_ptr   = be_transform_node(ptr);
194         ir_node  *val       = get_Store_value(node);
195         ir_node  *new_val   = be_transform_node(val);
196         ir_node  *mem       = get_Store_mem(node);
197         ir_node  *new_mem   = be_transform_node(mem);
198         ir_mode  *mode      = get_irn_mode(node);
199
200         if (mode_is_float(mode)) {
201                 return new_bd_TEMPLATE_fStore(dbgi, new_block, new_ptr, new_val, new_mem, mode);
202         }
203         return new_bd_TEMPLATE_Store(dbgi, new_block, new_ptr, new_mem, new_val, mode);
204 }
205
206 static ir_node *gen_Jmp(ir_node *node)
207 {
208         ir_node  *block     = get_nodes_block(node);
209         ir_node  *new_block = be_transform_node(block);
210         dbg_info *dbgi      = get_irn_dbg_info(node);
211
212         return new_bd_TEMPLATE_Jmp(dbgi, new_block);
213 }
214
215 /**
216  * returns true if mode should be stored in a general purpose register
217  */
218 static inline bool mode_needs_gp_reg(ir_mode *mode)
219 {
220         return mode_is_int(mode) || mode_is_reference(mode);
221 }
222
223 static ir_node *gen_Phi(ir_node *node)
224 {
225         const arch_register_req_t *req;
226         ir_node  *block     = get_nodes_block(node);
227         ir_node  *new_block = be_transform_node(block);
228         dbg_info *dbgi      = get_irn_dbg_info(node);
229         ir_mode  *mode      = get_irn_mode(node);
230         ir_graph *irg       = get_irn_irg(node);
231         ir_node  *phi;
232
233         if (mode_needs_gp_reg(mode)) {
234                 mode = mode_Iu;
235                 req  = TEMPLATE_reg_classes[CLASS_TEMPLATE_gp].class_req;
236         } else {
237                 req = arch_no_register_req;
238         }
239
240         phi = new_ir_node(dbgi, irg, new_block, op_Phi, mode, get_irn_arity(node),
241                           get_irn_in(node)+1);
242         copy_node_attr(irg, node, phi);
243         be_duplicate_deps(node, phi);
244
245         arch_set_out_register_req(phi, 0, req);
246         be_enqueue_preds(node);
247         return phi;
248 }
249
250 static void TEMPLATE_register_transformers(void)
251 {
252         be_start_transform_setup();
253
254         be_set_transform_function(op_Add,   gen_Add);
255         be_set_transform_function(op_And,   gen_And);
256         be_set_transform_function(op_Const, gen_Const);
257         be_set_transform_function(op_Eor,   gen_Eor);
258         be_set_transform_function(op_Jmp,   gen_Jmp);
259         be_set_transform_function(op_Load,  gen_Load);
260         be_set_transform_function(op_Minus, gen_Minus);
261         be_set_transform_function(op_Mul,   gen_Mul);
262         be_set_transform_function(op_Not,   gen_Not);
263         be_set_transform_function(op_Or,    gen_Or);
264         be_set_transform_function(op_Phi,   gen_Phi);
265         be_set_transform_function(op_Quot,  gen_Quot);
266         be_set_transform_function(op_Shl,   gen_Shl);
267         be_set_transform_function(op_Shr,   gen_Shr);
268         be_set_transform_function(op_Store, gen_Store);
269         be_set_transform_function(op_Sub,   gen_Sub);
270 }
271
272 /**
273  * Transform generic IR-nodes into TEMPLATE machine instructions
274  */
275 void TEMPLATE_transform_graph(TEMPLATE_code_gen_t *cg)
276 {
277         TEMPLATE_register_transformers();
278         be_transform_graph(cg->irg, NULL);
279 }
280
281 void TEMPLATE_init_transform(void)
282 {
283         FIRM_DBG_REGISTER(dbg, "firm.be.TEMPLATE.transform");
284 }