72996fae2e5c948edabc8704480ffc8feff9fad0
[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 "irvrfy.h"
33 #include "ircons.h"
34 #include "iropt_t.h"
35 #include "debug.h"
36 #include "error.h"
37
38 #include "../benode.h"
39 #include "../betranshlp.h"
40 #include "bearch_TEMPLATE_t.h"
41
42 #include "TEMPLATE_nodes_attr.h"
43 #include "TEMPLATE_transform.h"
44 #include "TEMPLATE_new_nodes.h"
45
46 #include "gen_TEMPLATE_regalloc_if.h"
47
48 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
49
50 typedef ir_node* (*new_binop_func)(dbg_info *dbgi, ir_node *block,
51                                    ir_node *left, ir_node *right);
52
53 static ir_node *transform_binop(ir_node *node, new_binop_func new_func)
54 {
55         ir_node  *block     = get_nodes_block(node);
56         ir_node  *new_block = be_transform_node(block);
57         dbg_info *dbgi      = get_irn_dbg_info(node);
58         ir_node  *left      = get_binop_left(node);
59         ir_node  *new_left  = be_transform_node(left);
60         ir_node  *right     = get_binop_right(node);
61         ir_node  *new_right = be_transform_node(right);
62
63         return new_func(dbgi, new_block, new_left, new_right);
64 }
65
66 static ir_node *gen_And(ir_node *node)
67 {
68         return transform_binop(node, new_bd_TEMPLATE_And);
69 }
70
71 static ir_node *gen_Or(ir_node *node)
72 {
73         return transform_binop(node, new_bd_TEMPLATE_Or);
74 }
75
76 static ir_node *gen_Eor(ir_node *node)
77 {
78         return transform_binop(node, new_bd_TEMPLATE_Xor);
79 }
80
81 static ir_node *gen_Quot(ir_node *node)
82 {
83         return transform_binop(node, new_bd_TEMPLATE_fDiv);
84 }
85
86 static ir_node *gen_Shl(ir_node *node)
87 {
88         return transform_binop(node, new_bd_TEMPLATE_Shl);
89 }
90
91 static ir_node *gen_Shr(ir_node *node)
92 {
93         return transform_binop(node, new_bd_TEMPLATE_Shr);
94 }
95
96 static ir_node *gen_Add(ir_node *node)
97 {
98         ir_mode *mode = get_irn_mode(node);
99
100         if (mode_is_float(mode)) {
101                 return transform_binop(node, new_bd_TEMPLATE_fAdd);
102         }
103         return transform_binop(node, new_bd_TEMPLATE_Add);
104 }
105
106 static ir_node *gen_Sub(ir_node *node)
107 {
108         ir_mode *mode = get_irn_mode(node);
109
110         if (mode_is_float(mode)) {
111                 return transform_binop(node, new_bd_TEMPLATE_fSub);
112         }
113         return transform_binop(node, new_bd_TEMPLATE_Sub);
114 }
115
116 static ir_node *gen_Mul(ir_node *node)
117 {
118         ir_mode *mode = get_irn_mode(node);
119
120         if (mode_is_float(mode)) {
121                 return transform_binop(node, new_bd_TEMPLATE_fMul);
122         }
123         return transform_binop(node, new_bd_TEMPLATE_Mul);
124 }
125
126
127 typedef ir_node* (*new_unop_func)(dbg_info *dbgi, ir_node *block, ir_node *op);
128
129 static ir_node *transform_unop(ir_node *node, new_unop_func new_func)
130 {
131         ir_node  *block     = get_nodes_block(node);
132         ir_node  *new_block = be_transform_node(block);
133         dbg_info *dbgi      = get_irn_dbg_info(node);
134         ir_node  *op        = get_unop_op(node);
135         ir_node  *new_op    = be_transform_node(op);
136
137         return new_func(dbgi, new_block, new_op);
138 }
139
140 static ir_node *gen_Minus(ir_node *node)
141 {
142         ir_mode *mode = get_irn_mode(node);
143
144         if (mode_is_float(mode)) {
145                 return transform_unop(node, new_bd_TEMPLATE_fMinus);
146         }
147         return transform_unop(node, new_bd_TEMPLATE_Minus);
148 }
149
150 static ir_node *gen_Not(ir_node *node)
151 {
152         return transform_unop(node, new_bd_TEMPLATE_Not);
153 }
154
155 static ir_node *gen_Const(ir_node *node)
156 {
157         ir_node  *block     = get_nodes_block(node);
158         ir_node  *new_block = be_transform_node(block);
159         dbg_info *dbgi      = get_irn_dbg_info(node);
160         tarval   *value     = get_Const_tarval(node);
161         ir_node  *result;
162
163         result = new_bd_TEMPLATE_Const(dbgi, new_block, value);
164
165         /* make sure the node does not float above the barrier into the prologue */
166         be_dep_on_frame(result);
167
168         return result;
169 }
170
171 static ir_node *gen_Load(ir_node *node)
172 {
173         ir_node  *block     = get_nodes_block(node);
174         ir_node  *new_block = be_transform_node(block);
175         dbg_info *dbgi      = get_irn_dbg_info(node);
176         ir_node  *ptr       = get_Load_ptr(node);
177         ir_node  *new_ptr   = be_transform_node(ptr);
178         ir_node  *mem       = get_Load_mem(node);
179         ir_node  *new_mem   = be_transform_node(mem);
180         ir_mode  *mode      = get_irn_mode(node);
181
182         if (mode_is_float(mode)) {
183                 return new_bd_TEMPLATE_fLoad(dbgi, new_block, new_ptr, new_mem, mode);
184         }
185         return new_bd_TEMPLATE_Load(dbgi, new_block, new_ptr, new_mem, mode);
186 }
187
188 static ir_node *gen_Store(ir_node *node)
189 {
190         ir_node  *block     = get_nodes_block(node);
191         ir_node  *new_block = be_transform_node(block);
192         dbg_info *dbgi      = get_irn_dbg_info(node);
193         ir_node  *ptr       = get_Store_ptr(node);
194         ir_node  *new_ptr   = be_transform_node(ptr);
195         ir_node  *val       = get_Store_value(node);
196         ir_node  *new_val   = be_transform_node(val);
197         ir_node  *mem       = get_Store_mem(node);
198         ir_node  *new_mem   = be_transform_node(mem);
199         ir_mode  *mode      = get_irn_mode(node);
200
201         if (mode_is_float(mode)) {
202                 return new_bd_TEMPLATE_fStore(dbgi, new_block, new_ptr, new_val, new_mem, mode);
203         }
204         return new_bd_TEMPLATE_Store(dbgi, new_block, new_ptr, new_mem, new_val, mode);
205 }
206
207 static ir_node *gen_Jmp(ir_node *node)
208 {
209         ir_node  *block     = get_nodes_block(node);
210         ir_node  *new_block = be_transform_node(block);
211         dbg_info *dbgi      = get_irn_dbg_info(node);
212
213         return new_bd_TEMPLATE_Jmp(dbgi, new_block);
214 }
215
216 /**
217  * returns true if mode should be stored in a general purpose register
218  */
219 static inline bool mode_needs_gp_reg(ir_mode *mode)
220 {
221         return mode_is_int(mode) || mode_is_reference(mode);
222 }
223
224 static ir_node *gen_Phi(ir_node *node)
225 {
226         const arch_register_req_t *req;
227         ir_node  *block     = get_nodes_block(node);
228         ir_node  *new_block = be_transform_node(block);
229         dbg_info *dbgi      = get_irn_dbg_info(node);
230         ir_mode  *mode      = get_irn_mode(node);
231         ir_graph *irg       = get_irn_irg(node);
232         ir_node  *phi;
233
234         if (mode_needs_gp_reg(mode)) {
235                 mode = mode_Iu;
236                 req  = TEMPLATE_reg_classes[CLASS_TEMPLATE_gp].class_req;
237         } else {
238                 req = arch_no_register_req;
239         }
240
241         phi = new_ir_node(dbgi, irg, new_block, op_Phi, mode, get_irn_arity(node),
242                           get_irn_in(node)+1);
243         copy_node_attr(irg, node, phi);
244         be_duplicate_deps(node, phi);
245
246         arch_set_out_register_req(phi, 0, req);
247         be_enqueue_preds(node);
248         return phi;
249 }
250
251 static ir_node *bad_transform(ir_node *node)
252 {
253         panic("TEMPLATE backend: unexpected node %+F", node);
254 }
255
256
257
258 static void set_transformer(ir_op *op, be_transform_func transform_func)
259 {
260         op->ops.generic = (op_func)transform_func;
261 }
262
263 static void TEMPLATE_register_transformers(void)
264 {
265         /* first clear the generic function pointer for all ops */
266         clear_irp_opcodes_generic_func();
267
268         set_transformer(op_Add,       gen_Add);
269         set_transformer(op_And,       gen_And);
270         set_transformer(op_Const,     gen_Const);
271         set_transformer(op_Eor,       gen_Eor);
272         set_transformer(op_Jmp,       gen_Jmp);
273         set_transformer(op_Load,      gen_Load);
274         set_transformer(op_Minus,     gen_Minus);
275         set_transformer(op_Mul,       gen_Mul);
276         set_transformer(op_Not,       gen_Not);
277         set_transformer(op_Or,        gen_Or);
278         set_transformer(op_Phi,       gen_Phi);
279         set_transformer(op_Quot,      gen_Quot);
280         set_transformer(op_Shl,       gen_Shl);
281         set_transformer(op_Shr,       gen_Shr);
282         set_transformer(op_Store,     gen_Store);
283         set_transformer(op_Sub,       gen_Sub);
284
285         /* TODO: implement missing nodes */
286
287
288         /* you should not see the following nodes */
289         set_transformer(op_ASM,       bad_transform);
290         set_transformer(op_Builtin,   bad_transform);
291         set_transformer(op_CallBegin, bad_transform);
292         set_transformer(op_Cast,      bad_transform);
293         set_transformer(op_Confirm,   bad_transform);
294         set_transformer(op_DivMod,    bad_transform);
295         set_transformer(op_EndExcept, bad_transform);
296         set_transformer(op_EndReg,    bad_transform);
297         set_transformer(op_Filter,    bad_transform);
298         set_transformer(op_Free,      bad_transform);
299         set_transformer(op_Id,        bad_transform);
300         set_transformer(op_InstOf,    bad_transform);
301         set_transformer(op_Mulh,      bad_transform);
302         set_transformer(op_Mux,       bad_transform);
303         set_transformer(op_Raise,     bad_transform);
304         set_transformer(op_Sel,       bad_transform);
305         set_transformer(op_Tuple,     bad_transform);
306 }
307
308 /**
309  * Transform generic IR-nodes into TEMPLATE machine instructions
310  */
311 void TEMPLATE_transform_graph(TEMPLATE_code_gen_t *cg)
312 {
313         TEMPLATE_register_transformers();
314         be_transform_graph(cg->irg, NULL);
315 }
316
317 void TEMPLATE_init_transform(void)
318 {
319         FIRM_DBG_REGISTER(dbg, "firm.be.TEMPLATE.transform");
320 }