89257c4ffcf81cceb7ed31b2490bfb124cd28407
[libfirm] / ir / be / bearch.c
1 /*
2  * This file is part of libFirm.
3  * Copyright (C) 2012 University of Karlsruhe.
4  */
5
6 /**
7  * @file
8  * @brief       Processor architecture specification.
9  * @author      Sebastian Hack
10  */
11 #include "config.h"
12
13 #include <string.h>
14
15 #include "bearch.h"
16 #include "benode.h"
17 #include "beinfo.h"
18 #include "ircons_t.h"
19 #include "irnode_t.h"
20 #include "irop_t.h"
21
22 #include "bitset.h"
23 #include "pset.h"
24 #include "raw_bitset.h"
25
26 #include "irprintf.h"
27
28 arch_register_req_t const arch_no_requirement = {
29         arch_register_req_type_none,
30         NULL,
31         NULL,
32         0,
33         0,
34         0
35 };
36
37 /**
38  * Get the isa responsible for a node.
39  * @param irn The node to get the responsible isa for.
40  * @return The irn operations given by the responsible isa.
41  */
42 static const arch_irn_ops_t *get_irn_ops(const ir_node *irn)
43 {
44         if (is_Proj(irn)) {
45                 irn = get_Proj_pred(irn);
46                 assert(!is_Proj(irn));
47         }
48
49         ir_op                *ops    = get_irn_op(irn);
50         const arch_irn_ops_t *be_ops = get_op_ops(ops)->be_ops;
51
52         return be_ops;
53 }
54
55 void arch_set_frame_offset(ir_node *irn, int offset)
56 {
57         const arch_irn_ops_t *ops = get_irn_ops(irn);
58         ops->set_frame_offset(irn, offset);
59 }
60
61 ir_entity *arch_get_frame_entity(const ir_node *irn)
62 {
63         const arch_irn_ops_t *ops = get_irn_ops(irn);
64         return ops->get_frame_entity(irn);
65 }
66
67 int arch_get_sp_bias(ir_node *irn)
68 {
69         const arch_irn_ops_t *ops = get_irn_ops(irn);
70         return ops->get_sp_bias(irn);
71 }
72
73 int arch_possible_memory_operand(const ir_node *irn, unsigned int i)
74 {
75         const arch_irn_ops_t *ops = get_irn_ops(irn);
76
77         if (ops->possible_memory_operand) {
78                 return ops->possible_memory_operand(irn, i);
79         } else {
80                 return 0;
81         }
82 }
83
84 void arch_perform_memory_operand(ir_node *irn, ir_node *spill, unsigned int i)
85 {
86         const arch_irn_ops_t *ops = get_irn_ops(irn);
87         ops->perform_memory_operand(irn, spill, i);
88 }
89
90 int arch_get_op_estimated_cost(const ir_node *irn)
91 {
92         const arch_irn_ops_t *ops = get_irn_ops(irn);
93
94         if (ops->get_op_estimated_cost) {
95                 return ops->get_op_estimated_cost(irn);
96         } else {
97                 return 1;
98         }
99 }
100
101 static reg_out_info_t *get_out_info_n(const ir_node *node, unsigned pos)
102 {
103         const backend_info_t *info = be_get_info(node);
104         assert(pos < (unsigned)ARR_LEN(info->out_infos));
105         return &info->out_infos[pos];
106 }
107
108
109 const arch_register_t *arch_get_irn_register(const ir_node *node)
110 {
111         const reg_out_info_t *out = get_out_info(node);
112         return out->reg;
113 }
114
115 const arch_register_t *arch_get_irn_register_out(const ir_node *node,
116                                                  unsigned pos)
117 {
118         const reg_out_info_t *out = get_out_info_n(node, pos);
119         return out->reg;
120 }
121
122 const arch_register_t *arch_get_irn_register_in(const ir_node *node, int pos)
123 {
124         ir_node *op = get_irn_n(node, pos);
125         return arch_get_irn_register(op);
126 }
127
128 void arch_set_irn_register_out(ir_node *node, unsigned pos,
129                                const arch_register_t *reg)
130 {
131         reg_out_info_t *out = get_out_info_n(node, pos);
132         out->reg            = reg;
133 }
134
135 void arch_set_irn_register(ir_node *node, const arch_register_t *reg)
136 {
137         reg_out_info_t *out = get_out_info(node);
138         out->reg = reg;
139 }
140
141 void arch_set_irn_flags(ir_node *node, arch_irn_flags_t flags)
142 {
143         backend_info_t *const info = be_get_info(node);
144         info->flags = flags;
145 }
146
147 void arch_add_irn_flags(ir_node *node, arch_irn_flags_t flags)
148 {
149         backend_info_t *const info = be_get_info(node);
150         info->flags |= flags;
151 }
152
153 bool arch_reg_is_allocatable(const arch_register_req_t *req,
154                              const arch_register_t *reg)
155 {
156         assert(req->type != arch_register_req_type_none);
157         if (req->cls != reg->reg_class)
158                 return false;
159         if (reg->type & arch_register_type_virtual)
160                 return true;
161         if (arch_register_req_is(req, limited))
162                 return rbitset_is_set(req->limited, reg->index);
163         return true;
164 }
165
166 /**
167  * Print information about a register requirement in human readable form
168  * @param F   output stream/file
169  * @param req The requirements structure to format.
170  */
171 static void arch_dump_register_req(FILE *F, const arch_register_req_t *req,
172                             const ir_node *node)
173 {
174         if (req == NULL || req->type == arch_register_req_type_none) {
175                 fprintf(F, "n/a");
176                 return;
177         }
178
179         fprintf(F, "%s", req->cls->name);
180
181         if (arch_register_req_is(req, limited)) {
182                 unsigned n_regs = req->cls->n_regs;
183                 unsigned i;
184
185                 fprintf(F, " limited to");
186                 for (i = 0; i < n_regs; ++i) {
187                         if (rbitset_is_set(req->limited, i)) {
188                                 const arch_register_t *reg = &req->cls->regs[i];
189                                 fprintf(F, " %s", reg->name);
190                         }
191                 }
192         }
193
194         if (arch_register_req_is(req, should_be_same)) {
195                 const unsigned other = req->other_same;
196                 int i;
197
198                 fprintf(F, " same as");
199                 for (i = 0; 1U << i <= other; ++i) {
200                         if (other & (1U << i)) {
201                                 ir_fprintf(F, " #%d (%+F)", i, get_irn_n(skip_Proj_const(node), i));
202                         }
203                 }
204         }
205
206         if (arch_register_req_is(req, must_be_different)) {
207                 const unsigned other = req->other_different;
208                 int i;
209
210                 fprintf(F, " different from");
211                 for (i = 0; 1U << i <= other; ++i) {
212                         if (other & (1U << i)) {
213                                 ir_fprintf(F, " #%d (%+F)", i, get_irn_n(skip_Proj_const(node), i));
214                         }
215                 }
216         }
217
218         if (req->width != 1) {
219                 fprintf(F, " width:%d", req->width);
220         }
221         if (arch_register_req_is(req, aligned)) {
222                 fprintf(F, " aligned");
223         }
224         if (arch_register_req_is(req, ignore)) {
225                 fprintf(F, " ignore");
226         }
227         if (arch_register_req_is(req, produces_sp)) {
228                 fprintf(F, " produces_sp");
229         }
230 }
231
232 void arch_dump_reqs_and_registers(FILE *F, const ir_node *node)
233 {
234         backend_info_t *const info  = be_get_info(node);
235         int             const n_ins = get_irn_arity(node);
236         /* don't fail on invalid graphs */
237         if (!info || (!info->in_reqs && n_ins != 0) || !info->out_infos) {
238                 fprintf(F, "invalid register requirements!!!\n");
239                 return;
240         }
241
242         for (int i = 0; i < n_ins; ++i) {
243                 const arch_register_req_t *req = arch_get_irn_register_req_in(node, i);
244                 fprintf(F, "inreq #%d = ", i);
245                 arch_dump_register_req(F, req, node);
246                 fputs("\n", F);
247         }
248         be_foreach_out(node, o) {
249                 const arch_register_req_t *req = arch_get_irn_register_req_out(node, o);
250                 fprintf(F, "outreq #%u = ", o);
251                 arch_dump_register_req(F, req, node);
252                 const arch_register_t *reg = arch_get_irn_register_out(node, o);
253                 fprintf(F, " [%s]\n", reg != NULL ? reg->name : "n/a");
254         }
255
256         fprintf(F, "flags =");
257         arch_irn_flags_t flags = arch_get_irn_flags(node);
258         if (flags == arch_irn_flags_none) {
259                 fprintf(F, " none");
260         } else {
261                 if (flags & arch_irn_flags_dont_spill) {
262                         fprintf(F, " unspillable");
263                 }
264                 if (flags & arch_irn_flags_rematerializable) {
265                         fprintf(F, " remat");
266                 }
267                 if (flags & arch_irn_flags_modify_flags) {
268                         fprintf(F, " modify_flags");
269                 }
270                 if (flags & arch_irn_flags_simple_jump) {
271                         fprintf(F, " simple_jump");
272                 }
273                 if (flags & arch_irn_flags_not_scheduled) {
274                         fprintf(F, " not_scheduled");
275                 }
276         }
277         fprintf(F, " (0x%x)\n", (unsigned)flags);
278 }