da45d1b827c5e846583ed496855ea96fb2b2a971
[libfirm] / ir / be / ia32 / bearch_ia32.c
1 #include "pseudo_irg.h"
2 #include "irgwalk.h"
3
4 #include "bitset.h"
5 #include "debug.h"
6
7 #include "../bearch.h"                /* the general register allocator interface */
8
9 #include "ia32_new_nodes.h"           /* ia32 nodes interface */
10 #include "gen_ia32_regalloc_if.h"     /* the generated interface (register type and class defenitions) */
11 #include "ia32_gen_decls.h"           /* interface declaration emitter */
12 #include "ia32_transform.h"
13
14 /* define shorter names for classes and indicees */
15
16 #define N_GP_REGS   N_ia32_general_purpose_REGS
17 #define N_FP_REGS   N_ia32_floating_point_REGS
18 #define N_FLAG_REGS N_ia32_flag_register_REGS
19
20 #define CLS_GP   CLASS_ia32_general_purpose
21 #define CLS_FP   CLASS_ia32_floating_point
22 #define CLS_FLAG CLASS_ia32_flag_register
23
24 #define N_CLASSES (sizeof(ia32_reg_classes) / sizeof(ia32_reg_classes[0]))
25
26 extern arch_register_class_t ia32_reg_classes[3];
27
28 /* Implementation of the register allocator functions */
29
30 /**
31  * Return register requirements for an ia32 node.
32  * If the node returns a tuple (mode_T) then the proj's
33  * will be asked for this information.
34  */
35 static const arch_register_req_t *ia32_get_irn_reg_req(const arch_irn_ops_t *self, arch_register_req_t *req, const ir_node *irn, int pos) {
36   const arch_register_req_t **irn_req;
37
38   if (is_Proj(irn)) {
39   }
40   else if (is_ia32_irn(irn)) {
41     if (get_irn_mode(irn) == mode_T) {
42       return NULL;
43     }
44
45     if (pos >= 0) {
46       irn_req = get_ia32_in_req(irn);
47     }
48     else {
49       irn_req = get_ia32_out_req(irn);
50       pos     = -1 - pos;
51     }
52
53     memcpy(req, irn_req[pos], sizeof(*req));
54     return req;
55   }
56   else
57     req = NULL;
58
59   return req;
60 }
61
62 static int ia32_get_n_operands(const arch_irn_ops_t *self, const ir_node *irn, int in_out) {
63   if (in_out >= 0)
64     return get_irn_arity(irn);
65   else
66     return get_ia32_n_res(irn);
67 }
68
69 static void ia32_set_irn_reg(const arch_irn_ops_t *self, ir_node *irn, int pos, const arch_register_t *reg) {
70   if (is_ia32_irn(irn)) {
71     const arch_register_t **slots;
72
73     slots      = get_ia32_slots(irn);
74     slots[pos] = reg;
75   }
76 }
77
78 static const arch_register_t *ia32_get_irn_reg(const arch_irn_ops_t *self, const ir_node *irn, int pos) {
79   if (is_ia32_irn(irn)) {
80     const arch_register_t **slots;
81
82     slots = get_ia32_slots(irn);
83
84     return slots[pos];
85   }
86   else
87     return NULL;
88 }
89
90 static arch_irn_class_t ia32_classify(const arch_irn_ops_t *self, const ir_node *irn) {
91   if (is_ia32_irn(irn)) {
92     if (is_ia32_Cmp(irn) || is_ia32_Cmp_i(irn)) // TODO: ia32_Jmp
93       return arch_irn_class_branch;
94     else
95       return arch_irn_class_normal;
96   }
97   else
98     return 0;
99 }
100
101 static arch_irn_flags_t ia32_get_flags(const arch_irn_ops_t *self, const ir_node *irn) {
102   if (is_ia32_irn(irn))
103     return get_ia32_flags(irn);
104   else
105     return 0;
106 }
107
108 /* fill register allocator interface */
109
110 static const arch_irn_ops_t ia32_irn_ops = {
111   ia32_get_irn_reg_req,
112   ia32_get_n_operands,
113   ia32_set_irn_reg,
114   ia32_get_irn_reg,
115   ia32_classify,
116   ia32_get_flags
117 };
118
119 /* Implementation of the backend isa functions */
120
121 static void ia32_init(void) {
122   ia32_register_init();
123   ia32_create_opcodes();
124 }
125
126 static int ia32_get_n_reg_class(void) {
127   return N_CLASSES;
128 }
129
130 static const arch_register_class_t *ia32_get_reg_class(int i) {
131   assert(i >= 0 && i < N_CLASSES && "Invalid ia32 register class requested.");
132   return &ia32_reg_classes[i];
133 }
134
135 static const arch_irn_ops_t *ia32_get_irn_ops(const arch_irn_handler_t *self, const ir_node *irn) {
136   return &ia32_irn_ops;
137 }
138
139 static void ia32_prepare_graph(ir_graph *irg) {
140   firm_dbg_module_t *dbg = firm_dbg_register("be.transform.ia32");
141   if (! is_pseudo_ir_graph(irg))
142     irg_walk_blkwise_graph(irg, NULL, ia32_transform_node, dbg);
143 }
144
145 static void ia32_codegen(FILE *out) {
146   ia32_gen_decls(out);
147
148 #if 0
149   for (i = 0; i < get_irp_n_irgs(); ++i) {
150     ir_graph *irg = get_irp_irg(i);
151     if (! is_pseudo_ir_graph(irg)) {
152       ia32_finish_irg(irg);
153       ia32_gen_routine(out, irg);
154     }
155   }
156 #endif
157 }
158
159 const arch_irn_handler_t ia32_irn_handler = {
160   ia32_get_irn_ops
161 };
162
163 /* fill isa interface */
164
165 const arch_isa_if_t ia32_isa = {
166   ia32_init,
167   ia32_get_n_reg_class,
168   ia32_get_reg_class,
169   ia32_prepare_graph,
170   &ia32_irn_handler,
171   ia32_codegen
172 };