Do not forcefully rebuild outedges in compute_execfreq(), but handle this at the...
[libfirm] / ir / be / TEMPLATE / TEMPLATE_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 TEMPLATE FIRM)
23  * @version $Id$
24  */
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "irnode_t.h"
30 #include "irgraph_t.h"
31 #include "irmode_t.h"
32 #include "irgmod.h"
33 #include "iredges.h"
34 #include "irvrfy.h"
35 #include "ircons.h"
36 #include "iropt_t.h"
37 #include "debug.h"
38
39 #include "../benode_t.h"
40 #include "bearch_TEMPLATE_t.h"
41
42 #include "TEMPLATE_nodes_attr.h"
43 #include "archop.h"
44 #include "TEMPLATE_transform.h"
45 #include "TEMPLATE_new_nodes.h"
46 #include "TEMPLATE_map_regs.h"
47
48 #include "gen_TEMPLATE_regalloc_if.h"
49
50 extern ir_op *get_op_Mulh(void);
51
52
53
54 /****************************************************************************************************
55  *                  _        _                        __                           _   _
56  *                 | |      | |                      / _|                         | | (_)
57  *  _ __   ___   __| | ___  | |_ _ __ __ _ _ __  ___| |_ ___  _ __ _ __ ___   __ _| |_ _  ___  _ __
58  * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __|  _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
59  * | | | | (_) | (_| |  __/ | |_| | | (_| | | | \__ \ || (_) | |  | | | | | | (_| | |_| | (_) | | | |
60  * |_| |_|\___/ \__,_|\___|  \__|_|  \__,_|_| |_|___/_| \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_|
61  *
62  ****************************************************************************************************/
63
64 /**
65  * Creates an TEMPLATE Add.
66  *
67  * @param env   The transformation environment
68  * @param op1   first operator
69  * @param op2   second operator
70  * @return the created TEMPLATE Add node
71  */
72 static ir_node *gen_Add(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
73         return new_rd_TEMPLATE_Add(env->dbg, env->irg, env->block, op1, op2, env->mode);
74 }
75
76
77
78 /**
79  * Creates an TEMPLATE Mul.
80  *
81  * @param dbg       firm node dbg
82  * @param block     the block the new node should belong to
83  * @param op1       first operator
84  * @param op2       second operator
85  * @param mode      node mode
86  * @return the created TEMPLATE Mul node
87  */
88 static ir_node *gen_Mul(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
89         if (mode_is_float(env->mode)) {
90                 return new_rd_TEMPLATE_fMul(env->dbg, env->irg, env->block, op1, op2, env->mode);
91         }
92         else {
93                 return new_rd_TEMPLATE_Mul(env->dbg, env->irg, env->block, op1, op2, env->mode);
94         }
95 }
96
97
98
99 /**
100  * Creates an TEMPLATE And.
101  *
102  * @param dbg       firm node dbg
103  * @param block     the block the new node should belong to
104  * @param op1       first operator
105  * @param op2       second operator
106  * @param mode      node mode
107  * @return the created TEMPLATE And node
108  */
109 static ir_node *gen_And(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
110         return new_rd_TEMPLATE_And(env->dbg, env->irg, env->block, op1, op2, env->mode);
111 }
112
113
114
115 /**
116  * Creates an TEMPLATE Or.
117  *
118  * @param dbg       firm node dbg
119  * @param block     the block the new node should belong to
120  * @param op1       first operator
121  * @param op2       second operator
122  * @param mode      node mode
123  * @return the created TEMPLATE Or node
124  */
125 static ir_node *gen_Or(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
126         return new_rd_TEMPLATE_Or(env->dbg, env->irg, env->block, op1, op2, env->mode);
127 }
128
129
130
131 /**
132  * Creates an TEMPLATE Eor.
133  *
134  * @param dbg       firm node dbg
135  * @param block     the block the new node should belong to
136  * @param op1       first operator
137  * @param op2       second operator
138  * @param mode      node mode
139  * @return the created TEMPLATE Eor node
140  */
141 static ir_node *gen_Eor(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
142         return new_rd_TEMPLATE_Eor(env->dbg, env->irg, env->block, op1, op2, env->mode);
143 }
144
145
146
147 /**
148  * Creates an TEMPLATE Sub.
149  *
150  * @param dbg       firm node dbg
151  * @param block     the block the new node should belong to
152  * @param op1       first operator
153  * @param op2       second operator
154  * @param mode      node mode
155  * @return the created TEMPLATE Sub node
156  */
157 static ir_node *gen_Sub(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
158         if (mode_is_float(env->mode)) {
159                 return new_rd_TEMPLATE_fSub(env->dbg, env->irg, env->block, op1, op2, env->mode);
160         }
161         else {
162                 return new_rd_TEMPLATE_Sub(env->dbg, env->irg, env->block, op1, op2, env->mode);
163         }
164 }
165
166
167
168 /**
169  * Creates an TEMPLATE floating Div.
170  *
171  * @param dbg       firm node dbg
172  * @param block     the block the new node should belong to
173  * @param op1       first operator
174  * @param op2       second operator
175  * @param mode      node mode
176  * @return the created TEMPLATE fDiv node
177  */
178 static ir_node *gen_Quot(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
179         return new_rd_TEMPLATE_fDiv(env->dbg, env->irg, env->block, op1, op2, env->mode);
180 }
181
182
183
184 /**
185  * Creates an TEMPLATE Shl.
186  *
187  * @param dbg       firm node dbg
188  * @param block     the block the new node should belong to
189  * @param op1       first operator
190  * @param op2       second operator
191  * @param mode      node mode
192  * @return the created TEMPLATE Shl node
193  */
194 static ir_node *gen_Shl(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
195         return new_rd_TEMPLATE_Shl(env->dbg, env->irg, env->block, op1, op2, env->mode);
196 }
197
198
199
200 /**
201  * Creates an TEMPLATE Shr.
202  *
203  * @param dbg       firm node dbg
204  * @param block     the block the new node should belong to
205  * @param op1       first operator
206  * @param op2       second operator
207  * @param mode      node mode
208  * @return the created TEMPLATE Shr node
209  */
210 static ir_node *gen_Shr(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
211         return new_rd_TEMPLATE_Shr(env->dbg, env->irg, env->block, op1, op2, env->mode);
212 }
213
214
215
216 /**
217  * Transforms a Minus node.
218  *
219  * @param mod     the debug module
220  * @param block   the block the new node should belong to
221  * @param node    the ir Minus node
222  * @param op      operator
223  * @param mode    node mode
224  * @return the created TEMPLATE Minus node
225  */
226 static ir_node *gen_Minus(TEMPLATE_transform_env_t *env, ir_node *op) {
227         if (mode_is_float(env->mode)) {
228                 return new_rd_TEMPLATE_fMinus(env->dbg, env->irg, env->block, op, env->mode);
229         }
230         return new_rd_TEMPLATE_Minus(env->dbg, env->irg, env->block, op, env->mode);
231 }
232
233
234
235 /**
236  * Transforms a Not node.
237  *
238  * @param mod     the debug module
239  * @param block   the block the new node should belong to
240  * @param node    the ir Not node
241  * @param op      operator
242  * @param mode    node mode
243  * @return the created TEMPLATE Not node
244  */
245 static ir_node *gen_Not(TEMPLATE_transform_env_t *env, ir_node *op) {
246         return new_rd_TEMPLATE_Not(env->dbg, env->irg, env->block, op, env->mode);
247 }
248
249
250
251 /**
252  * Transforms a Load.
253  *
254  * @param mod     the debug module
255  * @param block   the block the new node should belong to
256  * @param node    the ir Load node
257  * @param mode    node mode
258  * @return the created TEMPLATE Load node
259  */
260 static ir_node *gen_Load(TEMPLATE_transform_env_t *env) {
261         ir_node *node = env->irn;
262
263         if (mode_is_float(env->mode)) {
264                 return new_rd_TEMPLATE_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
265         }
266         return new_rd_TEMPLATE_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
267 }
268
269
270
271 /**
272  * Transforms a Store.
273  *
274  * @param mod     the debug module
275  * @param block   the block the new node should belong to
276  * @param node    the ir Store node
277  * @param mode    node mode
278  * @return the created TEMPLATE Store node
279  */
280 static ir_node *gen_Store(TEMPLATE_transform_env_t *env) {
281         ir_node *node = env->irn;
282
283         if (mode_is_float(env->mode)) {
284                 return new_rd_TEMPLATE_fStore(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
285         }
286         return new_rd_TEMPLATE_Store(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
287 }
288
289
290
291 /*********************************************************
292  *                  _             _      _
293  *                 (_)           | |    (_)
294  *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
295  * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
296  * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
297  * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
298  *
299  *********************************************************/
300
301
302
303 /**
304  * Transforms the given firm node (and maybe some other related nodes)
305  * into one or more assembler nodes.
306  *
307  * @param node    the firm node
308  * @param env     the debug module
309  */
310 void TEMPLATE_transform_node(ir_node *node, void *env) {
311 #ifdef DEBUG_libfirm
312         TEMPLATE_code_gen_t *cgenv = (TEMPLATE_code_gen_t *)env;
313 #endif
314         ir_opcode code             = get_irn_opcode(node);
315         ir_node *asm_node          = NULL;
316         TEMPLATE_transform_env_t tenv;
317         (void) env;
318
319         if (is_Block(node))
320                 return;
321
322         tenv.block    = get_nodes_block(node);
323         tenv.dbg      = get_irn_dbg_info(node);
324         tenv.irg      = current_ir_graph;
325         tenv.irn      = node;
326 #ifdef DEBUG_libfirm
327         tenv.mod      = cgenv->mod;
328 #endif
329         tenv.mode     = get_irn_mode(node);
330
331 #define UNOP(a)        case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break
332 #define BINOP(a)       case iro_##a: asm_node = gen_##a(&tenv, get_##a##_left(node), get_##a##_right(node)); break
333 #define GEN(a)         case iro_##a: asm_node = gen_##a(&tenv); break
334 #define IGN(a)         case iro_##a: break
335 #define BAD(a)         case iro_##a: goto bad
336
337         DBG((tenv.mod, LEVEL_1, "check %+F ... ", node));
338
339         switch (code) {
340                 BINOP(Add);
341                 BINOP(Mul);
342                 BINOP(And);
343                 BINOP(Or);
344                 BINOP(Eor);
345
346                 BINOP(Sub);
347                 BINOP(Shl);
348                 BINOP(Shr);
349                 BINOP(Quot);
350
351
352                 UNOP(Minus);
353                 UNOP(Not);
354
355                 GEN(Load);
356                 GEN(Store);
357
358                 /* TODO: implement these nodes */
359                 IGN(Shrs);
360                 IGN(Div);
361                 IGN(Mod);
362                 IGN(DivMod);
363                 IGN(Const);
364                 IGN(SymConst);
365                 IGN(Conv);
366                 IGN(Abs);
367                 IGN(Cond);
368                 IGN(Mux);
369                 IGN(CopyB);
370                 IGN(Unknown);
371                 IGN(Cmp);
372
373                 /* You probably don't need to handle the following nodes */
374
375                 IGN(Call);
376                 IGN(Proj);
377                 IGN(Alloc);
378
379                 IGN(Block);
380                 IGN(Start);
381                 IGN(End);
382                 IGN(NoMem);
383                 IGN(Phi);
384                 IGN(IJmp);
385                 IGN(Jmp);
386                 IGN(Break);
387                 IGN(Sync);
388
389                 BAD(Raise);
390                 BAD(Sel);
391                 BAD(InstOf);
392                 BAD(Cast);
393                 BAD(Free);
394                 BAD(Tuple);
395                 BAD(Id);
396                 BAD(Bad);
397                 BAD(Confirm);
398                 BAD(Filter);
399                 BAD(CallBegin);
400                 BAD(EndReg);
401                 BAD(EndExcept);
402
403                 default:
404                         if (get_irn_op(node) == get_op_Max() ||
405                             get_irn_op(node) == get_op_Min() ||
406                             is_Mulh(node))
407                         {
408                                 /* TODO: implement */
409                                 /* ignore for now  */
410                         }
411                         break;
412 bad:
413                 fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node));
414                 assert(0);
415         }
416
417         if (asm_node) {
418                 exchange(node, asm_node);
419                 DB((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
420         }
421         else {
422                 DB((tenv.mod, LEVEL_1, "ignored\n"));
423         }
424 }