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