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