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 amd64 FIRM)
27 #include "irgraph_t.h"
37 #include "betranshlp.h"
39 #include "bearch_amd64_t.h"
41 #include "amd64_nodes_attr.h"
42 #include "amd64_transform.h"
43 #include "amd64_new_nodes.h"
45 #include "gen_amd64_regalloc_if.h"
47 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
49 /* Some support functions: */
51 static inline int mode_needs_gp_reg(ir_mode *mode)
53 return mode_is_int(mode) || mode_is_reference(mode);
57 * Create a DAG constructing a given Const.
59 * @param irn a Firm const
61 static ir_node *create_const_graph(ir_node *irn, ir_node *block)
63 ir_tarval *tv = get_Const_tarval(irn);
64 ir_mode *mode = get_tarval_mode(tv);
65 dbg_info *dbgi = get_irn_dbg_info(irn);
68 if (mode_is_reference(mode)) {
69 /* AMD64 is 64bit, so we can safely convert a reference tarval into Iu */
70 assert(get_mode_size_bits(mode) == get_mode_size_bits(mode_Lu));
71 tv = tarval_convert_to(tv, mode_Lu);
74 value = get_tarval_long(tv);
76 return new_bd_amd64_Immediate(dbgi, block, value);
79 /* Op transformers: */
82 * Transforms a Const node.
84 * @return The transformed AMD64 node.
86 static ir_node *gen_Const(ir_node *node) {
87 ir_node *block = be_transform_node(get_nodes_block(node));
88 ir_mode *mode = get_irn_mode(node);
89 ir_node *res = create_const_graph(node, block);
96 * Transforms a SymConst node.
98 * @return The transformed ARM node.
100 static ir_node *gen_SymConst(ir_node *node)
102 ir_node *block = be_transform_node(get_nodes_block(node));
103 ir_entity *entity = get_SymConst_entity(node);
104 dbg_info *dbgi = get_irn_dbg_info(node);
107 new_node = new_bd_amd64_SymConst(dbgi, block, entity);
112 * Transforms an Add node.
114 * @return The transformed AMD64 node.
116 static ir_node *gen_Add(ir_node *node) {
117 ir_node *block = be_transform_node(get_nodes_block(node));
118 ir_node *op1 = get_Add_left(node);
119 ir_node *op2 = get_Add_right(node);
120 dbg_info *dbgi = get_irn_dbg_info(node);
121 ir_node *new_op1 = be_transform_node(op1);
122 ir_node *new_op2 = be_transform_node(op2);
124 ir_node *res = new_bd_amd64_Add(dbgi, block, new_op1, new_op2);
129 * Transforms an Sub node.
131 * @return The transformed AMD64 node.
133 static ir_node *gen_Sub(ir_node *node) {
134 ir_node *block = be_transform_node(get_nodes_block(node));
135 ir_node *op1 = get_Sub_left(node);
136 ir_node *op2 = get_Sub_right(node);
137 dbg_info *dbgi = get_irn_dbg_info(node);
138 ir_node *new_op1 = be_transform_node(op1);
139 ir_node *new_op2 = be_transform_node(op2);
141 ir_node *res = new_bd_amd64_Sub(dbgi, block, new_op1, new_op2);
145 static ir_node *gen_Mul(ir_node *node) {
146 ir_node *block = be_transform_node(get_nodes_block(node));
147 ir_node *op1 = get_Mul_left(node);
148 ir_node *op2 = get_Mul_right(node);
149 dbg_info *dbgi = get_irn_dbg_info(node);
150 ir_node *new_op1 = be_transform_node(op1);
151 ir_node *new_op2 = be_transform_node(op2);
153 ir_node *res = new_bd_amd64_Mul(dbgi, block, new_op1, new_op2);
157 static ir_node *gen_Minus(ir_node *node)
159 ir_node *block = be_transform_node(get_nodes_block(node));
160 ir_node *val = be_transform_node(get_Minus_op(node));
161 dbg_info *dbgi = get_irn_dbg_info(node);
163 return new_bd_amd64_Neg(dbgi, block, val);
166 static ir_node *gen_Jmp(ir_node *node)
168 ir_node *block = get_nodes_block(node);
169 ir_node *new_block = be_transform_node(block);
170 dbg_info *dbgi = get_irn_dbg_info(node);
172 return new_bd_amd64_Jmp(dbgi, new_block);
175 static ir_node *gen_be_Call(ir_node *node)
177 ir_node *res = be_duplicate_node(node);
178 arch_add_irn_flags(res, arch_irn_flags_modify_flags);
183 static ir_node *gen_Cmp(ir_node *node)
185 ir_node *block = be_transform_node(get_nodes_block(node));
186 ir_node *op1 = get_Cmp_left(node);
187 ir_node *op2 = get_Cmp_right(node);
188 ir_mode *cmp_mode = get_irn_mode(op1);
189 dbg_info *dbgi = get_irn_dbg_info(node);
194 if (mode_is_float(cmp_mode)) {
195 panic("Floating point not implemented yet!");
198 assert(get_irn_mode(op2) == cmp_mode);
199 is_unsigned = !mode_is_signed(cmp_mode);
201 new_op1 = be_transform_node(op1);
202 /* new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode); */
203 new_op2 = be_transform_node(op2);
204 /* new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode); */
205 return new_bd_amd64_Cmp(dbgi, block, new_op1, new_op2, false,
212 * @return the created ARM Cond node
214 static ir_node *gen_Cond(ir_node *node)
216 ir_node *const block = be_transform_node(get_nodes_block(node));
217 dbg_info *const dbgi = get_irn_dbg_info(node);
218 ir_node *const selector = get_Cond_selector(node);
219 ir_node *const flag_node = be_transform_node(selector);
220 ir_relation const relation = get_Cmp_relation(selector);
221 return new_bd_amd64_Jcc(dbgi, block, flag_node, relation);
224 static ir_node *gen_Phi(ir_node *node)
226 ir_mode *mode = get_irn_mode(node);
227 const arch_register_req_t *req;
228 if (mode_needs_gp_reg(mode)) {
229 /* all integer operations are on 64bit registers now */
231 req = amd64_reg_classes[CLASS_amd64_gp].class_req;
233 req = arch_no_register_req;
236 return be_transform_phi(node, req);
240 * Transforms a Conv node.
242 * @return The created ia32 Conv node
244 static ir_node *gen_Conv(ir_node *node)
246 ir_node *block = be_transform_node(get_nodes_block(node));
247 ir_node *op = get_Conv_op(node);
248 ir_node *new_op = be_transform_node(op);
249 ir_mode *src_mode = get_irn_mode(op);
250 ir_mode *dst_mode = get_irn_mode(node);
251 dbg_info *dbgi = get_irn_dbg_info(node);
253 if (src_mode == dst_mode)
256 if (mode_is_float(src_mode) || mode_is_float(dst_mode)) {
257 panic("float not supported yet");
258 } else { /* complete in gp registers */
259 int src_bits = get_mode_size_bits(src_mode);
260 int dst_bits = get_mode_size_bits(dst_mode);
263 if (src_bits == dst_bits) {
264 /* kill unnecessary conv */
268 if (src_bits < dst_bits) {
275 return new_bd_amd64_Conv(dbgi, block, new_op, min_mode);
280 * Transforms a Store.
282 * @return the created AMD64 Store node
284 static ir_node *gen_Store(ir_node *node)
286 ir_node *block = be_transform_node(get_nodes_block(node));
287 ir_node *ptr = get_Store_ptr(node);
288 ir_node *new_ptr = be_transform_node(ptr);
289 ir_node *mem = get_Store_mem(node);
290 ir_node *new_mem = be_transform_node(mem);
291 ir_node *val = get_Store_value(node);
292 ir_node *new_val = be_transform_node(val);
293 ir_mode *mode = get_irn_mode(val);
294 dbg_info *dbgi = get_irn_dbg_info(node);
295 ir_node *new_store = NULL;
297 if (mode_is_float(mode)) {
298 panic("Float not supported yet");
300 assert(mode_is_data(mode) && "unsupported mode for Store");
301 new_store = new_bd_amd64_Store(dbgi, block, new_ptr, new_val, new_mem, 0);
303 set_irn_pinned(new_store, get_irn_pinned(node));
310 * @return the created AMD64 Load node
312 static ir_node *gen_Load(ir_node *node)
314 ir_node *block = be_transform_node(get_nodes_block(node));
315 ir_node *ptr = get_Load_ptr(node);
316 ir_node *new_ptr = be_transform_node(ptr);
317 ir_node *mem = get_Load_mem(node);
318 ir_node *new_mem = be_transform_node(mem);
319 ir_mode *mode = get_Load_mode(node);
320 dbg_info *dbgi = get_irn_dbg_info(node);
321 ir_node *new_load = NULL;
323 if (mode_is_float(mode)) {
324 panic("Float not supported yet");
326 assert(mode_is_data(mode) && "unsupported mode for Load");
327 new_load = new_bd_amd64_Load(dbgi, block, new_ptr, new_mem, 0);
329 set_irn_pinned(new_load, get_irn_pinned(node));
335 * Transform a Proj from a Load.
337 static ir_node *gen_Proj_Load(ir_node *node)
339 ir_node *load = get_Proj_pred(node);
340 ir_node *new_load = be_transform_node(load);
341 dbg_info *dbgi = get_irn_dbg_info(node);
342 long proj = get_Proj_proj(node);
344 /* renumber the proj */
345 switch (get_amd64_irn_opcode(new_load)) {
347 /* handle all gp loads equal: they have the same proj numbers. */
348 if (proj == pn_Load_res) {
349 return new_rd_Proj(dbgi, new_load, mode_Lu, pn_amd64_Load_res);
350 } else if (proj == pn_Load_M) {
351 return new_rd_Proj(dbgi, new_load, mode_M, pn_amd64_Load_M);
355 panic("Unsupported Proj from Load");
358 return be_duplicate_node(node);
362 * Transform a Proj node.
364 static ir_node *gen_Proj(ir_node *node)
366 dbg_info *dbgi = get_irn_dbg_info(node);
367 ir_node *pred = get_Proj_pred(node);
368 long proj = get_Proj_proj(node);
372 if (is_Store(pred)) {
373 if (proj == pn_Store_M) {
374 return be_transform_node(pred);
376 panic("Unsupported Proj from Store");
378 } else if (is_Load(pred)) {
379 return gen_Proj_Load(node);
380 } else if (is_Start(pred)) {
383 return be_duplicate_node(node);
387 * Transforms a FrameAddr into an AMD64 Add.
389 static ir_node *gen_be_FrameAddr(ir_node *node)
391 ir_node *block = be_transform_node(get_nodes_block(node));
392 ir_entity *ent = be_get_frame_entity(node);
393 ir_node *fp = be_get_FrameAddr_frame(node);
394 ir_node *new_fp = be_transform_node(fp);
395 dbg_info *dbgi = get_irn_dbg_info(node);
398 new_node = new_bd_amd64_FrameAddr(dbgi, block, new_fp, ent);
402 /* Boilerplate code for transformation: */
404 static void amd64_register_transformers(void)
406 be_start_transform_setup();
408 be_set_transform_function(op_Const, gen_Const);
409 be_set_transform_function(op_SymConst, gen_SymConst);
410 be_set_transform_function(op_Add, gen_Add);
411 be_set_transform_function(op_Sub, gen_Sub);
412 be_set_transform_function(op_Mul, gen_Mul);
413 be_set_transform_function(op_be_Call, gen_be_Call);
414 be_set_transform_function(op_be_FrameAddr, gen_be_FrameAddr);
415 be_set_transform_function(op_Conv, gen_Conv);
416 be_set_transform_function(op_Jmp, gen_Jmp);
417 be_set_transform_function(op_Cmp, gen_Cmp);
418 be_set_transform_function(op_Cond, gen_Cond);
419 be_set_transform_function(op_Phi, gen_Phi);
420 be_set_transform_function(op_Load, gen_Load);
421 be_set_transform_function(op_Store, gen_Store);
422 be_set_transform_function(op_Proj, gen_Proj);
423 be_set_transform_function(op_Minus, gen_Minus);
426 void amd64_transform_graph(ir_graph *irg)
428 amd64_register_transformers();
429 be_transform_graph(irg, NULL);
432 void amd64_init_transform(void)
434 FIRM_DBG_REGISTER(dbg, "firm.be.amd64.transform");