2 * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
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.
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.
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
22 * @brief code selection (transform FIRM into TEMPLATE FIRM)
28 #include "irgraph_t.h"
38 #include "../benode.h"
39 #include "../betranshlp.h"
40 #include "bearch_TEMPLATE_t.h"
42 #include "TEMPLATE_nodes_attr.h"
43 #include "TEMPLATE_transform.h"
44 #include "TEMPLATE_new_nodes.h"
46 #include "gen_TEMPLATE_regalloc_if.h"
48 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
50 typedef ir_node* (*new_binop_func)(dbg_info *dbgi, ir_node *block,
51 ir_node *left, ir_node *right);
53 static ir_node *transform_binop(ir_node *node, new_binop_func new_func)
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);
63 return new_func(dbgi, new_block, new_left, new_right);
66 static ir_node *gen_And(ir_node *node)
68 return transform_binop(node, new_bd_TEMPLATE_And);
71 static ir_node *gen_Or(ir_node *node)
73 return transform_binop(node, new_bd_TEMPLATE_Or);
76 static ir_node *gen_Eor(ir_node *node)
78 return transform_binop(node, new_bd_TEMPLATE_Xor);
81 static ir_node *gen_Quot(ir_node *node)
83 return transform_binop(node, new_bd_TEMPLATE_fDiv);
86 static ir_node *gen_Shl(ir_node *node)
88 return transform_binop(node, new_bd_TEMPLATE_Shl);
91 static ir_node *gen_Shr(ir_node *node)
93 return transform_binop(node, new_bd_TEMPLATE_Shr);
96 static ir_node *gen_Add(ir_node *node)
98 ir_mode *mode = get_irn_mode(node);
100 if (mode_is_float(mode)) {
101 return transform_binop(node, new_bd_TEMPLATE_fAdd);
103 return transform_binop(node, new_bd_TEMPLATE_Add);
106 static ir_node *gen_Sub(ir_node *node)
108 ir_mode *mode = get_irn_mode(node);
110 if (mode_is_float(mode)) {
111 return transform_binop(node, new_bd_TEMPLATE_fSub);
113 return transform_binop(node, new_bd_TEMPLATE_Sub);
116 static ir_node *gen_Mul(ir_node *node)
118 ir_mode *mode = get_irn_mode(node);
120 if (mode_is_float(mode)) {
121 return transform_binop(node, new_bd_TEMPLATE_fMul);
123 return transform_binop(node, new_bd_TEMPLATE_Mul);
127 typedef ir_node* (*new_unop_func)(dbg_info *dbgi, ir_node *block, ir_node *op);
129 static ir_node *transform_unop(ir_node *node, new_unop_func new_func)
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);
137 return new_func(dbgi, new_block, new_op);
140 static ir_node *gen_Minus(ir_node *node)
142 ir_mode *mode = get_irn_mode(node);
144 if (mode_is_float(mode)) {
145 return transform_unop(node, new_bd_TEMPLATE_fMinus);
147 return transform_unop(node, new_bd_TEMPLATE_Minus);
150 static ir_node *gen_Not(ir_node *node)
152 return transform_unop(node, new_bd_TEMPLATE_Not);
155 static ir_node *gen_Const(ir_node *node)
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);
163 result = new_bd_TEMPLATE_Const(dbgi, new_block, value);
165 /* make sure the node does not float above the barrier into the prologue */
166 be_dep_on_frame(result);
171 static ir_node *gen_Load(ir_node *node)
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);
182 if (mode_is_float(mode)) {
183 return new_bd_TEMPLATE_fLoad(dbgi, new_block, new_ptr, new_mem, mode);
185 return new_bd_TEMPLATE_Load(dbgi, new_block, new_ptr, new_mem, mode);
188 static ir_node *gen_Store(ir_node *node)
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);
201 if (mode_is_float(mode)) {
202 return new_bd_TEMPLATE_fStore(dbgi, new_block, new_ptr, new_val, new_mem, mode);
204 return new_bd_TEMPLATE_Store(dbgi, new_block, new_ptr, new_mem, new_val, mode);
207 static ir_node *gen_Jmp(ir_node *node)
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);
213 return new_bd_TEMPLATE_Jmp(dbgi, new_block);
217 * returns true if mode should be stored in a general purpose register
219 static inline bool mode_needs_gp_reg(ir_mode *mode)
221 return mode_is_int(mode) || mode_is_reference(mode);
224 static ir_node *gen_Phi(ir_node *node)
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);
234 if (mode_needs_gp_reg(mode)) {
236 req = TEMPLATE_reg_classes[CLASS_TEMPLATE_gp].class_req;
238 req = arch_no_register_req;
241 phi = new_ir_node(dbgi, irg, new_block, op_Phi, mode, get_irn_arity(node),
243 copy_node_attr(irg, node, phi);
244 be_duplicate_deps(node, phi);
246 arch_set_out_register_req(phi, 0, req);
247 be_enqueue_preds(node);
251 static ir_node *bad_transform(ir_node *node)
253 panic("TEMPLATE backend: unexpected node %+F", node);
258 static void set_transformer(ir_op *op, be_transform_func transform_func)
260 op->ops.generic = (op_func)transform_func;
263 static void TEMPLATE_register_transformers(void)
265 /* first clear the generic function pointer for all ops */
266 clear_irp_opcodes_generic_func();
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);
285 /* TODO: implement missing nodes */
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);
309 * Transform generic IR-nodes into TEMPLATE machine instructions
311 void TEMPLATE_transform_graph(TEMPLATE_code_gen_t *cg)
313 TEMPLATE_register_transformers();
314 be_transform_graph(cg->irg, NULL);
317 void TEMPLATE_init_transform(void)
319 FIRM_DBG_REGISTER(dbg, "firm.be.TEMPLATE.transform");