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