remove license stuff from files
[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
88         if (ops->perform_memory_operand) {
89                 ops->perform_memory_operand(irn, spill, i);
90         } else {
91                 return;
92         }
93 }
94
95 int arch_get_op_estimated_cost(const ir_node *irn)
96 {
97         const arch_irn_ops_t *ops = get_irn_ops(irn);
98
99         if (ops->get_op_estimated_cost) {
100                 return ops->get_op_estimated_cost(irn);
101         } else {
102                 return 1;
103         }
104 }
105
106 static reg_out_info_t *get_out_info_n(const ir_node *node, unsigned pos)
107 {
108         const backend_info_t *info = be_get_info(node);
109         assert(pos < (unsigned)ARR_LEN(info->out_infos));
110         return &info->out_infos[pos];
111 }
112
113
114 const arch_register_t *arch_get_irn_register(const ir_node *node)
115 {
116         const reg_out_info_t *out = get_out_info(node);
117         return out->reg;
118 }
119
120 const arch_register_t *arch_get_irn_register_out(const ir_node *node,
121                                                  unsigned pos)
122 {
123         const reg_out_info_t *out = get_out_info_n(node, pos);
124         return out->reg;
125 }
126
127 const arch_register_t *arch_get_irn_register_in(const ir_node *node, int pos)
128 {
129         ir_node *op = get_irn_n(node, pos);
130         return arch_get_irn_register(op);
131 }
132
133 void arch_set_irn_register_out(ir_node *node, unsigned pos,
134                                const arch_register_t *reg)
135 {
136         reg_out_info_t *out = get_out_info_n(node, pos);
137         out->reg            = reg;
138 }
139
140 void arch_set_irn_register(ir_node *node, const arch_register_t *reg)
141 {
142         reg_out_info_t *out = get_out_info(node);
143         out->reg = reg;
144 }
145
146 void arch_set_irn_flags(ir_node *node, arch_irn_flags_t flags)
147 {
148         backend_info_t *const info = be_get_info(node);
149         info->flags = flags;
150 }
151
152 void arch_add_irn_flags(ir_node *node, arch_irn_flags_t flags)
153 {
154         backend_info_t *const info = be_get_info(node);
155         info->flags |= flags;
156 }
157
158 bool arch_reg_is_allocatable(const arch_register_req_t *req,
159                              const arch_register_t *reg)
160 {
161         assert(req->type != arch_register_req_type_none);
162         if (req->cls != reg->reg_class)
163                 return false;
164         if (reg->type & arch_register_type_virtual)
165                 return true;
166         if (arch_register_req_is(req, limited))
167                 return rbitset_is_set(req->limited, reg->index);
168         return true;
169 }
170
171 /**
172  * Print information about a register requirement in human readable form
173  * @param F   output stream/file
174  * @param req The requirements structure to format.
175  */
176 static void arch_dump_register_req(FILE *F, const arch_register_req_t *req,
177                             const ir_node *node)
178 {
179         if (req == NULL || req->type == arch_register_req_type_none) {
180                 fprintf(F, "n/a");
181                 return;
182         }
183
184         fprintf(F, "%s", req->cls->name);
185
186         if (arch_register_req_is(req, limited)) {
187                 unsigned n_regs = req->cls->n_regs;
188                 unsigned i;
189
190                 fprintf(F, " limited to");
191                 for (i = 0; i < n_regs; ++i) {
192                         if (rbitset_is_set(req->limited, i)) {
193                                 const arch_register_t *reg = &req->cls->regs[i];
194                                 fprintf(F, " %s", reg->name);
195                         }
196                 }
197         }
198
199         if (arch_register_req_is(req, should_be_same)) {
200                 const unsigned other = req->other_same;
201                 int i;
202
203                 fprintf(F, " same as");
204                 for (i = 0; 1U << i <= other; ++i) {
205                         if (other & (1U << i)) {
206                                 ir_fprintf(F, " #%d (%+F)", i, get_irn_n(skip_Proj_const(node), i));
207                         }
208                 }
209         }
210
211         if (arch_register_req_is(req, must_be_different)) {
212                 const unsigned other = req->other_different;
213                 int i;
214
215                 fprintf(F, " different from");
216                 for (i = 0; 1U << i <= other; ++i) {
217                         if (other & (1U << i)) {
218                                 ir_fprintf(F, " #%d (%+F)", i, get_irn_n(skip_Proj_const(node), i));
219                         }
220                 }
221         }
222
223         if (req->width != 1) {
224                 fprintf(F, " width:%d", req->width);
225         }
226         if (arch_register_req_is(req, aligned)) {
227                 fprintf(F, " aligned");
228         }
229         if (arch_register_req_is(req, ignore)) {
230                 fprintf(F, " ignore");
231         }
232         if (arch_register_req_is(req, produces_sp)) {
233                 fprintf(F, " produces_sp");
234         }
235 }
236
237 void arch_dump_reqs_and_registers(FILE *F, const ir_node *node)
238 {
239         backend_info_t *const info  = be_get_info(node);
240         int             const n_ins = get_irn_arity(node);
241         /* don't fail on invalid graphs */
242         if (!info || (!info->in_reqs && n_ins != 0) || !info->out_infos) {
243                 fprintf(F, "invalid register requirements!!!\n");
244                 return;
245         }
246
247         for (int i = 0; i < n_ins; ++i) {
248                 const arch_register_req_t *req = arch_get_irn_register_req_in(node, i);
249                 fprintf(F, "inreq #%d = ", i);
250                 arch_dump_register_req(F, req, node);
251                 fputs("\n", F);
252         }
253         be_foreach_out(node, o) {
254                 const arch_register_req_t *req = arch_get_irn_register_req_out(node, o);
255                 fprintf(F, "outreq #%u = ", o);
256                 arch_dump_register_req(F, req, node);
257                 const arch_register_t *reg = arch_get_irn_register_out(node, o);
258                 fprintf(F, " [%s]\n", reg != NULL ? reg->name : "n/a");
259         }
260
261         fprintf(F, "flags =");
262         arch_irn_flags_t flags = arch_get_irn_flags(node);
263         if (flags == arch_irn_flags_none) {
264                 fprintf(F, " none");
265         } else {
266                 if (flags & arch_irn_flags_dont_spill) {
267                         fprintf(F, " unspillable");
268                 }
269                 if (flags & arch_irn_flags_rematerializable) {
270                         fprintf(F, " remat");
271                 }
272                 if (flags & arch_irn_flags_modify_flags) {
273                         fprintf(F, " modify_flags");
274                 }
275                 if (flags & arch_irn_flags_simple_jump) {
276                         fprintf(F, " simple_jump");
277                 }
278                 if (flags & arch_irn_flags_not_scheduled) {
279                         fprintf(F, " not_scheduled");
280                 }
281         }
282         fprintf(F, " (0x%x)\n", (unsigned)flags);
283 }