architecture dependent part of the codegen module
[libfirm] / ir / be / ia32 / transform.c
1 #include <libfirm/firm.h>
2
3 #include "../firm2arch_nodes_attr.h"
4 #include "transform.h"
5 #include "new_nodes.h"
6
7 void transform_node(ir_node *node, void *env) {
8   ir_mode *mode     = get_irn_mode(node);
9   opcode  code      = get_irn_opcode(node);
10   ir_node *op1      = NULL;
11   ir_node *op2      = NULL;
12   ir_node *asm_op   = NULL;
13   ir_node *const_op = NULL;
14   ir_node *expr_op  = NULL;
15   opcode code_op1, code_op2;
16
17   /* TODO: maybe one can transform
18            "Const -- Sub -- Exp" into "Exp -- Minus -- Add -- Const"
19            to save a register
20            but I'm not sure about side effects */
21
22 #define GEN(a)  case iro_##a: asm_op = new_ia32_##a(op1, op2, mode); break
23 #define GENI(a)  case iro_##a: asm_op = new_ia32_##a##_i(expr_op, mode); break
24
25   switch (code) {
26     /* commutative arith ops */
27     case iro_Add:
28     case iro_Mul:
29     case iro_And:
30     case iro_Or:
31     case iro_Eor:
32       op1 = get_irn_n(node, 0);
33       op2 = get_irn_n(node, 1);
34       code_op1 = get_irn_opcode(op1);
35       code_op2 = get_irn_opcode(op2);
36
37       /* determine if one operator is a Const */
38       const_op = code_op1 == iro_Const ? op1 : (code_op2 == iro_Const ? op2 : NULL);
39       expr_op  = code_op1 != iro_Const ? op1 : (code_op2 != iro_Const ? op2 : NULL);
40
41       goto gen_asm_node;
42
43     /* not commutative arith ops: only construct the immediate nodes
44        when the right operand is a Const */
45     case iro_Sub:
46     case iro_DivMod:
47     case iro_Mod:
48     case iro_Shl:
49     case iro_Shr:
50     case iro_Shrs:
51     case iro_Rot:
52       op1 = get_irn_n(node, 0);
53       op2 = get_irn_n(node, 1);
54       code_op1 = get_irn_opcode(op1);
55       code_op2 = get_irn_opcode(op2);
56
57       /* determine if the right operator is a Const */
58       const_op = code_op2 == iro_Const ? op2 : NULL;
59       expr_op  = op1;
60
61 gen_asm_node:
62       assert(code_op1 != iro_Const && code_op2 != iro_Const && "Op(Const, Const) not expected!");
63       if ((code_op1 == iro_Const) && (code_op2 == iro_Const)) {
64         printf("Ignoring %s(Const, Const)\n", get_irn_opname(node));
65         return;
66       }
67
68       if (const_op) { /* one of the operators is a Const */
69         switch (code) {
70           GENI(Add);
71           GENI(Mul);
72           GENI(And);
73           GENI(Or);
74           GENI(Eor);
75           GENI(Sub);
76 //          GENI(DivMod);
77           GENI(Mod);
78           GENI(Shl);
79           GENI(Shr);
80           GENI(Shrs);
81           GENI(Rot);
82           default:
83             /* ignore */
84             break;
85         }
86         /* make the Const an attribute */
87         asmop_attr *attr = (asmop_attr *)get_irn_generic_attr(const_op);
88         attr->tv = get_Const_tarval(const_op);
89       }
90       else { /* both operators need to be computed */
91         switch (code) {
92           GEN(Add);
93           GEN(Mul);
94           GEN(And);
95           GEN(Or);
96           GEN(Eor);
97           GEN(Sub);
98 //          GEN(DivMod);
99           GEN(Mod);
100           GEN(Shl);
101           GEN(Shr);
102           GEN(Shrs);
103           GEN(Rot);
104           default:
105             /* ignore */
106             break;
107         }
108       }
109
110       /* exchange the old firm node with the new assembler node */
111       exchange(node, asm_op);
112       break;
113     default:
114       fprintf(stderr, "Ignoring node: %s\n", get_irn_opname(node));
115       break;
116   }
117 }