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_mode *gp_regs_mode;
52 
transform_binop(ir_node * node,new_binop_func new_func)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 
gen_And(ir_node * node)66 static ir_node *gen_And(ir_node *node)
67 {
68 	return transform_binop(node, new_bd_TEMPLATE_And);
69 }
70 
gen_Or(ir_node * node)71 static ir_node *gen_Or(ir_node *node)
72 {
73 	return transform_binop(node, new_bd_TEMPLATE_Or);
74 }
75 
gen_Eor(ir_node * node)76 static ir_node *gen_Eor(ir_node *node)
77 {
78 	return transform_binop(node, new_bd_TEMPLATE_Xor);
79 }
80 
gen_Div(ir_node * node)81 static ir_node *gen_Div(ir_node *node)
82 {
83 	ir_mode *mode = get_Div_resmode(node);
84 	assert(mode_is_float(mode));
85 	return transform_binop(node, new_bd_TEMPLATE_fDiv);
86 }
87 
gen_Shl(ir_node * node)88 static ir_node *gen_Shl(ir_node *node)
89 {
90 	ir_mode *mode = get_irn_mode(node);
91 	if (get_mode_modulo_shift(mode) != 32)
92 		panic("modulo shift!=32 not supported");
93 	return transform_binop(node, new_bd_TEMPLATE_Shl);
94 }
95 
gen_Shr(ir_node * node)96 static ir_node *gen_Shr(ir_node *node)
97 {
98 	ir_mode *mode = get_irn_mode(node);
99 	if (get_mode_modulo_shift(mode) != 32)
100 		panic("modulo shift!=32 not supported");
101 	return transform_binop(node, new_bd_TEMPLATE_Shr);
102 }
103 
gen_Add(ir_node * node)104 static ir_node *gen_Add(ir_node *node)
105 {
106 	ir_mode *mode = get_irn_mode(node);
107 
108 	if (mode_is_float(mode)) {
109 		return transform_binop(node, new_bd_TEMPLATE_fAdd);
110 	}
111 	return transform_binop(node, new_bd_TEMPLATE_Add);
112 }
113 
gen_Sub(ir_node * node)114 static ir_node *gen_Sub(ir_node *node)
115 {
116 	ir_mode *mode = get_irn_mode(node);
117 
118 	if (mode_is_float(mode)) {
119 		return transform_binop(node, new_bd_TEMPLATE_fSub);
120 	}
121 	return transform_binop(node, new_bd_TEMPLATE_Sub);
122 }
123 
gen_Mul(ir_node * node)124 static ir_node *gen_Mul(ir_node *node)
125 {
126 	ir_mode *mode = get_irn_mode(node);
127 
128 	if (mode_is_float(mode)) {
129 		return transform_binop(node, new_bd_TEMPLATE_fMul);
130 	}
131 	return transform_binop(node, new_bd_TEMPLATE_Mul);
132 }
133 
134 
135 typedef ir_node* (*new_unop_func)(dbg_info *dbgi, ir_node *block, ir_node *op);
136 
transform_unop(ir_node * node,new_unop_func new_func)137 static ir_node *transform_unop(ir_node *node, new_unop_func new_func)
138 {
139 	ir_node  *block     = get_nodes_block(node);
140 	ir_node  *new_block = be_transform_node(block);
141 	dbg_info *dbgi      = get_irn_dbg_info(node);
142 	ir_node  *op        = get_unop_op(node);
143 	ir_node  *new_op    = be_transform_node(op);
144 
145 	return new_func(dbgi, new_block, new_op);
146 }
147 
gen_Minus(ir_node * node)148 static ir_node *gen_Minus(ir_node *node)
149 {
150 	ir_mode *mode = get_irn_mode(node);
151 
152 	if (mode_is_float(mode)) {
153 		return transform_unop(node, new_bd_TEMPLATE_fMinus);
154 	}
155 	return transform_unop(node, new_bd_TEMPLATE_Minus);
156 }
157 
gen_Not(ir_node * node)158 static ir_node *gen_Not(ir_node *node)
159 {
160 	return transform_unop(node, new_bd_TEMPLATE_Not);
161 }
162 
gen_Const(ir_node * node)163 static ir_node *gen_Const(ir_node *node)
164 {
165 	ir_node   *block     = get_nodes_block(node);
166 	ir_node   *new_block = be_transform_node(block);
167 	dbg_info  *dbgi      = get_irn_dbg_info(node);
168 	ir_tarval *value     = get_Const_tarval(node);
169 	ir_node   *result;
170 
171 	result = new_bd_TEMPLATE_Const(dbgi, new_block, value);
172 
173 	return result;
174 }
175 
gen_Load(ir_node * node)176 static ir_node *gen_Load(ir_node *node)
177 {
178 	ir_node  *block     = get_nodes_block(node);
179 	ir_node  *new_block = be_transform_node(block);
180 	dbg_info *dbgi      = get_irn_dbg_info(node);
181 	ir_node  *ptr       = get_Load_ptr(node);
182 	ir_node  *new_ptr   = be_transform_node(ptr);
183 	ir_node  *mem       = get_Load_mem(node);
184 	ir_node  *new_mem   = be_transform_node(mem);
185 	ir_mode  *mode      = get_irn_mode(node);
186 
187 	if (mode_is_float(mode)) {
188 		return new_bd_TEMPLATE_fLoad(dbgi, new_block, new_ptr, new_mem, mode);
189 	}
190 	return new_bd_TEMPLATE_Load(dbgi, new_block, new_ptr, new_mem, mode);
191 }
192 
gen_Store(ir_node * node)193 static ir_node *gen_Store(ir_node *node)
194 {
195 	ir_node  *block     = get_nodes_block(node);
196 	ir_node  *new_block = be_transform_node(block);
197 	dbg_info *dbgi      = get_irn_dbg_info(node);
198 	ir_node  *ptr       = get_Store_ptr(node);
199 	ir_node  *new_ptr   = be_transform_node(ptr);
200 	ir_node  *val       = get_Store_value(node);
201 	ir_node  *new_val   = be_transform_node(val);
202 	ir_node  *mem       = get_Store_mem(node);
203 	ir_node  *new_mem   = be_transform_node(mem);
204 	ir_mode  *mode      = get_irn_mode(node);
205 
206 	if (mode_is_float(mode)) {
207 		return new_bd_TEMPLATE_fStore(dbgi, new_block, new_ptr, new_val, new_mem, mode);
208 	}
209 	return new_bd_TEMPLATE_Store(dbgi, new_block, new_ptr, new_mem, new_val, mode);
210 }
211 
gen_Jmp(ir_node * node)212 static ir_node *gen_Jmp(ir_node *node)
213 {
214 	ir_node  *block     = get_nodes_block(node);
215 	ir_node  *new_block = be_transform_node(block);
216 	dbg_info *dbgi      = get_irn_dbg_info(node);
217 
218 	return new_bd_TEMPLATE_Jmp(dbgi, new_block);
219 }
220 
gen_Start(ir_node * node)221 static ir_node *gen_Start(ir_node *node)
222 {
223 	dbg_info *dbgi      = get_irn_dbg_info(node);
224 	ir_node  *block     = get_nodes_block(node);
225 	ir_node  *new_block = be_transform_node(block);
226 
227 	return new_bd_TEMPLATE_Start(dbgi, new_block);
228 }
229 
gen_Return(ir_node * node)230 static ir_node *gen_Return(ir_node *node)
231 {
232 	dbg_info *dbgi      = get_irn_dbg_info(node);
233 	ir_node  *block     = get_nodes_block(node);
234 	ir_node  *new_block = be_transform_node(block);
235 	ir_node  *mem       = get_Return_mem(node);
236 	ir_node  *new_mem   = be_transform_node(mem);
237 	ir_graph *irg       = get_irn_irg(node);
238 	ir_node  *sp        = get_irg_frame(irg);
239 
240 	return new_bd_TEMPLATE_Return(dbgi, new_block, sp, new_mem);
241 }
242 
243 /**
244  * returns true if mode should be stored in a general purpose register
245  */
mode_needs_gp_reg(ir_mode * mode)246 static inline bool mode_needs_gp_reg(ir_mode *mode)
247 {
248 	return mode_is_int(mode) || mode_is_reference(mode);
249 }
250 
gen_Phi(ir_node * node)251 static ir_node *gen_Phi(ir_node *node)
252 {
253 	ir_mode                   *mode = get_irn_mode(node);
254 	const arch_register_req_t *req;
255 	if (mode_needs_gp_reg(mode)) {
256 		mode = mode_Iu;
257 		req  = TEMPLATE_reg_classes[CLASS_TEMPLATE_gp].class_req;
258 	} else {
259 		req = arch_no_register_req;
260 	}
261 
262 	return be_transform_phi(node, req);
263 }
264 
gen_Proj_Start(ir_node * node)265 static ir_node *gen_Proj_Start(ir_node *node)
266 {
267 	dbg_info *dbgi      = get_irn_dbg_info(node);
268 	ir_node  *block     = get_nodes_block(node);
269 	ir_node  *new_block = be_transform_node(block);
270 	ir_node  *start     = get_Proj_pred(node);
271 	ir_node  *new_start = be_transform_node(start);
272 	long      pn        = get_Proj_proj(node);
273 
274 	switch ((pn_Start) pn) {
275 	case pn_Start_X_initial_exec:
276 		return new_bd_TEMPLATE_Jmp(dbgi, new_block);
277 	case pn_Start_M:
278 		return new_rd_Proj(dbgi, new_start, mode_M, pn_TEMPLATE_Start_M);
279 	case pn_Start_T_args:
280 		return new_r_Bad(get_irn_irg(block), mode_T);
281 	case pn_Start_P_frame_base:
282 		return new_rd_Proj(dbgi, new_start, gp_regs_mode, pn_TEMPLATE_Start_stack);
283 	}
284 	panic("unexpected Start proj %ld\n", pn);
285 }
286 
gen_Proj(ir_node * node)287 static ir_node *gen_Proj(ir_node *node)
288 {
289 	ir_node *pred = get_Proj_pred(node);
290 
291 	switch (get_irn_opcode(pred)) {
292 	case iro_Start: return gen_Proj_Start(node);
293 	default:
294 		panic("code selection can't handle Proj after %+F\n", pred);
295 	}
296 }
297 
TEMPLATE_register_transformers(void)298 static void TEMPLATE_register_transformers(void)
299 {
300 	be_start_transform_setup();
301 
302 	be_set_transform_function(op_Add,    gen_Add);
303 	be_set_transform_function(op_And,    gen_And);
304 	be_set_transform_function(op_Const,  gen_Const);
305 	be_set_transform_function(op_Div,    gen_Div);
306 	be_set_transform_function(op_Eor,    gen_Eor);
307 	be_set_transform_function(op_Jmp,    gen_Jmp);
308 	be_set_transform_function(op_Load,   gen_Load);
309 	be_set_transform_function(op_Minus,  gen_Minus);
310 	be_set_transform_function(op_Mul,    gen_Mul);
311 	be_set_transform_function(op_Not,    gen_Not);
312 	be_set_transform_function(op_Or,     gen_Or);
313 	be_set_transform_function(op_Proj,   gen_Proj);
314 	be_set_transform_function(op_Phi,    gen_Phi);
315 	be_set_transform_function(op_Return, gen_Return);
316 	be_set_transform_function(op_Shl,    gen_Shl);
317 	be_set_transform_function(op_Shr,    gen_Shr);
318 	be_set_transform_function(op_Start,  gen_Start);
319 	be_set_transform_function(op_Store,  gen_Store);
320 	be_set_transform_function(op_Sub,    gen_Sub);
321 }
322 
323 /**
324  * Transform generic IR-nodes into TEMPLATE machine instructions
325  */
TEMPLATE_transform_graph(ir_graph * irg)326 void TEMPLATE_transform_graph(ir_graph *irg)
327 {
328 	gp_regs_mode = TEMPLATE_reg_classes[CLASS_TEMPLATE_gp].mode;
329 
330 	TEMPLATE_register_transformers();
331 	be_transform_graph(irg, NULL);
332 }
333 
TEMPLATE_init_transform(void)334 void TEMPLATE_init_transform(void)
335 {
336 	FIRM_DBG_REGISTER(dbg, "firm.be.TEMPLATE.transform");
337 }
338