2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
8 * @brief code selection (transform FIRM into TEMPLATE FIRM)
13 #include "irgraph_t.h"
23 #include "betranshlp.h"
24 #include "bearch_TEMPLATE_t.h"
26 #include "TEMPLATE_nodes_attr.h"
27 #include "TEMPLATE_transform.h"
28 #include "TEMPLATE_new_nodes.h"
30 #include "gen_TEMPLATE_regalloc_if.h"
32 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
34 typedef ir_node* (*new_binop_func)(dbg_info *dbgi, ir_node *block,
35 ir_node *left, ir_node *right);
37 static ir_mode *gp_regs_mode;
39 static ir_node *transform_binop(ir_node *node, new_binop_func new_func)
41 ir_node *block = get_nodes_block(node);
42 ir_node *new_block = be_transform_node(block);
43 dbg_info *dbgi = get_irn_dbg_info(node);
44 ir_node *left = get_binop_left(node);
45 ir_node *new_left = be_transform_node(left);
46 ir_node *right = get_binop_right(node);
47 ir_node *new_right = be_transform_node(right);
49 return new_func(dbgi, new_block, new_left, new_right);
52 static ir_node *gen_And(ir_node *node)
54 return transform_binop(node, new_bd_TEMPLATE_And);
57 static ir_node *gen_Or(ir_node *node)
59 return transform_binop(node, new_bd_TEMPLATE_Or);
62 static ir_node *gen_Eor(ir_node *node)
64 return transform_binop(node, new_bd_TEMPLATE_Xor);
67 static ir_node *gen_Div(ir_node *node)
69 ir_mode *mode = get_Div_resmode(node);
70 assert(mode_is_float(mode));
71 return transform_binop(node, new_bd_TEMPLATE_fDiv);
74 static ir_node *gen_Shl(ir_node *node)
76 ir_mode *mode = get_irn_mode(node);
77 if (get_mode_modulo_shift(mode) != 32)
78 panic("modulo shift!=32 not supported");
79 return transform_binop(node, new_bd_TEMPLATE_Shl);
82 static ir_node *gen_Shr(ir_node *node)
84 ir_mode *mode = get_irn_mode(node);
85 if (get_mode_modulo_shift(mode) != 32)
86 panic("modulo shift!=32 not supported");
87 return transform_binop(node, new_bd_TEMPLATE_Shr);
90 static ir_node *gen_Add(ir_node *node)
92 ir_mode *mode = get_irn_mode(node);
94 if (mode_is_float(mode)) {
95 return transform_binop(node, new_bd_TEMPLATE_fAdd);
97 return transform_binop(node, new_bd_TEMPLATE_Add);
100 static ir_node *gen_Sub(ir_node *node)
102 ir_mode *mode = get_irn_mode(node);
104 if (mode_is_float(mode)) {
105 return transform_binop(node, new_bd_TEMPLATE_fSub);
107 return transform_binop(node, new_bd_TEMPLATE_Sub);
110 static ir_node *gen_Mul(ir_node *node)
112 ir_mode *mode = get_irn_mode(node);
114 if (mode_is_float(mode)) {
115 return transform_binop(node, new_bd_TEMPLATE_fMul);
117 return transform_binop(node, new_bd_TEMPLATE_Mul);
121 typedef ir_node* (*new_unop_func)(dbg_info *dbgi, ir_node *block, ir_node *op);
123 static ir_node *transform_unop(ir_node *node, new_unop_func new_func)
125 ir_node *block = get_nodes_block(node);
126 ir_node *new_block = be_transform_node(block);
127 dbg_info *dbgi = get_irn_dbg_info(node);
128 ir_node *op = get_unop_op(node);
129 ir_node *new_op = be_transform_node(op);
131 return new_func(dbgi, new_block, new_op);
134 static ir_node *gen_Minus(ir_node *node)
136 ir_mode *mode = get_irn_mode(node);
138 if (mode_is_float(mode)) {
139 return transform_unop(node, new_bd_TEMPLATE_fMinus);
141 return transform_unop(node, new_bd_TEMPLATE_Minus);
144 static ir_node *gen_Not(ir_node *node)
146 return transform_unop(node, new_bd_TEMPLATE_Not);
149 static ir_node *gen_Const(ir_node *node)
151 ir_node *block = get_nodes_block(node);
152 ir_node *new_block = be_transform_node(block);
153 dbg_info *dbgi = get_irn_dbg_info(node);
154 ir_tarval *value = get_Const_tarval(node);
157 result = new_bd_TEMPLATE_Const(dbgi, new_block, value);
162 static ir_node *gen_Load(ir_node *node)
164 ir_node *block = get_nodes_block(node);
165 ir_node *new_block = be_transform_node(block);
166 dbg_info *dbgi = get_irn_dbg_info(node);
167 ir_node *ptr = get_Load_ptr(node);
168 ir_node *new_ptr = be_transform_node(ptr);
169 ir_node *mem = get_Load_mem(node);
170 ir_node *new_mem = be_transform_node(mem);
171 ir_mode *mode = get_irn_mode(node);
173 if (mode_is_float(mode)) {
174 return new_bd_TEMPLATE_fLoad(dbgi, new_block, new_ptr, new_mem, mode);
176 return new_bd_TEMPLATE_Load(dbgi, new_block, new_ptr, new_mem, mode);
179 static ir_node *gen_Store(ir_node *node)
181 ir_node *block = get_nodes_block(node);
182 ir_node *new_block = be_transform_node(block);
183 dbg_info *dbgi = get_irn_dbg_info(node);
184 ir_node *ptr = get_Store_ptr(node);
185 ir_node *new_ptr = be_transform_node(ptr);
186 ir_node *val = get_Store_value(node);
187 ir_node *new_val = be_transform_node(val);
188 ir_node *mem = get_Store_mem(node);
189 ir_node *new_mem = be_transform_node(mem);
190 ir_mode *mode = get_irn_mode(node);
192 if (mode_is_float(mode)) {
193 return new_bd_TEMPLATE_fStore(dbgi, new_block, new_ptr, new_val, new_mem, mode);
195 return new_bd_TEMPLATE_Store(dbgi, new_block, new_ptr, new_mem, new_val, mode);
198 static ir_node *gen_Jmp(ir_node *node)
200 ir_node *block = get_nodes_block(node);
201 ir_node *new_block = be_transform_node(block);
202 dbg_info *dbgi = get_irn_dbg_info(node);
204 return new_bd_TEMPLATE_Jmp(dbgi, new_block);
207 static ir_node *gen_Start(ir_node *node)
209 dbg_info *dbgi = get_irn_dbg_info(node);
210 ir_node *block = get_nodes_block(node);
211 ir_node *new_block = be_transform_node(block);
213 return new_bd_TEMPLATE_Start(dbgi, new_block);
216 static ir_node *gen_Return(ir_node *node)
218 dbg_info *dbgi = get_irn_dbg_info(node);
219 ir_node *block = get_nodes_block(node);
220 ir_node *new_block = be_transform_node(block);
221 ir_node *mem = get_Return_mem(node);
222 ir_node *new_mem = be_transform_node(mem);
223 ir_graph *irg = get_irn_irg(node);
224 ir_node *sp = get_irg_frame(irg);
226 return new_bd_TEMPLATE_Return(dbgi, new_block, sp, new_mem);
230 * returns true if mode should be stored in a general purpose register
232 static inline bool mode_needs_gp_reg(ir_mode *mode)
234 return mode_is_int(mode) || mode_is_reference(mode);
237 static ir_node *gen_Phi(ir_node *node)
239 ir_mode *mode = get_irn_mode(node);
240 const arch_register_req_t *req;
241 if (mode_needs_gp_reg(mode)) {
243 req = TEMPLATE_reg_classes[CLASS_TEMPLATE_gp].class_req;
245 req = arch_no_register_req;
248 return be_transform_phi(node, req);
251 static ir_node *gen_Proj_Start(ir_node *node)
253 dbg_info *dbgi = get_irn_dbg_info(node);
254 ir_node *block = get_nodes_block(node);
255 ir_node *new_block = be_transform_node(block);
256 ir_node *start = get_Proj_pred(node);
257 ir_node *new_start = be_transform_node(start);
258 long pn = get_Proj_proj(node);
260 switch ((pn_Start) pn) {
261 case pn_Start_X_initial_exec:
262 return new_bd_TEMPLATE_Jmp(dbgi, new_block);
264 return new_rd_Proj(dbgi, new_start, mode_M, pn_TEMPLATE_Start_M);
265 case pn_Start_T_args:
266 return new_r_Bad(get_irn_irg(block), mode_T);
267 case pn_Start_P_frame_base:
268 return new_rd_Proj(dbgi, new_start, gp_regs_mode, pn_TEMPLATE_Start_stack);
270 panic("unexpected Start proj %ld\n", pn);
273 static ir_node *gen_Proj(ir_node *node)
275 ir_node *pred = get_Proj_pred(node);
277 switch (get_irn_opcode(pred)) {
278 case iro_Start: return gen_Proj_Start(node);
280 panic("code selection can't handle Proj after %+F\n", pred);
284 static void TEMPLATE_register_transformers(void)
286 be_start_transform_setup();
288 be_set_transform_function(op_Add, gen_Add);
289 be_set_transform_function(op_And, gen_And);
290 be_set_transform_function(op_Const, gen_Const);
291 be_set_transform_function(op_Div, gen_Div);
292 be_set_transform_function(op_Eor, gen_Eor);
293 be_set_transform_function(op_Jmp, gen_Jmp);
294 be_set_transform_function(op_Load, gen_Load);
295 be_set_transform_function(op_Minus, gen_Minus);
296 be_set_transform_function(op_Mul, gen_Mul);
297 be_set_transform_function(op_Not, gen_Not);
298 be_set_transform_function(op_Or, gen_Or);
299 be_set_transform_function(op_Proj, gen_Proj);
300 be_set_transform_function(op_Phi, gen_Phi);
301 be_set_transform_function(op_Return, gen_Return);
302 be_set_transform_function(op_Shl, gen_Shl);
303 be_set_transform_function(op_Shr, gen_Shr);
304 be_set_transform_function(op_Start, gen_Start);
305 be_set_transform_function(op_Store, gen_Store);
306 be_set_transform_function(op_Sub, gen_Sub);
310 * Transform generic IR-nodes into TEMPLATE machine instructions
312 void TEMPLATE_transform_graph(ir_graph *irg)
314 gp_regs_mode = TEMPLATE_reg_classes[CLASS_TEMPLATE_gp].mode;
316 TEMPLATE_register_transformers();
317 be_transform_graph(irg, NULL);
320 void TEMPLATE_init_transform(void)
322 FIRM_DBG_REGISTER(dbg, "firm.be.TEMPLATE.transform");