bfc0f2303fda6be37de38a286c0cd08ffd0f23c9
[libfirm] / ir / be / ia32 / ia32_new_nodes.c
1 /**
2  * This file implements the creation of the achitecture specific firm opcodes
3  * and the coresponding node constructors for the $arch assembler irg.
4  * @author Christian Wuerdig
5  * $Id$
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include <stdlib.h>
13
14 #include "irprog_t.h"
15 #include "irgraph_t.h"
16 #include "irnode_t.h"
17 #include "irmode_t.h"
18 #include "ircons_t.h"
19 #include "iropt_t.h"
20 #include "irop.h"
21 #include "firm_common_t.h"
22 #include "irvrfy_t.h"
23
24 #include "../bearch.h"
25
26 #include "ia32_nodes_attr.h"
27 #include "ia32_new_nodes.h"
28 #include "gen_ia32_regalloc_if.h"
29
30
31
32 /***********************************************************************************
33  *      _                                   _       _             __
34  *     | |                                 (_)     | |           / _|
35  *   __| |_   _ _ __ ___  _ __   ___ _ __   _ _ __ | |_ ___ _ __| |_ __ _  ___ ___
36  *  / _` | | | | '_ ` _ \| '_ \ / _ \ '__| | | '_ \| __/ _ \ '__|  _/ _` |/ __/ _ \
37  * | (_| | |_| | | | | | | |_) |  __/ |    | | | | | ||  __/ |  | || (_| | (_|  __/
38  *  \__,_|\__,_|_| |_| |_| .__/ \___|_|    |_|_| |_|\__\___|_|  |_| \__,_|\___\___|
39  *                       | |
40  *                       |_|
41  ***********************************************************************************/
42
43 /**
44  * Prints a tarval to file F.
45  * @param F         output file
46  * @param tv        tarval
47  * @param brackets  1 == print square brackets around tarval
48  */
49 static void fprintf_tv(FILE *F, tarval *tv, int brackets) {
50         char buf[1024];
51         tarval_snprintf(buf, sizeof(buf), tv);
52
53         if (brackets)
54                 fprintf(F, "[%s]", buf);
55         else
56                 fprintf(F, "%s", buf);
57 }
58
59 /**
60  * Returns the name of a SymConst.
61  * @param symc  the SymConst
62  * @return name of the SymConst
63  */
64 const char *get_sc_name(ir_node *symc) {
65         if (get_irn_opcode(symc) != iro_SymConst)
66                 return "NONE";
67
68         switch (get_SymConst_kind(symc)) {
69                 case symconst_addr_name:
70                         return get_id_str(get_SymConst_name(symc));
71
72                 case symconst_addr_ent:
73                         return get_entity_ld_name(get_SymConst_entity(symc));
74
75                 default:
76                         assert(0 && "Unsupported SymConst");
77         }
78
79         return NULL;
80 }
81
82 /**
83  * Dumper interface for dumping ia32 nodes in vcg.
84  * @param n        the node to dump
85  * @param F        the output file
86  * @param reason   indicates which kind of information should be dumped
87  * @return 0 on success or != 0 on failure
88  */
89 static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) {
90         const char *name, *p;
91         ir_mode    *mode = NULL;
92         int        bad   = 0;
93         asmop_attr *attr;
94         int        i;
95         const arch_register_req_t **reqs;
96         const arch_register_t     **slots;
97
98         switch (reason) {
99                 case dump_node_opcode_txt:
100                         name = get_irn_opname(n);
101                         fprintf(F, "%s", name);
102                         break;
103
104                 case dump_node_mode_txt:
105                         mode = get_irn_mode(n);
106
107                         if (mode == mode_BB || mode == mode_ANY || mode == mode_BAD || mode == mode_T) {
108                                 mode = NULL;
109                         }
110                         else if (is_ia32_Load(n)) {
111                                 mode = get_irn_mode(get_irn_n(n, 1));
112                         }
113                         else if (is_ia32_Store(n)) {
114                                 mode = get_irn_mode(get_irn_n(n, 2));
115                         }
116
117                         if (mode) {
118                                 fprintf(F, "[%s]", get_mode_name(mode));
119                         }
120                         break;
121
122                 case dump_node_nodeattr_txt:
123                         name = get_irn_opname(n);
124                         p = name + strlen(name) - 2;
125                         if ((p[0] == '_' && p[1] == 'i') || is_ia32_Const(n) || is_ia32_fConst(n)) {
126                                 tarval *tv = get_ia32_Immop_tarval(n);
127                                 if (tv) {
128                                         fprintf_tv(F, tv, 1);
129                                 }
130                                 else {
131                                         fprintf(F, "[SymC &%s]", get_sc_name(get_ia32_old_ir(n)));
132                                 }
133                         }
134                         else if (is_ia32_Call(n)) {
135                                 ir_node *sc = get_ia32_old_ir(n);
136
137                                 fprintf(F, "&%s ", get_sc_name(sc));
138                         }
139
140                         if (is_ia32_AddrMode(n)) {
141                                 fprintf(F, "[AddrMode] ");
142                         }
143
144                         break;
145
146                 case dump_node_info_txt:
147                         attr = get_ia32_attr(n);
148
149                         /* dump IN requirements */
150                         if (get_irn_arity(n) > 0) {
151                                 reqs = get_ia32_in_req(n);
152
153                                 if (reqs) {
154                                         for (i = 0; i < get_irn_arity(n); i++) {
155                                                 if (reqs[i]->type != arch_register_req_type_none) {
156                                                         fprintf(F, "inreq[%d]=[%s]\n", i, reqs[i]->cls->name);
157                                                 }
158                                                 else {
159                                                         fprintf(F, "inreq[%d]=[none]\n", i);
160                                                 }
161                                         }
162
163                                         fprintf(F, "\n");
164                                 }
165                                 else {
166                                         fprintf(F, "NO IN REQS\n");
167                                 }
168                         }
169
170                         /* dump OUT requirements */
171                         if (attr->n_res > 0) {
172                                 reqs = get_ia32_out_req(n);
173
174                                 if (reqs) {
175                                         for (i = 0; i < attr->n_res; i++) {
176                                                 if (reqs[i]->type != arch_register_req_type_none) {
177                                                         fprintf(F, "outreq[%d]=[%s]\n", i, reqs[i]->cls->name);
178                                                 }
179                                                 else {
180                                                         fprintf(F, "outreq[%d]=[none]\n", i);
181                                                 }
182                                         }
183                                 }
184                                 else {
185                                         fprintf(F, "NO OUT REQS\n");
186                                 }
187                         }
188
189                         /* dump assigned registers */
190                         slots = get_ia32_slots(n);
191                         if (slots && attr->n_res > 0) {
192                                 for (i = 0; i < attr->n_res; i++) {
193                                         if (slots[i]) {
194                                                 fprintf(F, "reg #%d = %s\n", i, slots[i]->name);
195                                         }
196                                         else {
197                                                 fprintf(F, "reg #%d = n/a\n", i);
198                                         }
199                                 }
200                         }
201
202                         /* special for LEA */
203                         if (is_ia32_Lea(n) || is_ia32_Lea_i(n)) {
204                                 tarval *o  = get_ia32_offs(n);
205                                 tarval *tv = get_ia32_Immop_tarval(n);
206
207                                 if (is_ia32_AddrMode(n)) {
208                                         fprintf(F, "AddrMode ");
209                                 }
210
211                                 fprintf(F, "LEA ");
212                                 if (o) {
213                                         fprintf_tv(F, o, 0);
214                                 }
215
216                                 fprintf(F, "(%s", get_irn_opname(get_irn_n(n, 0)));
217
218                                 if (is_ia32_Lea(n)) {
219                                         fprintf(F, ", %s", get_irn_opname(get_irn_n(n, 1)));
220                                 }
221
222                                 if (tv) {
223                                         fprintf(F, ", ");
224                                         fprintf_tv(F, tv, 0);
225                                 }
226                                 fprintf(F, ")\n");
227                         }
228                         break;
229         }
230
231         return bad;
232 }
233
234
235
236 /***************************************************************************************************
237  *        _   _                   _       __        _                    _   _               _
238  *       | | | |                 | |     / /       | |                  | | | |             | |
239  *   __ _| |_| |_ _ __   ___  ___| |_   / /_ _  ___| |_   _ __ ___   ___| |_| |__   ___   __| |___
240  *  / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
241  * | (_| | |_| |_| |    \__ \  __/ |_ / / (_| |  __/ |_  | | | | | |  __/ |_| | | | (_) | (_| \__ \
242  *  \__,_|\__|\__|_|    |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
243  *                                        __/ |
244  *                                       |___/
245  ***************************************************************************************************/
246
247 /**
248  * Wraps get_irn_generic_attr() as it takes no const ir_node, so we need to do a cast.
249  * Firm was made by people hating const :-(
250  */
251 asmop_attr *get_ia32_attr(const ir_node *node) {
252   return (asmop_attr *)get_irn_generic_attr((ir_node *)node);
253 }
254
255 /**
256  * Return the tarval of an immediate operation or NULL in case of SymConst
257  */
258 tarval *get_ia32_Immop_tarval(const ir_node *node) {
259   asmop_attr *attr = get_ia32_attr(node);
260   if (attr->tp == asmop_Const)
261     return attr->tv;
262   else
263     return NULL;
264 }
265
266 /**
267  * Return the old_ir attribute.
268  */
269 ir_node *get_ia32_old_ir(const ir_node *node) {
270   asmop_attr *attr = get_ia32_attr(node);
271   return attr->old_ir;
272 }
273
274 /**
275  * Copy the attributes from an ia32_Const to an Immop (Add_i, Sub_i, ...) node
276  */
277 void set_ia32_Immop_attr(ir_node *node, ir_node *cnst) {
278   asmop_attr *na = get_ia32_attr(node);
279   asmop_attr *ca = get_ia32_attr(cnst);
280
281   assert((is_ia32_Const(cnst) || is_ia32_fConst(cnst)) && "Need ia32_Const to set Immop attr");
282
283   na->tp     = ca->tp;
284   na->tv     = ca->tv;
285
286   if (ca->old_ir) {
287     na->old_ir = calloc(1, sizeof(*(ca->old_ir)));
288     memcpy(na->old_ir, ca->old_ir, sizeof(*(ca->old_ir)));
289   }
290   else
291     na->old_ir = NULL;
292 }
293
294 /**
295  * Copy the attributes from a Const to an ia32_Const
296  */
297 void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst) {
298   asmop_attr *attr = get_ia32_attr(ia32_cnst);
299
300   assert((is_ia32_Const(ia32_cnst) || is_ia32_fConst(ia32_cnst)) && "Need ia32_Const to set Const attr");
301
302   switch (get_irn_opcode(cnst)) {
303     case iro_Const:
304       attr->tp = asmop_Const;
305       attr->tv = get_Const_tarval(cnst);
306       break;
307     case iro_SymConst:
308       attr->tp     = asmop_SymConst;
309       attr->old_ir = calloc(1, sizeof(*cnst));
310       memcpy(attr->old_ir, cnst, sizeof(*cnst));
311       break;
312     case iro_Unknown:
313       assert(0 && "Unknown Const NYI");
314       break;
315     default:
316       assert(0 && "Cannot create ia32_Const for this opcode");
317   }
318 }
319
320 /**
321  * Sets the type of an ia32_Const.
322  */
323 void set_ia32_Const_type(ir_node *node, int type) {
324         asmop_attr *attr = get_ia32_attr(node);
325
326         assert((is_ia32_Const(node) || is_ia32_fConst(node)) && "Need ia32_Const to set type");
327         assert((type == asmop_Const || type == asmop_SymConst) && "Unsupported ia32_Const type");
328
329         attr->tp = type;
330 }
331
332 /**
333  * Sets the AddrMode attribute
334  */
335 void set_ia32_AddrMode(ir_node *node) {
336         asmop_attr *attr = get_ia32_attr(node);
337         attr->tp = asmop_AddrMode;
338 }
339
340 /**
341  * Returns whether or not the node is an AddrMode node.
342  */
343 int is_ia32_AddrMode(ir_node *node) {
344         asmop_attr *attr = get_ia32_attr(node);
345         return (attr->tp == asmop_AddrMode);
346 }
347
348 /**
349  * Sets the attributes of an immediate operation to the specified tarval
350  */
351 void set_ia32_Immop_tarval(ir_node *node, tarval *tv) {
352         asmop_attr *attr = get_ia32_attr(node);
353
354         attr->tp = asmop_Const;
355         attr->tv = tv;
356 }
357
358 /**
359  * Sets the offset for a Lea.
360  */
361 void set_ia32_offs(ir_node *node, tarval *offs) {
362         asmop_attr *attr = get_ia32_attr(node);
363         attr->offset     = offs;
364 }
365
366 /**
367  * Gets the offset for a Lea.
368  */
369 tarval *get_ia32_offs(const ir_node *node) {
370         asmop_attr *attr = get_ia32_attr(node);
371         return attr->offset;
372 }
373
374 /**
375  * Returns the argument register requirements of an ia32 node.
376  */
377 const arch_register_req_t **get_ia32_in_req(const ir_node *node) {
378         asmop_attr *attr = get_ia32_attr(node);
379         return attr->in_req;
380 }
381
382 /**
383  * Returns the result register requirements of an ia32 node.
384  */
385 const arch_register_req_t **get_ia32_out_req(const ir_node *node) {
386         asmop_attr *attr = get_ia32_attr(node);
387         return attr->out_req;
388 }
389
390 /**
391  * Sets the OUT register requirements at position pos.
392  */
393 void set_ia32_regreq_out(ir_node *node, const arch_register_req_t *req, int pos) {
394         asmop_attr *attr   = get_ia32_attr(node);
395         attr->out_req[pos] = req;
396 }
397
398 /**
399  * Sets the IN register requirements at position pos.
400  */
401 void set_ia32_regreq_in(ir_node *node, const arch_register_req_t *req, int pos) {
402         asmop_attr *attr  = get_ia32_attr(node);
403         attr->in_req[pos] = req;
404 }
405
406 /**
407  * Returns the register flag of an ia32 node.
408  */
409 arch_irn_flags_t get_ia32_flags(const ir_node *node) {
410         asmop_attr *attr = get_ia32_attr(node);
411         return attr->flags;
412 }
413
414 /**
415  * Returns the result register slots of an ia32 node.
416  */
417 const arch_register_t **get_ia32_slots(const ir_node *node) {
418         asmop_attr *attr = get_ia32_attr(node);
419         return attr->slots;
420 }
421
422 /**
423  * Returns the name of the OUT register at position pos.
424  */
425 const char *get_ia32_out_reg_name(const ir_node *node, int pos) {
426         asmop_attr *attr = get_ia32_attr(node);
427
428         assert(is_ia32_irn(node) && "Not an ia32 node.");
429         assert(pos < attr->n_res && "Invalid OUT position.");
430         assert(attr->slots[pos]  && "No register assigned");
431
432         return attr->slots[pos]->name;
433 }
434
435 /**
436  * Returns the index of the OUT register at position pos within its register class.
437  */
438 int get_ia32_out_regnr(const ir_node *node, int pos) {
439         asmop_attr *attr = get_ia32_attr(node);
440
441         assert(is_ia32_irn(node) && "Not an ia32 node.");
442         assert(pos < attr->n_res && "Invalid OUT position.");
443         assert(attr->slots[pos]  && "No register assigned");
444
445         return attr->slots[pos]->index;
446 }
447
448 /**
449  * Returns the OUT register at position pos.
450  */
451 const arch_register_t *get_ia32_out_reg(const ir_node *node, int pos) {
452         asmop_attr *attr = get_ia32_attr(node);
453
454         assert(is_ia32_irn(node) && "Not an ia32 node.");
455         assert(pos < attr->n_res && "Invalid OUT position.");
456         assert(attr->slots[pos]  && "No register assigned");
457
458         return attr->slots[pos];
459 }
460
461 /**
462  * Sets the number of results.
463  */
464 void set_ia32_n_res(ir_node *node, int n_res) {
465         asmop_attr *attr = get_ia32_attr(node);
466         attr->n_res = n_res;
467 }
468
469 /**
470  * Returns the number of results.
471  */
472 int get_ia32_n_res(const ir_node *node) {
473         asmop_attr *attr = get_ia32_attr(node);
474         return attr->n_res;
475 }
476
477 /**
478  * Sets the flavour of an ia32 DivMod node to flavour_Div/Mod/DivMod.
479  */
480 void set_ia32_DivMod_flavour(ir_node *node, divmod_flavour_t dm_flav) {
481         asmop_attr *attr = get_ia32_attr(node);
482         attr->dm_flav    = dm_flav;
483 }
484
485 /**
486  * Returns the projnum code.
487  */
488 long get_ia32_pncode(const ir_node *node) {
489         asmop_attr *attr = get_ia32_attr(node);
490         return attr->pn_code;
491 }
492
493 /**
494  * Sets the projnum code
495  */
496 void set_ia32_pncode(ir_node *node, long code) {
497         asmop_attr *attr = get_ia32_attr(node);
498         attr->pn_code = code;
499 }
500
501 /* Include the generated functions */
502 #include "gen_ia32_new_nodes.c.inl"