479a40d70006142f2255b02b982f864134f4ea1a
[libfirm] / ir / be / amd64 / amd64_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 amd64 FIRM)
23  * @version $Id: amd64_transform.c 26673 2009-10-01 16:43:13Z matze $
24  */
25 #include "config.h"
26
27 #include "irnode_t.h"
28 #include "irgraph_t.h"
29 #include "irmode_t.h"
30 #include "irgmod.h"
31 #include "iredges.h"
32 #include "irvrfy.h"
33 #include "ircons.h"
34 #include "iropt_t.h"
35 #include "error.h"
36 #include "debug.h"
37
38 #include "../benode.h"
39 #include "../betranshlp.h"
40 #include "bearch_amd64_t.h"
41
42 #include "amd64_nodes_attr.h"
43 #include "amd64_transform.h"
44 #include "amd64_new_nodes.h"
45
46 #include "gen_amd64_regalloc_if.h"
47
48 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
49
50 /** holds the current code generator during transformation */
51 static amd64_code_gen_t *env_cg;
52
53 ///* its enough to have those once */
54 //static ir_node *nomem, *noreg_GP;
55
56 /* Some support functions: */
57
58 static inline int mode_needs_gp_reg(ir_mode *mode)
59 {
60         return mode_is_int(mode) || mode_is_reference(mode);
61 }
62
63 /**
64  * Create a DAG constructing a given Const.
65  *
66  * @param irn  a Firm const
67  */
68 static ir_node *create_const_graph(ir_node *irn, ir_node *block)
69 {
70         tarval  *tv    = get_Const_tarval(irn);
71         ir_mode *mode  = get_tarval_mode(tv);
72         dbg_info *dbgi = get_irn_dbg_info(irn);
73         unsigned value;
74
75         if (mode_is_reference(mode)) {
76                 /* AMD64 is 64bit, so we can safely convert a reference tarval into Iu */
77                 assert(get_mode_size_bits(mode) == get_mode_size_bits(mode_Iu));
78                 tv = tarval_convert_to(tv, mode_Iu);
79         }
80
81         value = get_tarval_long(tv);
82         //d// printf ("TEST GENERATE %d\n", value);
83
84         return new_bd_amd64_Immediate(dbgi, block, value);
85 }
86
87 /* Op transformers: */
88
89 /**
90  * Transforms a Const node.
91  *
92  * @return The transformed AMD64 node.
93  */
94 static ir_node *gen_Const(ir_node *node) {
95         ir_node  *block = be_transform_node(get_nodes_block(node));
96         ir_mode  *mode  = get_irn_mode(node);
97         ir_node *res = create_const_graph(node, block);
98         (void) mode;
99
100         be_dep_on_frame(res);
101
102         return res;
103 }
104
105 /**
106  * Transforms a SymConst node.
107  *
108  * @return The transformed ARM node.
109  */
110 static ir_node *gen_SymConst(ir_node *node)
111 {
112         ir_node   *block  = be_transform_node(get_nodes_block(node));
113         ir_entity *entity = get_SymConst_entity(node);
114         dbg_info  *dbgi   = get_irn_dbg_info(node);
115         ir_node   *new_node;
116
117         new_node = new_bd_amd64_SymConst(dbgi, block, entity);
118         be_dep_on_frame(new_node);
119         return new_node;
120 }
121
122 /**
123  * Transforms an Add node.
124  *
125  * @return The transformed AMD64 node.
126  */
127 static ir_node *gen_Add(ir_node *node) {
128         ir_node  *block = be_transform_node(get_nodes_block(node));
129         /* ir_mode  *mode  = get_irn_mode(node); */
130         ir_node  *op1   = get_Add_left(node);
131         ir_node  *op2   = get_Add_right(node);
132         dbg_info *dbgi  = get_irn_dbg_info(node);
133         ir_node  *new_op1 = be_transform_node(op1);
134         ir_node  *new_op2 = be_transform_node(op2);
135
136         ir_node *res = new_bd_amd64_Add(dbgi, block, new_op1, new_op2);
137         be_dep_on_frame (res);
138         return res;
139 }
140
141 static ir_node *gen_Jmp(ir_node *node)
142 {
143         ir_node  *block     = get_nodes_block(node);
144         ir_node  *new_block = be_transform_node(block);
145         dbg_info *dbgi      = get_irn_dbg_info(node);
146
147         return new_bd_amd64_Jmp(dbgi, new_block);
148 }
149
150 static ir_node *gen_be_Call(ir_node *node)
151 {
152         ir_node *res = be_duplicate_node(node);
153         arch_irn_add_flags(res, arch_irn_flags_modify_flags);
154
155         return res;
156 }
157
158
159 ///**
160 // * Create an And that will zero out upper bits.
161 // *
162 // * @param dbgi     debug info
163 // * @param block    the basic block
164 // * @param op       the original node
165 // * param src_bits  number of lower bits that will remain
166 // */
167 //static ir_node *gen_zero_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
168 //                                   int src_bits)
169 //{
170 //      if (src_bits == 8) {
171 //              return new_bd_arm_And_imm(dbgi, block, op, 0xFF, 0);
172 //      } else if (src_bits == 16) {
173 //              ir_node *lshift = new_bd_arm_Mov_reg_shift_imm(dbgi, block, op, ARM_SHF_LSL_IMM, 16);
174 //              ir_node *rshift = new_bd_arm_Mov_reg_shift_imm(dbgi, block, lshift, ARM_SHF_LSR_IMM, 16);
175 //              return rshift;
176 //      } else {
177 //              panic("zero extension only supported for 8 and 16 bits");
178 //      }
179 //}
180 //
181 ///**
182 // * Generate code for a sign extension.
183 // */
184 //static ir_node *gen_sign_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
185 //                                   int src_bits)
186 //{
187 //      int shift_width = 32 - src_bits;
188 //      ir_node *lshift_node = new_bd_arm_Mov_reg_shift_imm(dbgi, block, op, ARM_SHF_LSL_IMM, shift_width);
189 //      ir_node *rshift_node = new_bd_arm_Mov_reg_shift_imm(dbgi, block, lshift_node, ARM_SHF_ASR_IMM, shift_width);
190 //      return rshift_node;
191 //}
192 //
193 //static ir_node *gen_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
194 //                              ir_mode *orig_mode)
195 //{
196 //      int bits = get_mode_size_bits(orig_mode);
197 //      if (bits == 32)
198 //              return op;
199 //
200 //      if (mode_is_signed(orig_mode)) {
201 //              return gen_sign_extension(dbgi, block, op, bits);
202 //      } else {
203 //              return gen_zero_extension(dbgi, block, op, bits);
204 //      }
205 //}
206 //
207 ///**
208 // * returns true if it is assured, that the upper bits of a node are "clean"
209 // * which means for a 16 or 8 bit value, that the upper bits in the register
210 // * are 0 for unsigned and a copy of the last significant bit for signed
211 // * numbers.
212 // */
213 //static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode)
214 //{
215 //      (void) transformed_node;
216 //      (void) mode;
217 //      /* TODO */
218 //      return false;
219 //}
220
221 /**
222  * Change some phi modes
223  */
224 static ir_node *gen_Phi(ir_node *node)
225 {
226         const arch_register_req_t *req;
227         ir_node  *block = be_transform_node(get_nodes_block(node));
228         ir_graph *irg   = current_ir_graph;
229         dbg_info *dbgi  = get_irn_dbg_info(node);
230         ir_mode  *mode  = get_irn_mode(node);
231         ir_node  *phi;
232
233         if (mode_needs_gp_reg(mode)) {
234                 /* all integer operations are on 32bit registers now */
235                 mode = mode_Iu;
236                 req  = amd64_reg_classes[CLASS_amd64_gp].class_req;
237         } else {
238                 req = arch_no_register_req;
239         }
240
241         /* phi nodes allow loops, so we use the old arguments for now
242          * and fix this later */
243         phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node),
244                           get_irn_in(node) + 1);
245         copy_node_attr(irg, node, phi);
246         be_duplicate_deps(node, phi);
247
248         arch_set_out_register_req(phi, 0, req);
249
250         be_enqueue_preds(node);
251
252         return phi;
253 }
254
255
256
257 /**
258  * Transforms a Conv node.
259  *
260  * @return The created ia32 Conv node
261  */
262 static ir_node *gen_Conv(ir_node *node)
263 {
264         ir_node  *block    = be_transform_node(get_nodes_block(node));
265         ir_node  *op       = get_Conv_op(node);
266         ir_node  *new_op   = be_transform_node(op);
267         ir_mode  *src_mode = get_irn_mode(op);
268         ir_mode  *dst_mode = get_irn_mode(node);
269         dbg_info *dbgi     = get_irn_dbg_info(node);
270
271         if (src_mode == dst_mode)
272                 return new_op;
273
274         if (mode_is_float(src_mode) || mode_is_float(dst_mode)) {
275                 panic("float not supported yet");
276         } else { /* complete in gp registers */
277                 int src_bits = get_mode_size_bits(src_mode);
278                 int dst_bits = get_mode_size_bits(dst_mode);
279                 int min_bits;
280                 ir_mode *min_mode;
281
282                 if (src_bits == dst_bits) {
283                         /* kill unneccessary conv */
284                         return new_op;
285                 }
286
287                 if (src_bits < dst_bits) {
288                         min_bits = src_bits;
289                         min_mode = src_mode;
290                 } else {
291                         min_bits = dst_bits;
292                         min_mode = dst_mode;
293                 }
294
295                 return new_bd_amd64_Conv(dbgi, block, new_op, min_mode);
296
297                 //if (upper_bits_clean(new_op, min_mode)) {
298                 //      return new_op;
299                 //}
300
301                 //if (mode_is_signed(min_mode)) {
302                 //      return gen_sign_extension(dbg, block, new_op, min_bits);
303                 //} else {
304                 //      return gen_zero_extension(dbg, block, new_op, min_bits);
305                 //}
306         }
307 }
308
309 /* Boilerplate code for transformation: */
310
311 static void amd64_pretransform_node(void)
312 {
313         amd64_code_gen_t *cg = env_cg;
314         (void) cg;
315
316 //      nomem = get_irg_no_mem(current_ir_graph);
317 }
318
319 static void set_transformer(ir_op *op, be_transform_func amd64_transform_func)
320 {
321         op->ops.generic = (op_func)amd64_transform_func;
322 }
323
324 static void amd64_register_transformers(void)
325 {
326         clear_irp_opcodes_generic_func();
327
328         set_transformer(op_Const,        gen_Const);
329         set_transformer(op_SymConst,     gen_SymConst);
330         set_transformer(op_Add,          gen_Add);
331         set_transformer(op_be_Call,      gen_be_Call);
332         set_transformer(op_Conv,         gen_Conv);
333         set_transformer(op_Jmp,          gen_Jmp);
334         set_transformer(op_Phi,          gen_Phi);
335 }
336
337
338 void amd64_transform_graph(amd64_code_gen_t *cg)
339 {
340         amd64_register_transformers();
341         env_cg = cg;
342         be_transform_graph(cg->irg, amd64_pretransform_node);
343 }
344
345 void amd64_init_transform(void)
346 {
347         FIRM_DBG_REGISTER(dbg, "firm.be.amd64.transform");
348 }