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