942857056a9041b0816f63035e25239e8502df82
[libfirm] / ir / be / TEMPLATE / TEMPLATE_new_nodes.c
1 /**
2  * This file implements the creation of the achitecture specific firm opcodes
3  * and the coresponding node constructors for the TEMPLATE assembler irg.
4  * $Id$
5  */
6 #ifdef HAVE_CONFIG_H
7 #include <config.h>
8 #endif
9
10 #ifdef _WIN32
11 #include <malloc.h>
12 #else
13 #include <alloca.h>
14 #endif
15
16 #include <stdlib.h>
17
18 #include "irprog_t.h"
19 #include "irgraph_t.h"
20 #include "irnode_t.h"
21 #include "irmode_t.h"
22 #include "ircons_t.h"
23 #include "iropt_t.h"
24 #include "irop.h"
25 #include "firm_common_t.h"
26 #include "irvrfy_t.h"
27 #include "irprintf.h"
28
29 #include "../bearch.h"
30
31 #include "TEMPLATE_nodes_attr.h"
32 #include "TEMPLATE_new_nodes.h"
33 #include "gen_TEMPLATE_regalloc_if.h"
34
35
36
37 /***********************************************************************************
38  *      _                                   _       _             __
39  *     | |                                 (_)     | |           / _|
40  *   __| |_   _ _ __ ___  _ __   ___ _ __   _ _ __ | |_ ___ _ __| |_ __ _  ___ ___
41  *  / _` | | | | '_ ` _ \| '_ \ / _ \ '__| | | '_ \| __/ _ \ '__|  _/ _` |/ __/ _ \
42  * | (_| | |_| | | | | | | |_) |  __/ |    | | | | | ||  __/ |  | || (_| | (_|  __/
43  *  \__,_|\__,_|_| |_| |_| .__/ \___|_|    |_|_| |_|\__\___|_|  |_| \__,_|\___\___|
44  *                       | |
45  *                       |_|
46  ***********************************************************************************/
47
48 /**
49  * Returns a string containing the names of all registers within the limited bitset
50  */
51 static char *get_limited_regs(const arch_register_req_t *req, char *buf, int max) {
52         bitset_t *bs   = bitset_alloca(req->cls->n_regs);
53         char     *p    = buf;
54         int       size = 0;
55         int       i, cnt;
56
57         req->limited(NULL, bs);
58
59         for (i = 0; i < req->cls->n_regs; i++) {
60                 if (bitset_is_set(bs, i)) {
61                         cnt = snprintf(p, max - size, " %s", req->cls->regs[i].name);
62                         if (cnt < 0) {
63                                 fprintf(stderr, "dumper problem, exiting\n");
64                                 exit(1);
65                         }
66
67                         p    += cnt;
68                         size += cnt;
69
70                         if (size >= max)
71                                 break;
72                 }
73         }
74
75         return buf;
76 }
77
78 /**
79  * Dumps the register requirements for either in or out.
80  */
81 static void dump_reg_req(FILE *F, ir_node *n, const TEMPLATE_register_req_t **reqs, int inout) {
82         char *dir = inout ? "out" : "in";
83         int   max = inout ? get_TEMPLATE_n_res(n) : get_irn_arity(n);
84         char *buf = alloca(1024);
85         int   i;
86
87         memset(buf, 0, 1024);
88
89         if (reqs) {
90                 for (i = 0; i < max; i++) {
91                         fprintf(F, "%sreq #%d =", dir, i);
92
93                         if (reqs[i]->req.type == arch_register_req_type_none) {
94                                 fprintf(F, " n/a");
95                         }
96
97                         if (reqs[i]->req.type & arch_register_req_type_normal) {
98                                 fprintf(F, " %s", reqs[i]->req.cls->name);
99                         }
100
101                         if (reqs[i]->req.type & arch_register_req_type_limited) {
102                                 fprintf(F, " %s", get_limited_regs(&reqs[i]->req, buf, 1024));
103                         }
104
105                         if (reqs[i]->req.type & arch_register_req_type_should_be_same) {
106                                 ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->same_pos));
107                         }
108
109                         if (reqs[i]->req.type & arch_register_req_type_should_be_different) {
110                                 ir_fprintf(F, " different from %+F", get_irn_n(n, reqs[i]->different_pos));
111                         }
112
113                         fprintf(F, "\n");
114                 }
115
116                 fprintf(F, "\n");
117         }
118         else {
119                 fprintf(F, "%sreq = N/A\n", dir);
120         }
121 }
122
123
124 /**
125  * Dumper interface for dumping TEMPLATE nodes in vcg.
126  * @param n        the node to dump
127  * @param F        the output file
128  * @param reason   indicates which kind of information should be dumped
129  * @return 0 on success or != 0 on failure
130  */
131 static int TEMPLATE_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
132         ir_mode     *mode = NULL;
133         int          bad  = 0;
134         int          i;
135         TEMPLATE_attr_t *attr;
136         const TEMPLATE_register_req_t **reqs;
137         const arch_register_t     **slots;
138
139         switch (reason) {
140                 case dump_node_opcode_txt:
141                         fprintf(F, "%s", get_irn_opname(n));
142                         break;
143
144                 case dump_node_mode_txt:
145                         mode = get_irn_mode(n);
146
147                         if (mode) {
148                                 fprintf(F, "[%s]", get_mode_name(mode));
149                         }
150                         else {
151                                 fprintf(F, "[?NOMODE?]");
152                         }
153                         break;
154
155                 case dump_node_nodeattr_txt:
156
157                         /* TODO: dump some attributes which should show up */
158                         /* in node name in dump (e.g. consts or the like)  */
159
160                         break;
161
162                 case dump_node_info_txt:
163                         attr = get_TEMPLATE_attr(n);
164                         fprintf(F, "=== TEMPLATE attr begin ===\n");
165
166                         /* dump IN requirements */
167                         if (get_irn_arity(n) > 0) {
168                                 reqs = get_TEMPLATE_in_req_all(n);
169                                 dump_reg_req(F, n, reqs, 0);
170                         }
171
172                         /* dump OUT requirements */
173                         if (attr->n_res > 0) {
174                                 reqs = get_TEMPLATE_out_req_all(n);
175                                 dump_reg_req(F, n, reqs, 1);
176                         }
177
178                         /* dump assigned registers */
179                         slots = get_TEMPLATE_slots(n);
180                         if (slots && attr->n_res > 0) {
181                                 for (i = 0; i < attr->n_res; i++) {
182                                         if (slots[i]) {
183                                                 fprintf(F, "reg #%d = %s\n", i, slots[i]->name);
184                                         }
185                                         else {
186                                                 fprintf(F, "reg #%d = n/a\n", i);
187                                         }
188                                 }
189                         }
190                         fprintf(F, "\n");
191
192                         /* dump n_res */
193                         fprintf(F, "n_res = %d\n", get_TEMPLATE_n_res(n));
194
195                         /* dump flags */
196                         fprintf(F, "flags =");
197                         if (attr->flags == arch_irn_flags_none) {
198                                 fprintf(F, " none");
199                         }
200                         else {
201                                 if (attr->flags & arch_irn_flags_dont_spill) {
202                                         fprintf(F, " unspillable");
203                                 }
204                                 if (attr->flags & arch_irn_flags_rematerializable) {
205                                         fprintf(F, " remat");
206                                 }
207                                 if (attr->flags & arch_irn_flags_ignore) {
208                                         fprintf(F, " ignore");
209                                 }
210                         }
211                         fprintf(F, " (%d)\n", attr->flags);
212
213                         /* TODO: dump all additional attributes */
214
215                         fprintf(F, "=== TEMPLATE attr end ===\n");
216                         /* end of: case dump_node_info_txt */
217                         break;
218         }
219
220
221         return bad;
222 }
223
224
225
226 /***************************************************************************************************
227  *        _   _                   _       __        _                    _   _               _
228  *       | | | |                 | |     / /       | |                  | | | |             | |
229  *   __ _| |_| |_ _ __   ___  ___| |_   / /_ _  ___| |_   _ __ ___   ___| |_| |__   ___   __| |___
230  *  / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
231  * | (_| | |_| |_| |    \__ \  __/ |_ / / (_| |  __/ |_  | | | | | |  __/ |_| | | | (_) | (_| \__ \
232  *  \__,_|\__|\__|_|    |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
233  *                                        __/ |
234  *                                       |___/
235  ***************************************************************************************************/
236
237 /**
238  * Wraps get_irn_generic_attr() as it takes no const ir_node, so we need to do a cast.
239  * Firm was made by people hating const :-(
240  */
241 TEMPLATE_attr_t *get_TEMPLATE_attr(const ir_node *node) {
242         assert(is_TEMPLATE_irn(node) && "need TEMPLATE node to get attributes");
243         return (TEMPLATE_attr_t *)get_irn_generic_attr((ir_node *)node);
244 }
245
246 /**
247  * Returns the argument register requirements of a TEMPLATE node.
248  */
249 const TEMPLATE_register_req_t **get_TEMPLATE_in_req_all(const ir_node *node) {
250         TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
251         return attr->in_req;
252 }
253
254 /**
255  * Returns the result register requirements of an TEMPLATE node.
256  */
257 const TEMPLATE_register_req_t **get_TEMPLATE_out_req_all(const ir_node *node) {
258         TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
259         return attr->out_req;
260 }
261
262 /**
263  * Returns the argument register requirement at position pos of an TEMPLATE node.
264  */
265 const TEMPLATE_register_req_t *get_TEMPLATE_in_req(const ir_node *node, int pos) {
266         TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
267         return attr->in_req[pos];
268 }
269
270 /**
271  * Returns the result register requirement at position pos of an TEMPLATE node.
272  */
273 const TEMPLATE_register_req_t *get_TEMPLATE_out_req(const ir_node *node, int pos) {
274         TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
275         return attr->out_req[pos];
276 }
277
278 /**
279  * Sets the OUT register requirements at position pos.
280  */
281 void set_TEMPLATE_req_out(ir_node *node, const TEMPLATE_register_req_t *req, int pos) {
282         TEMPLATE_attr_t *attr   = get_TEMPLATE_attr(node);
283         attr->out_req[pos] = req;
284 }
285
286 /**
287  * Sets the IN register requirements at position pos.
288  */
289 void set_TEMPLATE_req_in(ir_node *node, const TEMPLATE_register_req_t *req, int pos) {
290         TEMPLATE_attr_t *attr  = get_TEMPLATE_attr(node);
291         attr->in_req[pos] = req;
292 }
293
294 /**
295  * Returns the register flag of an TEMPLATE node.
296  */
297 arch_irn_flags_t get_TEMPLATE_flags(const ir_node *node) {
298         TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
299         return attr->flags;
300 }
301
302 /**
303  * Sets the register flag of an TEMPLATE node.
304  */
305 void set_TEMPLATE_flags(const ir_node *node, arch_irn_flags_t flags) {
306         TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
307         attr->flags      = flags;
308 }
309
310 /**
311  * Returns the result register slots of an TEMPLATE node.
312  */
313 const arch_register_t **get_TEMPLATE_slots(const ir_node *node) {
314         TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
315         return attr->slots;
316 }
317
318 /**
319  * Returns the name of the OUT register at position pos.
320  */
321 const char *get_TEMPLATE_out_reg_name(const ir_node *node, int pos) {
322         TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
323
324         assert(is_TEMPLATE_irn(node) && "Not an TEMPLATE node.");
325         assert(pos < attr->n_res && "Invalid OUT position.");
326         assert(attr->slots[pos]  && "No register assigned");
327
328         return arch_register_get_name(attr->slots[pos]);
329 }
330
331 /**
332  * Returns the index of the OUT register at position pos within its register class.
333  */
334 int get_TEMPLATE_out_regnr(const ir_node *node, int pos) {
335         TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
336
337         assert(is_TEMPLATE_irn(node) && "Not an TEMPLATE node.");
338         assert(pos < attr->n_res && "Invalid OUT position.");
339         assert(attr->slots[pos]  && "No register assigned");
340
341         return arch_register_get_index(attr->slots[pos]);
342 }
343
344 /**
345  * Returns the OUT register at position pos.
346  */
347 const arch_register_t *get_TEMPLATE_out_reg(const ir_node *node, int pos) {
348         TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
349
350         assert(is_TEMPLATE_irn(node) && "Not an TEMPLATE node.");
351         assert(pos < attr->n_res && "Invalid OUT position.");
352         assert(attr->slots[pos]  && "No register assigned");
353
354         return attr->slots[pos];
355 }
356
357 /**
358  * Sets the number of results.
359  */
360 void set_TEMPLATE_n_res(ir_node *node, int n_res) {
361         TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
362         attr->n_res      = n_res;
363 }
364
365 /**
366  * Returns the number of results.
367  */
368 int get_TEMPLATE_n_res(const ir_node *node) {
369         TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
370         return attr->n_res;
371 }
372
373
374
375 /***************************************************************************************
376  *                  _                            _                   _
377  *                 | |                          | |                 | |
378  *  _ __   ___   __| | ___    ___ ___  _ __  ___| |_ _ __ _   _  ___| |_ ___  _ __ ___
379  * | '_ \ / _ \ / _` |/ _ \  / __/ _ \| '_ \/ __| __| '__| | | |/ __| __/ _ \| '__/ __|
380  * | | | | (_) | (_| |  __/ | (_| (_) | | | \__ \ |_| |  | |_| | (__| || (_) | |  \__ \
381  * |_| |_|\___/ \__,_|\___|  \___\___/|_| |_|___/\__|_|   \__,_|\___|\__\___/|_|  |___/
382  *
383  ***************************************************************************************/
384
385 /* Include the generated constructor functions */
386 #include "gen_TEMPLATE_new_nodes.c.inl"