get_Call_n_params: use int for consistency
[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  */
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 "error.h"
34 #include "debug.h"
35
36 #include "benode.h"
37 #include "betranshlp.h"
38 #include "beutil.h"
39 #include "bearch_amd64_t.h"
40
41 #include "amd64_nodes_attr.h"
42 #include "amd64_transform.h"
43 #include "amd64_new_nodes.h"
44
45 #include "gen_amd64_regalloc_if.h"
46
47 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
48
49 /* Some support functions: */
50
51 static inline int mode_needs_gp_reg(ir_mode *mode)
52 {
53         return mode_is_int(mode) || mode_is_reference(mode);
54 }
55
56 /**
57  * Create a DAG constructing a given Const.
58  *
59  * @param irn  a Firm const
60  */
61 static ir_node *create_const_graph(ir_node *irn, ir_node *block)
62 {
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);
66         unsigned   value;
67
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);
72         }
73
74         value = get_tarval_long(tv);
75         //d// printf ("TEST GENERATE %d\n", value);
76
77         return new_bd_amd64_Immediate(dbgi, block, value);
78 }
79
80 /* Op transformers: */
81
82 /**
83  * Transforms a Const node.
84  *
85  * @return The transformed AMD64 node.
86  */
87 static ir_node *gen_Const(ir_node *node) {
88         ir_node  *block = be_transform_node(get_nodes_block(node));
89         ir_mode  *mode  = get_irn_mode(node);
90         ir_node *res = create_const_graph(node, block);
91         (void) mode;
92
93         return res;
94 }
95
96 /**
97  * Transforms a SymConst node.
98  *
99  * @return The transformed ARM node.
100  */
101 static ir_node *gen_SymConst(ir_node *node)
102 {
103         ir_node   *block  = be_transform_node(get_nodes_block(node));
104         ir_entity *entity = get_SymConst_entity(node);
105         dbg_info  *dbgi   = get_irn_dbg_info(node);
106         ir_node   *new_node;
107
108         new_node = new_bd_amd64_SymConst(dbgi, block, entity);
109         return new_node;
110 }
111
112 /**
113  * Transforms an Add node.
114  *
115  * @return The transformed AMD64 node.
116  */
117 static ir_node *gen_Add(ir_node *node) {
118         ir_node  *block = be_transform_node(get_nodes_block(node));
119         /* ir_mode  *mode  = get_irn_mode(node); */
120         ir_node  *op1   = get_Add_left(node);
121         ir_node  *op2   = get_Add_right(node);
122         dbg_info *dbgi  = get_irn_dbg_info(node);
123         ir_node  *new_op1 = be_transform_node(op1);
124         ir_node  *new_op2 = be_transform_node(op2);
125
126         ir_node *res = new_bd_amd64_Add(dbgi, block, new_op1, new_op2);
127         return res;
128 }
129
130 /**
131  * Transforms an Sub node.
132  *
133  * @return The transformed AMD64 node.
134  */
135 static ir_node *gen_Sub(ir_node *node) {
136         ir_node  *block = be_transform_node(get_nodes_block(node));
137         /* ir_mode  *mode  = get_irn_mode(node); */
138         ir_node  *op1   = get_Sub_left(node);
139         ir_node  *op2   = get_Sub_right(node);
140         dbg_info *dbgi  = get_irn_dbg_info(node);
141         ir_node  *new_op1 = be_transform_node(op1);
142         ir_node  *new_op2 = be_transform_node(op2);
143
144         ir_node *res = new_bd_amd64_Sub(dbgi, block, new_op1, new_op2);
145         return res;
146 }
147
148 static ir_node *gen_Mul(ir_node *node) {
149         ir_node  *block = be_transform_node(get_nodes_block(node));
150         /* ir_mode  *mode  = get_irn_mode(node); */
151         ir_node  *op1   = get_Mul_left(node);
152         ir_node  *op2   = get_Mul_right(node);
153         dbg_info *dbgi  = get_irn_dbg_info(node);
154         ir_node  *new_op1 = be_transform_node(op1);
155         ir_node  *new_op2 = be_transform_node(op2);
156
157         ir_node *res = new_bd_amd64_Mul(dbgi, block, new_op1, new_op2);
158         return res;
159 }
160
161 static ir_node *gen_Minus(ir_node *node)
162 {
163         ir_node  *block    = be_transform_node(get_nodes_block(node));
164         ir_node  *val      = be_transform_node(get_Minus_op(node));
165         dbg_info *dbgi     = get_irn_dbg_info(node);
166
167         return new_bd_amd64_Neg(dbgi, block, val);
168 }
169
170 static ir_node *gen_Jmp(ir_node *node)
171 {
172         ir_node  *block     = get_nodes_block(node);
173         ir_node  *new_block = be_transform_node(block);
174         dbg_info *dbgi      = get_irn_dbg_info(node);
175
176         return new_bd_amd64_Jmp(dbgi, new_block);
177 }
178
179 static ir_node *gen_be_Call(ir_node *node)
180 {
181         ir_node *res = be_duplicate_node(node);
182         arch_add_irn_flags(res, arch_irn_flags_modify_flags);
183
184         return res;
185 }
186
187 static ir_node *gen_Cmp(ir_node *node)
188 {
189         ir_node  *block    = be_transform_node(get_nodes_block(node));
190         ir_node  *op1      = get_Cmp_left(node);
191         ir_node  *op2      = get_Cmp_right(node);
192         ir_mode  *cmp_mode = get_irn_mode(op1);
193         dbg_info *dbgi     = get_irn_dbg_info(node);
194         ir_node  *new_op1;
195         ir_node  *new_op2;
196         bool      is_unsigned;
197
198         if (mode_is_float(cmp_mode)) {
199                 panic("Floating point not implemented yet!");
200         }
201
202         assert(get_irn_mode(op2) == cmp_mode);
203         is_unsigned = !mode_is_signed(cmp_mode);
204
205         new_op1 = be_transform_node(op1);
206         /* new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode); */
207         new_op2 = be_transform_node(op2);
208         /* new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode); */
209         return new_bd_amd64_Cmp(dbgi, block, new_op1, new_op2, false,
210                                 is_unsigned);
211 }
212
213 /**
214  * Transforms a Cond.
215  *
216  * @return the created ARM Cond node
217  */
218 static ir_node *gen_Cond(ir_node *node)
219 {
220         ir_node    *selector = get_Cond_selector(node);
221         ir_mode    *mode     = get_irn_mode(selector);
222         ir_node    *block;
223         ir_node    *flag_node;
224         ir_relation relation;
225         dbg_info   *dbgi;
226
227         if (mode != mode_b) {
228                 panic ("create_Switch not implemented yet!");
229                 // return gen_SwitchJmp(node);
230         }
231         assert(is_Cmp(selector));
232
233         block     = be_transform_node(get_nodes_block(node));
234         dbgi      = get_irn_dbg_info(node);
235         flag_node = be_transform_node(selector);
236         relation  = get_Cmp_relation(selector);
237
238         return new_bd_amd64_Jcc(dbgi, block, flag_node, relation);
239 }
240
241 #if 0
242 /**
243  * Create an And that will zero out upper bits.
244  *
245  * @param dbgi     debug info
246  * @param block    the basic block
247  * @param op       the original node
248  * param src_bits  number of lower bits that will remain
249  */
250 static ir_node *gen_zero_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
251                                    int src_bits)
252 {
253         if (src_bits == 8) {
254                 return new_bd_arm_And_imm(dbgi, block, op, 0xFF, 0);
255         } else if (src_bits == 16) {
256                 ir_node *lshift = new_bd_arm_Mov_reg_shift_imm(dbgi, block, op, ARM_SHF_LSL_IMM, 16);
257                 ir_node *rshift = new_bd_arm_Mov_reg_shift_imm(dbgi, block, lshift, ARM_SHF_LSR_IMM, 16);
258                 return rshift;
259         } else {
260                 panic("zero extension only supported for 8 and 16 bits");
261         }
262 }
263
264 /**
265  * Generate code for a sign extension.
266  */
267 static ir_node *gen_sign_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
268                                    int src_bits)
269 {
270         int shift_width = 32 - src_bits;
271         ir_node *lshift_node = new_bd_arm_Mov_reg_shift_imm(dbgi, block, op, ARM_SHF_LSL_IMM, shift_width);
272         ir_node *rshift_node = new_bd_arm_Mov_reg_shift_imm(dbgi, block, lshift_node, ARM_SHF_ASR_IMM, shift_width);
273         return rshift_node;
274 }
275
276 static ir_node *gen_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
277                               ir_mode *orig_mode)
278 {
279         int bits = get_mode_size_bits(orig_mode);
280         if (bits == 32)
281                 return op;
282
283         if (mode_is_signed(orig_mode)) {
284                 return gen_sign_extension(dbgi, block, op, bits);
285         } else {
286                 return gen_zero_extension(dbgi, block, op, bits);
287         }
288 }
289
290 /**
291  * returns true if it is assured, that the upper bits of a node are "clean"
292  * which means for a 16 or 8 bit value, that the upper bits in the register
293  * are 0 for unsigned and a copy of the last significant bit for signed
294  * numbers.
295  */
296 static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode)
297 {
298         (void) transformed_node;
299         (void) mode;
300         /* TODO */
301         return false;
302 }
303 #endif
304
305 /**
306  * Change some phi modes
307  */
308 static ir_node *gen_Phi(ir_node *node)
309 {
310         const arch_register_req_t *req;
311         ir_node  *block = be_transform_node(get_nodes_block(node));
312         ir_graph *irg   = current_ir_graph;
313         dbg_info *dbgi  = get_irn_dbg_info(node);
314         ir_mode  *mode  = get_irn_mode(node);
315         ir_node  *phi;
316
317         if (mode_needs_gp_reg(mode)) {
318                 /* all integer operations are on 64bit registers now */
319                 mode = mode_Lu;
320                 req  = amd64_reg_classes[CLASS_amd64_gp].class_req;
321         } else {
322                 req = arch_no_register_req;
323         }
324
325         /* phi nodes allow loops, so we use the old arguments for now
326          * and fix this later */
327         phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node),
328                           get_irn_in(node) + 1);
329         copy_node_attr(irg, node, phi);
330         be_duplicate_deps(node, phi);
331
332         arch_set_irn_register_req_out(phi, 0, req);
333
334         be_enqueue_preds(node);
335
336         return phi;
337 }
338
339
340
341 /**
342  * Transforms a Conv node.
343  *
344  * @return The created ia32 Conv node
345  */
346 static ir_node *gen_Conv(ir_node *node)
347 {
348         ir_node  *block    = be_transform_node(get_nodes_block(node));
349         ir_node  *op       = get_Conv_op(node);
350         ir_node  *new_op   = be_transform_node(op);
351         ir_mode  *src_mode = get_irn_mode(op);
352         ir_mode  *dst_mode = get_irn_mode(node);
353         dbg_info *dbgi     = get_irn_dbg_info(node);
354
355         if (src_mode == dst_mode)
356                 return new_op;
357
358         if (mode_is_float(src_mode) || mode_is_float(dst_mode)) {
359                 panic("float not supported yet");
360         } else { /* complete in gp registers */
361                 int src_bits = get_mode_size_bits(src_mode);
362                 int dst_bits = get_mode_size_bits(dst_mode);
363                 ir_mode *min_mode;
364
365                 if (src_bits == dst_bits) {
366                         /* kill unnecessary conv */
367                         return new_op;
368                 }
369
370                 if (src_bits < dst_bits) {
371                         min_mode = src_mode;
372                 } else {
373                         min_mode = dst_mode;
374                 }
375
376
377                 return new_bd_amd64_Conv(dbgi, block, new_op, min_mode);
378
379 #if 0
380                 if (upper_bits_clean(new_op, min_mode)) {
381                         return new_op;
382                 }
383
384                 if (mode_is_signed(min_mode)) {
385                         return gen_sign_extension(dbg, block, new_op, min_bits);
386                 } else {
387                         return gen_zero_extension(dbg, block, new_op, min_bits);
388                 }
389 #endif
390         }
391 }
392
393 /**
394  * Transforms a Store.
395  *
396  * @return the created AMD64 Store node
397  */
398 static ir_node *gen_Store(ir_node *node)
399 {
400         ir_node  *block    = be_transform_node(get_nodes_block(node));
401         ir_node  *ptr      = get_Store_ptr(node);
402         ir_node  *new_ptr  = be_transform_node(ptr);
403         ir_node  *mem      = get_Store_mem(node);
404         ir_node  *new_mem  = be_transform_node(mem);
405         ir_node  *val      = get_Store_value(node);
406         ir_node  *new_val  = be_transform_node(val);
407         ir_mode  *mode     = get_irn_mode(val);
408         dbg_info *dbgi     = get_irn_dbg_info(node);
409         ir_node *new_store = NULL;
410
411         if (mode_is_float(mode)) {
412                 panic("Float not supported yet");
413         } else {
414                 assert(mode_is_data(mode) && "unsupported mode for Store");
415                 new_store = new_bd_amd64_Store(dbgi, block, new_ptr, new_val, new_mem, 0);
416         }
417         set_irn_pinned(new_store, get_irn_pinned(node));
418         return new_store;
419 }
420
421 /**
422  * Transforms a Load.
423  *
424  * @return the created AMD64 Load node
425  */
426 static ir_node *gen_Load(ir_node *node)
427 {
428         ir_node  *block    = be_transform_node(get_nodes_block(node));
429         ir_node  *ptr      = get_Load_ptr(node);
430         ir_node  *new_ptr  = be_transform_node(ptr);
431         ir_node  *mem      = get_Load_mem(node);
432         ir_node  *new_mem  = be_transform_node(mem);
433         ir_mode  *mode     = get_Load_mode(node);
434         dbg_info *dbgi     = get_irn_dbg_info(node);
435         ir_node  *new_load = NULL;
436
437         if (mode_is_float(mode)) {
438                 panic("Float not supported yet");
439         } else {
440                 assert(mode_is_data(mode) && "unsupported mode for Load");
441                 new_load = new_bd_amd64_Load(dbgi, block, new_ptr, new_mem, 0);
442         }
443         set_irn_pinned(new_load, get_irn_pinned(node));
444
445 #if 0
446         /* check for special case: the loaded value might not be used */
447         if (be_get_Proj_for_pn(node, pn_Load_res) == NULL) {
448                 /* add a result proj and a Keep to produce a pseudo use */
449                 ir_node *proj = new_r_Proj(new_load, mode_Iu, pn_amd64_Load_res);
450                 be_new_Keep(block, 1, &proj);
451         }
452 #endif
453
454         return new_load;
455 }
456
457 /**
458  * Transform a Proj from a Load.
459  */
460 static ir_node *gen_Proj_Load(ir_node *node)
461 {
462         ir_node  *load     = get_Proj_pred(node);
463         ir_node  *new_load = be_transform_node(load);
464         dbg_info *dbgi     = get_irn_dbg_info(node);
465         long     proj      = get_Proj_proj(node);
466
467         /* renumber the proj */
468         switch (get_amd64_irn_opcode(new_load)) {
469                 case iro_amd64_Load:
470                         /* handle all gp loads equal: they have the same proj numbers. */
471                         if (proj == pn_Load_res) {
472                                 return new_rd_Proj(dbgi, new_load, mode_Lu, pn_amd64_Load_res);
473                         } else if (proj == pn_Load_M) {
474                                 return new_rd_Proj(dbgi, new_load, mode_M, pn_amd64_Load_M);
475                         }
476                 break;
477         /*
478                 case iro_sparc_fpaLoad:
479                         panic("FP not implemented yet");
480                 break;
481         */
482                 default:
483                         panic("Unsupported Proj from Load");
484         }
485
486     return be_duplicate_node(node);
487 }
488
489 /**
490  * Transform a Proj node.
491  */
492 static ir_node *gen_Proj(ir_node *node)
493 {
494         ir_graph *irg  = current_ir_graph;
495         dbg_info *dbgi = get_irn_dbg_info(node);
496         ir_node  *pred = get_Proj_pred(node);
497         long     proj  = get_Proj_proj(node);
498
499         (void) irg;
500     (void) dbgi;
501
502         if (is_Store(pred)) {
503                 if (proj == pn_Store_M) {
504                         return be_transform_node(pred);
505                 } else {
506                         panic("Unsupported Proj from Store");
507                 }
508         } else if (is_Load(pred)) {
509                 return gen_Proj_Load(node);
510 #if 0
511         } else if (be_is_SubSP(pred)) {
512                 //panic("gen_Proj not implemented for SubSP");
513                 return gen_Proj_be_SubSP(node);
514         } else if (be_is_AddSP(pred)) {
515                 //panic("gen_Proj not implemented for AddSP");
516                 return gen_Proj_be_AddSP(node);
517         } else if (is_Cmp(pred)) {
518                 //panic("gen_Proj not implemented for Cmp");
519                 return gen_Proj_Cmp(node);
520         } else if (is_Div(pred)) {
521                 return gen_Proj_Div(node);
522 #endif
523         } else if (is_Start(pred)) {
524 #if 0
525                 if (node == get_irg_anchor(irg, anchor_tls)) {
526                         return gen_Proj_tls(node);
527                 }
528         } else {
529                 ir_node *new_pred = be_transform_node(pred);
530                 ir_mode *mode     = get_irn_mode(node);
531                 if (mode_needs_gp_reg(mode)) {
532                         ir_node *new_proj = new_r_Proj(new_pred, mode_Iu, get_Proj_proj(node));
533                         new_proj->node_nr = node->node_nr;
534                         return new_proj;
535                 }
536 #endif
537         }
538
539     return be_duplicate_node(node);
540 }
541
542 /**
543  * Transforms a FrameAddr into an AMD64 Add.
544  */
545 static ir_node *gen_be_FrameAddr(ir_node *node)
546 {
547         ir_node   *block  = be_transform_node(get_nodes_block(node));
548         ir_entity *ent    = be_get_frame_entity(node);
549         ir_node   *fp     = be_get_FrameAddr_frame(node);
550         ir_node   *new_fp = be_transform_node(fp);
551         dbg_info  *dbgi   = get_irn_dbg_info(node);
552         ir_node   *new_node;
553
554         new_node = new_bd_amd64_FrameAddr(dbgi, block, new_fp, ent);
555         return new_node;
556 }
557
558 /* Boilerplate code for transformation: */
559
560 static void amd64_register_transformers(void)
561 {
562         be_start_transform_setup();
563
564         be_set_transform_function(op_Const,        gen_Const);
565         be_set_transform_function(op_SymConst,     gen_SymConst);
566         be_set_transform_function(op_Add,          gen_Add);
567         be_set_transform_function(op_Sub,          gen_Sub);
568         be_set_transform_function(op_Mul,          gen_Mul);
569         be_set_transform_function(op_be_Call,      gen_be_Call);
570         be_set_transform_function(op_be_FrameAddr, gen_be_FrameAddr);
571         be_set_transform_function(op_Conv,         gen_Conv);
572         be_set_transform_function(op_Jmp,          gen_Jmp);
573         be_set_transform_function(op_Cmp,          gen_Cmp);
574         be_set_transform_function(op_Cond,         gen_Cond);
575         be_set_transform_function(op_Phi,          gen_Phi);
576         be_set_transform_function(op_Load,         gen_Load);
577         be_set_transform_function(op_Store,        gen_Store);
578         be_set_transform_function(op_Proj,         gen_Proj);
579         be_set_transform_function(op_Minus,        gen_Minus);
580 }
581
582 void amd64_transform_graph(ir_graph *irg)
583 {
584         amd64_register_transformers();
585         be_transform_graph(irg, NULL);
586 }
587
588 void amd64_init_transform(void)
589 {
590         FIRM_DBG_REGISTER(dbg, "firm.be.amd64.transform");
591 }