becopyopt: Inline the thin wrapper nodes_interfere(), so we do not need to fetch...
[libfirm] / ir / be / TEMPLATE / TEMPLATE_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 TEMPLATE 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 "debug.h"
20 #include "error.h"
21
22 #include "benode.h"
23 #include "betranshlp.h"
24 #include "bearch_TEMPLATE_t.h"
25
26 #include "TEMPLATE_nodes_attr.h"
27 #include "TEMPLATE_transform.h"
28 #include "TEMPLATE_new_nodes.h"
29
30 #include "gen_TEMPLATE_regalloc_if.h"
31
32 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
33
34 typedef ir_node* (*new_binop_func)(dbg_info *dbgi, ir_node *block,
35                                    ir_node *left, ir_node *right);
36
37 static ir_mode *gp_regs_mode;
38
39 static ir_node *transform_binop(ir_node *node, new_binop_func new_func)
40 {
41         ir_node  *block     = get_nodes_block(node);
42         ir_node  *new_block = be_transform_node(block);
43         dbg_info *dbgi      = get_irn_dbg_info(node);
44         ir_node  *left      = get_binop_left(node);
45         ir_node  *new_left  = be_transform_node(left);
46         ir_node  *right     = get_binop_right(node);
47         ir_node  *new_right = be_transform_node(right);
48
49         return new_func(dbgi, new_block, new_left, new_right);
50 }
51
52 static ir_node *gen_And(ir_node *node)
53 {
54         return transform_binop(node, new_bd_TEMPLATE_And);
55 }
56
57 static ir_node *gen_Or(ir_node *node)
58 {
59         return transform_binop(node, new_bd_TEMPLATE_Or);
60 }
61
62 static ir_node *gen_Eor(ir_node *node)
63 {
64         return transform_binop(node, new_bd_TEMPLATE_Xor);
65 }
66
67 static ir_node *gen_Div(ir_node *node)
68 {
69         ir_mode *mode = get_Div_resmode(node);
70         assert(mode_is_float(mode));
71         return transform_binop(node, new_bd_TEMPLATE_fDiv);
72 }
73
74 static ir_node *gen_Shl(ir_node *node)
75 {
76         ir_mode *mode = get_irn_mode(node);
77         if (get_mode_modulo_shift(mode) != 32)
78                 panic("modulo shift!=32 not supported");
79         return transform_binop(node, new_bd_TEMPLATE_Shl);
80 }
81
82 static ir_node *gen_Shr(ir_node *node)
83 {
84         ir_mode *mode = get_irn_mode(node);
85         if (get_mode_modulo_shift(mode) != 32)
86                 panic("modulo shift!=32 not supported");
87         return transform_binop(node, new_bd_TEMPLATE_Shr);
88 }
89
90 static ir_node *gen_Add(ir_node *node)
91 {
92         ir_mode *mode = get_irn_mode(node);
93
94         if (mode_is_float(mode)) {
95                 return transform_binop(node, new_bd_TEMPLATE_fAdd);
96         }
97         return transform_binop(node, new_bd_TEMPLATE_Add);
98 }
99
100 static ir_node *gen_Sub(ir_node *node)
101 {
102         ir_mode *mode = get_irn_mode(node);
103
104         if (mode_is_float(mode)) {
105                 return transform_binop(node, new_bd_TEMPLATE_fSub);
106         }
107         return transform_binop(node, new_bd_TEMPLATE_Sub);
108 }
109
110 static ir_node *gen_Mul(ir_node *node)
111 {
112         ir_mode *mode = get_irn_mode(node);
113
114         if (mode_is_float(mode)) {
115                 return transform_binop(node, new_bd_TEMPLATE_fMul);
116         }
117         return transform_binop(node, new_bd_TEMPLATE_Mul);
118 }
119
120
121 typedef ir_node* (*new_unop_func)(dbg_info *dbgi, ir_node *block, ir_node *op);
122
123 static ir_node *transform_unop(ir_node *node, new_unop_func new_func)
124 {
125         ir_node  *block     = get_nodes_block(node);
126         ir_node  *new_block = be_transform_node(block);
127         dbg_info *dbgi      = get_irn_dbg_info(node);
128         ir_node  *op        = get_unop_op(node);
129         ir_node  *new_op    = be_transform_node(op);
130
131         return new_func(dbgi, new_block, new_op);
132 }
133
134 static ir_node *gen_Minus(ir_node *node)
135 {
136         ir_mode *mode = get_irn_mode(node);
137
138         if (mode_is_float(mode)) {
139                 return transform_unop(node, new_bd_TEMPLATE_fMinus);
140         }
141         return transform_unop(node, new_bd_TEMPLATE_Minus);
142 }
143
144 static ir_node *gen_Not(ir_node *node)
145 {
146         return transform_unop(node, new_bd_TEMPLATE_Not);
147 }
148
149 static ir_node *gen_Const(ir_node *node)
150 {
151         ir_node   *block     = get_nodes_block(node);
152         ir_node   *new_block = be_transform_node(block);
153         dbg_info  *dbgi      = get_irn_dbg_info(node);
154         ir_tarval *value     = get_Const_tarval(node);
155         ir_node   *result;
156
157         result = new_bd_TEMPLATE_Const(dbgi, new_block, value);
158
159         return result;
160 }
161
162 static ir_node *gen_Load(ir_node *node)
163 {
164         ir_node  *block     = get_nodes_block(node);
165         ir_node  *new_block = be_transform_node(block);
166         dbg_info *dbgi      = get_irn_dbg_info(node);
167         ir_node  *ptr       = get_Load_ptr(node);
168         ir_node  *new_ptr   = be_transform_node(ptr);
169         ir_node  *mem       = get_Load_mem(node);
170         ir_node  *new_mem   = be_transform_node(mem);
171         ir_mode  *mode      = get_irn_mode(node);
172
173         if (mode_is_float(mode)) {
174                 return new_bd_TEMPLATE_fLoad(dbgi, new_block, new_ptr, new_mem, mode);
175         }
176         return new_bd_TEMPLATE_Load(dbgi, new_block, new_ptr, new_mem, mode);
177 }
178
179 static ir_node *gen_Store(ir_node *node)
180 {
181         ir_node  *block     = get_nodes_block(node);
182         ir_node  *new_block = be_transform_node(block);
183         dbg_info *dbgi      = get_irn_dbg_info(node);
184         ir_node  *ptr       = get_Store_ptr(node);
185         ir_node  *new_ptr   = be_transform_node(ptr);
186         ir_node  *val       = get_Store_value(node);
187         ir_node  *new_val   = be_transform_node(val);
188         ir_node  *mem       = get_Store_mem(node);
189         ir_node  *new_mem   = be_transform_node(mem);
190         ir_mode  *mode      = get_irn_mode(node);
191
192         if (mode_is_float(mode)) {
193                 return new_bd_TEMPLATE_fStore(dbgi, new_block, new_ptr, new_val, new_mem, mode);
194         }
195         return new_bd_TEMPLATE_Store(dbgi, new_block, new_ptr, new_mem, new_val, mode);
196 }
197
198 static ir_node *gen_Jmp(ir_node *node)
199 {
200         ir_node  *block     = get_nodes_block(node);
201         ir_node  *new_block = be_transform_node(block);
202         dbg_info *dbgi      = get_irn_dbg_info(node);
203
204         return new_bd_TEMPLATE_Jmp(dbgi, new_block);
205 }
206
207 static ir_node *gen_Start(ir_node *node)
208 {
209         dbg_info *dbgi      = get_irn_dbg_info(node);
210         ir_node  *block     = get_nodes_block(node);
211         ir_node  *new_block = be_transform_node(block);
212
213         return new_bd_TEMPLATE_Start(dbgi, new_block);
214 }
215
216 static ir_node *gen_Return(ir_node *node)
217 {
218         dbg_info *dbgi      = get_irn_dbg_info(node);
219         ir_node  *block     = get_nodes_block(node);
220         ir_node  *new_block = be_transform_node(block);
221         ir_node  *mem       = get_Return_mem(node);
222         ir_node  *new_mem   = be_transform_node(mem);
223         ir_graph *irg       = get_irn_irg(node);
224         ir_node  *sp        = get_irg_frame(irg);
225
226         return new_bd_TEMPLATE_Return(dbgi, new_block, sp, new_mem);
227 }
228
229 /**
230  * returns true if mode should be stored in a general purpose register
231  */
232 static inline bool mode_needs_gp_reg(ir_mode *mode)
233 {
234         return mode_is_int(mode) || mode_is_reference(mode);
235 }
236
237 static ir_node *gen_Phi(ir_node *node)
238 {
239         ir_mode                   *mode = get_irn_mode(node);
240         const arch_register_req_t *req;
241         if (mode_needs_gp_reg(mode)) {
242                 mode = mode_Iu;
243                 req  = TEMPLATE_reg_classes[CLASS_TEMPLATE_gp].class_req;
244         } else {
245                 req = arch_no_register_req;
246         }
247
248         return be_transform_phi(node, req);
249 }
250
251 static ir_node *gen_Proj_Start(ir_node *node)
252 {
253         dbg_info *dbgi      = get_irn_dbg_info(node);
254         ir_node  *block     = get_nodes_block(node);
255         ir_node  *new_block = be_transform_node(block);
256         ir_node  *start     = get_Proj_pred(node);
257         ir_node  *new_start = be_transform_node(start);
258         long      pn        = get_Proj_proj(node);
259
260         switch ((pn_Start) pn) {
261         case pn_Start_X_initial_exec:
262                 return new_bd_TEMPLATE_Jmp(dbgi, new_block);
263         case pn_Start_M:
264                 return new_rd_Proj(dbgi, new_start, mode_M, pn_TEMPLATE_Start_M);
265         case pn_Start_T_args:
266                 return new_r_Bad(get_irn_irg(block), mode_T);
267         case pn_Start_P_frame_base:
268                 return new_rd_Proj(dbgi, new_start, gp_regs_mode, pn_TEMPLATE_Start_stack);
269         }
270         panic("unexpected Start proj %ld\n", pn);
271 }
272
273 static ir_node *gen_Proj(ir_node *node)
274 {
275         ir_node *pred = get_Proj_pred(node);
276
277         switch (get_irn_opcode(pred)) {
278         case iro_Start: return gen_Proj_Start(node);
279         default:
280                 panic("code selection can't handle Proj after %+F\n", pred);
281         }
282 }
283
284 static void TEMPLATE_register_transformers(void)
285 {
286         be_start_transform_setup();
287
288         be_set_transform_function(op_Add,    gen_Add);
289         be_set_transform_function(op_And,    gen_And);
290         be_set_transform_function(op_Const,  gen_Const);
291         be_set_transform_function(op_Div,    gen_Div);
292         be_set_transform_function(op_Eor,    gen_Eor);
293         be_set_transform_function(op_Jmp,    gen_Jmp);
294         be_set_transform_function(op_Load,   gen_Load);
295         be_set_transform_function(op_Minus,  gen_Minus);
296         be_set_transform_function(op_Mul,    gen_Mul);
297         be_set_transform_function(op_Not,    gen_Not);
298         be_set_transform_function(op_Or,     gen_Or);
299         be_set_transform_function(op_Proj,   gen_Proj);
300         be_set_transform_function(op_Phi,    gen_Phi);
301         be_set_transform_function(op_Return, gen_Return);
302         be_set_transform_function(op_Shl,    gen_Shl);
303         be_set_transform_function(op_Shr,    gen_Shr);
304         be_set_transform_function(op_Start,  gen_Start);
305         be_set_transform_function(op_Store,  gen_Store);
306         be_set_transform_function(op_Sub,    gen_Sub);
307 }
308
309 /**
310  * Transform generic IR-nodes into TEMPLATE machine instructions
311  */
312 void TEMPLATE_transform_graph(ir_graph *irg)
313 {
314         gp_regs_mode = TEMPLATE_reg_classes[CLASS_TEMPLATE_gp].mode;
315
316         TEMPLATE_register_transformers();
317         be_transform_graph(irg, NULL);
318 }
319
320 void TEMPLATE_init_transform(void)
321 {
322         FIRM_DBG_REGISTER(dbg, "firm.be.TEMPLATE.transform");
323 }