becopyheur2: Use rbitset_copy_to_bitset().
[libfirm] / ir / be / amd64 / amd64_transform.c
1 /*
2  * This file is part of libFirm.
3  * Copyright (C) 2012 University of Karlsruhe.
4  */
5
6 /**
7  * @file
8  * @brief   code selection (transform FIRM into amd64 FIRM)
9  */
10 #include "config.h"
11
12 #include "irnode_t.h"
13 #include "irgraph_t.h"
14 #include "irmode_t.h"
15 #include "irgmod.h"
16 #include "iredges.h"
17 #include "ircons.h"
18 #include "iropt_t.h"
19 #include "error.h"
20 #include "debug.h"
21
22 #include "benode.h"
23 #include "betranshlp.h"
24 #include "beutil.h"
25 #include "bearch_amd64_t.h"
26
27 #include "amd64_nodes_attr.h"
28 #include "amd64_transform.h"
29 #include "amd64_new_nodes.h"
30
31 #include "gen_amd64_regalloc_if.h"
32
33 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
34
35 /* Some support functions: */
36
37 static inline int mode_needs_gp_reg(ir_mode *mode)
38 {
39         return mode_is_int(mode) || mode_is_reference(mode);
40 }
41
42 /**
43  * Create a DAG constructing a given Const.
44  *
45  * @param irn  a Firm const
46  */
47 static ir_node *create_const_graph(ir_node *irn, ir_node *block)
48 {
49         ir_tarval *tv   = get_Const_tarval(irn);
50         ir_mode   *mode = get_tarval_mode(tv);
51         dbg_info  *dbgi = get_irn_dbg_info(irn);
52         unsigned   value;
53
54         if (mode_is_reference(mode)) {
55                 /* AMD64 is 64bit, so we can safely convert a reference tarval into Iu */
56                 assert(get_mode_size_bits(mode) == get_mode_size_bits(mode_Lu));
57                 tv = tarval_convert_to(tv, mode_Lu);
58         }
59
60         value = get_tarval_long(tv);
61
62         return new_bd_amd64_Immediate(dbgi, block, value);
63 }
64
65 /* Op transformers: */
66
67 /**
68  * Transforms a Const node.
69  *
70  * @return The transformed AMD64 node.
71  */
72 static ir_node *gen_Const(ir_node *node) {
73         ir_node  *block = be_transform_node(get_nodes_block(node));
74         ir_mode  *mode  = get_irn_mode(node);
75         ir_node *res = create_const_graph(node, block);
76         (void) mode;
77
78         return res;
79 }
80
81 /**
82  * Transforms a SymConst node.
83  *
84  * @return The transformed ARM node.
85  */
86 static ir_node *gen_SymConst(ir_node *node)
87 {
88         ir_node   *block  = be_transform_node(get_nodes_block(node));
89         ir_entity *entity = get_SymConst_entity(node);
90         dbg_info  *dbgi   = get_irn_dbg_info(node);
91         ir_node   *new_node;
92
93         new_node = new_bd_amd64_SymConst(dbgi, block, entity);
94         return new_node;
95 }
96
97 /**
98  * Transforms an Add node.
99  *
100  * @return The transformed AMD64 node.
101  */
102 static ir_node *gen_Add(ir_node *node) {
103         ir_node  *block = be_transform_node(get_nodes_block(node));
104         ir_node  *op1   = get_Add_left(node);
105         ir_node  *op2   = get_Add_right(node);
106         dbg_info *dbgi  = get_irn_dbg_info(node);
107         ir_node  *new_op1 = be_transform_node(op1);
108         ir_node  *new_op2 = be_transform_node(op2);
109
110         ir_node *res = new_bd_amd64_Add(dbgi, block, new_op1, new_op2);
111         return res;
112 }
113
114 /**
115  * Transforms an Sub node.
116  *
117  * @return The transformed AMD64 node.
118  */
119 static ir_node *gen_Sub(ir_node *node) {
120         ir_node  *block = be_transform_node(get_nodes_block(node));
121         ir_node  *op1   = get_Sub_left(node);
122         ir_node  *op2   = get_Sub_right(node);
123         dbg_info *dbgi  = get_irn_dbg_info(node);
124         ir_node  *new_op1 = be_transform_node(op1);
125         ir_node  *new_op2 = be_transform_node(op2);
126
127         ir_node *res = new_bd_amd64_Sub(dbgi, block, new_op1, new_op2);
128         return res;
129 }
130
131 static ir_node *gen_Mul(ir_node *node) {
132         ir_node  *block = be_transform_node(get_nodes_block(node));
133         ir_node  *op1   = get_Mul_left(node);
134         ir_node  *op2   = get_Mul_right(node);
135         dbg_info *dbgi  = get_irn_dbg_info(node);
136         ir_node  *new_op1 = be_transform_node(op1);
137         ir_node  *new_op2 = be_transform_node(op2);
138
139         ir_node *res = new_bd_amd64_Mul(dbgi, block, new_op1, new_op2);
140         return res;
141 }
142
143 static ir_node *gen_Minus(ir_node *node)
144 {
145         ir_node  *block    = be_transform_node(get_nodes_block(node));
146         ir_node  *val      = be_transform_node(get_Minus_op(node));
147         dbg_info *dbgi     = get_irn_dbg_info(node);
148
149         return new_bd_amd64_Neg(dbgi, block, val);
150 }
151
152 static ir_node *gen_Jmp(ir_node *node)
153 {
154         ir_node  *block     = get_nodes_block(node);
155         ir_node  *new_block = be_transform_node(block);
156         dbg_info *dbgi      = get_irn_dbg_info(node);
157
158         return new_bd_amd64_Jmp(dbgi, new_block);
159 }
160
161 static ir_node *gen_be_Call(ir_node *node)
162 {
163         ir_node *res = be_duplicate_node(node);
164         arch_add_irn_flags(res, arch_irn_flags_modify_flags);
165
166         return res;
167 }
168
169 static ir_node *gen_Cmp(ir_node *node)
170 {
171         ir_node  *block    = be_transform_node(get_nodes_block(node));
172         ir_node  *op1      = get_Cmp_left(node);
173         ir_node  *op2      = get_Cmp_right(node);
174         ir_mode  *cmp_mode = get_irn_mode(op1);
175         dbg_info *dbgi     = get_irn_dbg_info(node);
176         ir_node  *new_op1;
177         ir_node  *new_op2;
178         bool      is_unsigned;
179
180         if (mode_is_float(cmp_mode)) {
181                 panic("Floating point not implemented yet!");
182         }
183
184         assert(get_irn_mode(op2) == cmp_mode);
185         is_unsigned = !mode_is_signed(cmp_mode);
186
187         new_op1 = be_transform_node(op1);
188         /* new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode); */
189         new_op2 = be_transform_node(op2);
190         /* new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode); */
191         return new_bd_amd64_Cmp(dbgi, block, new_op1, new_op2, false,
192                                 is_unsigned);
193 }
194
195 /**
196  * Transforms a Cond.
197  *
198  * @return the created ARM Cond node
199  */
200 static ir_node *gen_Cond(ir_node *node)
201 {
202         ir_node    *const block     = be_transform_node(get_nodes_block(node));
203         dbg_info   *const dbgi      = get_irn_dbg_info(node);
204         ir_node    *const selector  = get_Cond_selector(node);
205         ir_node    *const flag_node = be_transform_node(selector);
206         ir_relation const relation  = get_Cmp_relation(selector);
207         return new_bd_amd64_Jcc(dbgi, block, flag_node, relation);
208 }
209
210 static ir_node *gen_Phi(ir_node *node)
211 {
212         ir_mode                   *mode = get_irn_mode(node);
213         const arch_register_req_t *req;
214         if (mode_needs_gp_reg(mode)) {
215                 /* all integer operations are on 64bit registers now */
216                 mode = mode_Lu;
217                 req  = amd64_reg_classes[CLASS_amd64_gp].class_req;
218         } else {
219                 req = arch_no_register_req;
220         }
221
222         return be_transform_phi(node, req);
223 }
224
225 /**
226  * Transforms a Conv node.
227  *
228  * @return The created ia32 Conv node
229  */
230 static ir_node *gen_Conv(ir_node *node)
231 {
232         ir_node  *block    = be_transform_node(get_nodes_block(node));
233         ir_node  *op       = get_Conv_op(node);
234         ir_node  *new_op   = be_transform_node(op);
235         ir_mode  *src_mode = get_irn_mode(op);
236         ir_mode  *dst_mode = get_irn_mode(node);
237         dbg_info *dbgi     = get_irn_dbg_info(node);
238
239         if (src_mode == dst_mode)
240                 return new_op;
241
242         if (mode_is_float(src_mode) || mode_is_float(dst_mode)) {
243                 panic("float not supported yet");
244         } else { /* complete in gp registers */
245                 int src_bits = get_mode_size_bits(src_mode);
246                 int dst_bits = get_mode_size_bits(dst_mode);
247                 ir_mode *min_mode;
248
249                 if (src_bits == dst_bits) {
250                         /* kill unnecessary conv */
251                         return new_op;
252                 }
253
254                 if (src_bits < dst_bits) {
255                         min_mode = src_mode;
256                 } else {
257                         min_mode = dst_mode;
258                 }
259
260
261                 return new_bd_amd64_Conv(dbgi, block, new_op, min_mode);
262         }
263 }
264
265 /**
266  * Transforms a Store.
267  *
268  * @return the created AMD64 Store node
269  */
270 static ir_node *gen_Store(ir_node *node)
271 {
272         ir_node  *block    = be_transform_node(get_nodes_block(node));
273         ir_node  *ptr      = get_Store_ptr(node);
274         ir_node  *new_ptr  = be_transform_node(ptr);
275         ir_node  *mem      = get_Store_mem(node);
276         ir_node  *new_mem  = be_transform_node(mem);
277         ir_node  *val      = get_Store_value(node);
278         ir_node  *new_val  = be_transform_node(val);
279         ir_mode  *mode     = get_irn_mode(val);
280         dbg_info *dbgi     = get_irn_dbg_info(node);
281         ir_node *new_store = NULL;
282
283         if (mode_is_float(mode)) {
284                 panic("Float not supported yet");
285         } else {
286                 assert(mode_is_data(mode) && "unsupported mode for Store");
287                 new_store = new_bd_amd64_Store(dbgi, block, new_ptr, new_val, new_mem, 0);
288         }
289         set_irn_pinned(new_store, get_irn_pinned(node));
290         return new_store;
291 }
292
293 /**
294  * Transforms a Load.
295  *
296  * @return the created AMD64 Load node
297  */
298 static ir_node *gen_Load(ir_node *node)
299 {
300         ir_node  *block    = be_transform_node(get_nodes_block(node));
301         ir_node  *ptr      = get_Load_ptr(node);
302         ir_node  *new_ptr  = be_transform_node(ptr);
303         ir_node  *mem      = get_Load_mem(node);
304         ir_node  *new_mem  = be_transform_node(mem);
305         ir_mode  *mode     = get_Load_mode(node);
306         dbg_info *dbgi     = get_irn_dbg_info(node);
307         ir_node  *new_load = NULL;
308
309         if (mode_is_float(mode)) {
310                 panic("Float not supported yet");
311         } else {
312                 assert(mode_is_data(mode) && "unsupported mode for Load");
313                 new_load = new_bd_amd64_Load(dbgi, block, new_ptr, new_mem, 0);
314         }
315         set_irn_pinned(new_load, get_irn_pinned(node));
316
317         return new_load;
318 }
319
320 /**
321  * Transform a Proj from a Load.
322  */
323 static ir_node *gen_Proj_Load(ir_node *node)
324 {
325         ir_node  *load     = get_Proj_pred(node);
326         ir_node  *new_load = be_transform_node(load);
327         dbg_info *dbgi     = get_irn_dbg_info(node);
328         long     proj      = get_Proj_proj(node);
329
330         /* renumber the proj */
331         switch (get_amd64_irn_opcode(new_load)) {
332                 case iro_amd64_Load:
333                         /* handle all gp loads equal: they have the same proj numbers. */
334                         if (proj == pn_Load_res) {
335                                 return new_rd_Proj(dbgi, new_load, mode_Lu, pn_amd64_Load_res);
336                         } else if (proj == pn_Load_M) {
337                                 return new_rd_Proj(dbgi, new_load, mode_M, pn_amd64_Load_M);
338                         }
339                 break;
340                 default:
341                         panic("Unsupported Proj from Load");
342         }
343
344     return be_duplicate_node(node);
345 }
346
347 /**
348  * Transform a Proj node.
349  */
350 static ir_node *gen_Proj(ir_node *node)
351 {
352         dbg_info *dbgi = get_irn_dbg_info(node);
353         ir_node  *pred = get_Proj_pred(node);
354         long     proj  = get_Proj_proj(node);
355
356     (void) dbgi;
357
358         if (is_Store(pred)) {
359                 if (proj == pn_Store_M) {
360                         return be_transform_node(pred);
361                 } else {
362                         panic("Unsupported Proj from Store");
363                 }
364         } else if (is_Load(pred)) {
365                 return gen_Proj_Load(node);
366         } else if (is_Start(pred)) {
367         }
368
369     return be_duplicate_node(node);
370 }
371
372 /**
373  * Transforms a FrameAddr into an AMD64 Add.
374  */
375 static ir_node *gen_be_FrameAddr(ir_node *node)
376 {
377         ir_node   *block  = be_transform_node(get_nodes_block(node));
378         ir_entity *ent    = be_get_frame_entity(node);
379         ir_node   *fp     = be_get_FrameAddr_frame(node);
380         ir_node   *new_fp = be_transform_node(fp);
381         dbg_info  *dbgi   = get_irn_dbg_info(node);
382         ir_node   *new_node;
383
384         new_node = new_bd_amd64_FrameAddr(dbgi, block, new_fp, ent);
385         return new_node;
386 }
387
388 /* Boilerplate code for transformation: */
389
390 static void amd64_register_transformers(void)
391 {
392         be_start_transform_setup();
393
394         be_set_transform_function(op_Const,        gen_Const);
395         be_set_transform_function(op_SymConst,     gen_SymConst);
396         be_set_transform_function(op_Add,          gen_Add);
397         be_set_transform_function(op_Sub,          gen_Sub);
398         be_set_transform_function(op_Mul,          gen_Mul);
399         be_set_transform_function(op_be_Call,      gen_be_Call);
400         be_set_transform_function(op_be_FrameAddr, gen_be_FrameAddr);
401         be_set_transform_function(op_Conv,         gen_Conv);
402         be_set_transform_function(op_Jmp,          gen_Jmp);
403         be_set_transform_function(op_Cmp,          gen_Cmp);
404         be_set_transform_function(op_Cond,         gen_Cond);
405         be_set_transform_function(op_Phi,          gen_Phi);
406         be_set_transform_function(op_Load,         gen_Load);
407         be_set_transform_function(op_Store,        gen_Store);
408         be_set_transform_function(op_Proj,         gen_Proj);
409         be_set_transform_function(op_Minus,        gen_Minus);
410 }
411
412 void amd64_transform_graph(ir_graph *irg)
413 {
414         amd64_register_transformers();
415         be_transform_graph(irg, NULL);
416 }
417
418 void amd64_init_transform(void)
419 {
420         FIRM_DBG_REGISTER(dbg, "firm.be.amd64.transform");
421 }