new header for internal usage
[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_all(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_all(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_am_offs(n);
205                                 tarval *tv = get_ia32_Immop_tarval(n);
206
207                                 fprintf(F, "LEA ");
208                                 if (o) {
209                                         fprintf_tv(F, o, 0);
210                                 }
211
212                                 fprintf(F, "(%s", get_irn_opname(get_irn_n(n, 0)));
213
214                                 if (is_ia32_Lea(n)) {
215                                         fprintf(F, ", %s", get_irn_opname(get_irn_n(n, 1)));
216                                 }
217
218                                 if (tv) {
219                                         fprintf(F, ", ");
220                                         fprintf_tv(F, tv, 0);
221                                 }
222                                 fprintf(F, ")\n");
223                         }
224                         break;
225         }
226
227         return bad;
228 }
229
230
231
232 /***************************************************************************************************
233  *        _   _                   _       __        _                    _   _               _
234  *       | | | |                 | |     / /       | |                  | | | |             | |
235  *   __ _| |_| |_ _ __   ___  ___| |_   / /_ _  ___| |_   _ __ ___   ___| |_| |__   ___   __| |___
236  *  / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
237  * | (_| | |_| |_| |    \__ \  __/ |_ / / (_| |  __/ |_  | | | | | |  __/ |_| | | | (_) | (_| \__ \
238  *  \__,_|\__|\__|_|    |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
239  *                                        __/ |
240  *                                       |___/
241  ***************************************************************************************************/
242
243 /**
244  * Wraps get_irn_generic_attr() as it takes no const ir_node, so we need to do a cast.
245  * Firm was made by people hating const :-(
246  */
247 asmop_attr *get_ia32_attr(const ir_node *node) {
248         assert(is_ia32_irn(node) && "need ia32 node to get ia32 attributes");
249         return (asmop_attr *)get_irn_generic_attr((ir_node *)node);
250 }
251
252 /**
253  * Gets the type of an ia32 node.
254  */
255 asmop_type_t get_ia32_op_type(const ir_node *node) {
256         asmop_attr *attr = get_ia32_attr(node);
257         return attr->tp;
258 }
259
260 /**
261  * Sets the type of an ia32 node.
262  */
263 void set_ia32_op_type(const ir_node *node, asmop_type_t tp) {
264         asmop_attr *attr = get_ia32_attr(node);
265         attr->tp         = tp;
266 }
267
268 /**
269  * Gets the addr mode type of an ia32 node
270  */
271 addrmode_type_t get_ia32_am_type(const ir_node *node) {
272         asmop_attr *attr = get_ia32_attr(node);
273         return attr->am_tp;
274 }
275
276 /**
277  * Sets the addr mode type of an ia32 node
278  */
279 void set_ia32_am_type(const ir_node *node, addrmode_type_t am_tp) {
280         asmop_attr *attr = get_ia32_attr(node);
281         attr->am_tp      = am_tp;
282 }
283
284 /**
285  * Gets the addr mode offset.
286  */
287 tarval *get_ia32_am_offs(const ir_node *node) {
288         asmop_attr *attr = get_ia32_attr(node);
289         return attr->am_offs;
290 }
291
292 /**
293  * Sets the offset for addr mode.
294  */
295 void set_ia32_am_offs(ir_node *node, tarval *am_offs) {
296         asmop_attr *attr = get_ia32_attr(node);
297         attr->am_offs    = am_offs;
298 }
299
300 /**
301  * Gets the addr mode const.
302  */
303 tarval *get_ia32_am_const(const ir_node *node) {
304         asmop_attr *attr = get_ia32_attr(node);
305         return attr->am_const;
306 }
307
308 /**
309  * Sets the const for addr mode.
310  */
311 void set_ia32_am_const(ir_node *node, tarval *am_const) {
312         asmop_attr *attr = get_ia32_attr(node);
313         attr->am_const   = am_const;
314 }
315
316 /**
317  * Return the tarval of an immediate operation or NULL in case of SymConst
318  */
319 tarval *get_ia32_Immop_tarval(const ir_node *node) {
320         asmop_attr *attr = get_ia32_attr(node);
321     return attr->tv;
322 }
323
324 /**
325  * Sets the attributes of an immediate operation to the specified tarval
326  */
327 void set_ia32_Immop_tarval(ir_node *node, tarval *tv) {
328         asmop_attr *attr = get_ia32_attr(node);
329         attr->tv = tv;
330 }
331
332 /**
333  * Return the old_ir attribute.
334  */
335 ir_node *get_ia32_old_ir(const ir_node *node) {
336   asmop_attr *attr = get_ia32_attr(node);
337   return attr->old_ir;
338 }
339
340 /**
341  * Sets the old_ir attribute.
342  */
343 void set_ia32_old_ir(ir_node *node, ir_node *old_ir) {
344   asmop_attr *attr = get_ia32_attr(node);
345   attr->old_ir = old_ir;
346 }
347
348 /**
349  * Returns the argument register requirements of an ia32 node.
350  */
351 const arch_register_req_t **get_ia32_in_req_all(const ir_node *node) {
352         asmop_attr *attr = get_ia32_attr(node);
353         return attr->in_req;
354 }
355
356 /**
357  * Returns the result register requirements of an ia32 node.
358  */
359 const arch_register_req_t **get_ia32_out_req_all(const ir_node *node) {
360         asmop_attr *attr = get_ia32_attr(node);
361         return attr->out_req;
362 }
363
364 /**
365  * Returns the argument register requirement at position pos of an ia32 node.
366  */
367 const arch_register_req_t *get_ia32_in_req(const ir_node *node, int pos) {
368         asmop_attr *attr = get_ia32_attr(node);
369         return attr->in_req[pos];
370 }
371
372 /**
373  * Returns the result register requirement at position pos of an ia32 node.
374  */
375 const arch_register_req_t *get_ia32_out_req(const ir_node *node, int pos) {
376         asmop_attr *attr = get_ia32_attr(node);
377         return attr->out_req[pos];
378 }
379
380 /**
381  * Sets the OUT register requirements at position pos.
382  */
383 void set_ia32_req_out(ir_node *node, const arch_register_req_t *req, int pos) {
384         asmop_attr *attr   = get_ia32_attr(node);
385         attr->out_req[pos] = req;
386 }
387
388 /**
389  * Sets the IN register requirements at position pos.
390  */
391 void set_ia32_req_in(ir_node *node, const arch_register_req_t *req, int pos) {
392         asmop_attr *attr  = get_ia32_attr(node);
393         attr->in_req[pos] = req;
394 }
395
396 /**
397  * Returns the register flag of an ia32 node.
398  */
399 arch_irn_flags_t get_ia32_flags(const ir_node *node) {
400         asmop_attr *attr = get_ia32_attr(node);
401         return attr->flags;
402 }
403
404 /**
405  * Sets the register flag of an ia32 node.
406  */
407 void set_ia32_flags(const ir_node *node, arch_irn_flags_t flags) {
408         asmop_attr *attr = get_ia32_attr(node);
409         attr->flags      = flags;
410 }
411
412 /**
413  * Returns the result register slots of an ia32 node.
414  */
415 const arch_register_t **get_ia32_slots(const ir_node *node) {
416         asmop_attr *attr = get_ia32_attr(node);
417         return attr->slots;
418 }
419
420 /**
421  * Returns the name of the OUT register at position pos.
422  */
423 const char *get_ia32_out_reg_name(const ir_node *node, int pos) {
424         asmop_attr *attr = get_ia32_attr(node);
425
426         assert(is_ia32_irn(node) && "Not an ia32 node.");
427         assert(pos < attr->n_res && "Invalid OUT position.");
428         assert(attr->slots[pos]  && "No register assigned");
429
430         return arch_register_get_name(attr->slots[pos]);
431 }
432
433 /**
434  * Returns the index of the OUT register at position pos within its register class.
435  */
436 int get_ia32_out_regnr(const ir_node *node, int pos) {
437         asmop_attr *attr = get_ia32_attr(node);
438
439         assert(is_ia32_irn(node) && "Not an ia32 node.");
440         assert(pos < attr->n_res && "Invalid OUT position.");
441         assert(attr->slots[pos]  && "No register assigned");
442
443         return arch_register_get_index(attr->slots[pos]);
444 }
445
446 /**
447  * Returns the OUT register at position pos.
448  */
449 const arch_register_t *get_ia32_out_reg(const ir_node *node, int pos) {
450         asmop_attr *attr = get_ia32_attr(node);
451
452         assert(is_ia32_irn(node) && "Not an ia32 node.");
453         assert(pos < attr->n_res && "Invalid OUT position.");
454         assert(attr->slots[pos]  && "No register assigned");
455
456         return attr->slots[pos];
457 }
458
459 /**
460  * Sets the number of results.
461  */
462 void set_ia32_n_res(ir_node *node, int n_res) {
463         asmop_attr *attr = get_ia32_attr(node);
464         attr->n_res      = n_res;
465 }
466
467 /**
468  * Returns the number of results.
469  */
470 int get_ia32_n_res(const ir_node *node) {
471         asmop_attr *attr = get_ia32_attr(node);
472         return attr->n_res;
473 }
474
475 /**
476  * Returns the flavour of an ia32 DivMod,
477  */
478 divmod_flavour_t get_ia32_DivMod_flavour(const ir_node *node) {
479         asmop_attr *attr = get_ia32_attr(node);
480         return attr->dm_flav;
481 }
482
483 /**
484  * Sets the flavour of an ia32 DivMod node to flavour_Div/Mod/DivMod.
485  */
486 void set_ia32_DivMod_flavour(ir_node *node, divmod_flavour_t dm_flav) {
487         asmop_attr *attr = get_ia32_attr(node);
488         attr->dm_flav    = dm_flav;
489 }
490
491 /**
492  * Returns the projnum code.
493  */
494 long get_ia32_pncode(const ir_node *node) {
495         asmop_attr *attr = get_ia32_attr(node);
496         return attr->pn_code;
497 }
498
499 /**
500  * Sets the projnum code
501  */
502 void set_ia32_pncode(ir_node *node, long code) {
503         asmop_attr *attr = get_ia32_attr(node);
504         attr->pn_code    = code;
505 }
506
507
508 /******************************************************************************************************
509  *                      _       _         _   _           __                  _   _
510  *                     (_)     | |       | | | |         / _|                | | (_)
511  *  ___ _ __   ___  ___ _  __ _| |   __ _| |_| |_ _ __  | |_ _   _ _ __   ___| |_ _  ___  _ __    ___
512  * / __| '_ \ / _ \/ __| |/ _` | |  / _` | __| __| '__| |  _| | | | '_ \ / __| __| |/ _ \| '_ \  / __|
513  * \__ \ |_) |  __/ (__| | (_| | | | (_| | |_| |_| |    | | | |_| | | | | (__| |_| | (_) | | | | \__ \
514  * |___/ .__/ \___|\___|_|\__,_|_|  \__,_|\__|\__|_|    |_|  \__,_|_| |_|\___|\__|_|\___/|_| |_| |___/
515  *     | |
516  *     |_|
517  ******************************************************************************************************/
518
519 /**
520  * Gets the type of an ia32_Const.
521  */
522 unsigned get_ia32_Const_type(ir_node *node) {
523         asmop_attr *attr = get_ia32_attr(node);
524
525         assert((is_ia32_Const(node) || is_ia32_fConst(node)) && "Need ia32_Const to get type");
526
527         return attr->tp;
528 }
529
530 /**
531  * Sets the type of an ia32_Const.
532  */
533 void set_ia32_Const_type(ir_node *node, int type) {
534         asmop_attr *attr = get_ia32_attr(node);
535
536         assert((is_ia32_Const(node) || is_ia32_fConst(node)) && "Need ia32_Const to set type");
537         assert((type == asmop_Const || type == asmop_SymConst) && "Unsupported ia32_Const type");
538
539         attr->tp = type;
540 }
541
542 /**
543  * Copy the attributes from an ia32_Const to an Immop (Add_i, Sub_i, ...) node
544  */
545 void set_ia32_Immop_attr(ir_node *node, ir_node *cnst) {
546         asmop_attr *na = get_ia32_attr(node);
547         asmop_attr *ca = get_ia32_attr(cnst);
548
549         assert((is_ia32_Const(cnst) || is_ia32_fConst(cnst)) && "Need ia32_Const to set Immop attr");
550
551         na->tp = ca->tp;
552         na->tv = ca->tv;
553
554         if (ca->old_ir) {
555                 na->old_ir = calloc(1, sizeof(*(ca->old_ir)));
556                 memcpy(na->old_ir, ca->old_ir, sizeof(*(ca->old_ir)));
557         }
558         else {
559                 na->old_ir = NULL;
560         }
561 }
562
563 /**
564  * Copy the attributes from a Const to an ia32_Const
565  */
566 void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst) {
567         asmop_attr *attr = get_ia32_attr(ia32_cnst);
568
569         assert((is_ia32_Const(ia32_cnst) || is_ia32_fConst(ia32_cnst)) && "Need ia32_Const to set Const attr");
570
571         switch (get_irn_opcode(cnst)) {
572                 case iro_Const:
573                         attr->tp = asmop_Const;
574                         attr->tv = get_Const_tarval(cnst);
575                         break;
576                 case iro_SymConst:
577                         attr->tp     = asmop_SymConst;
578                         attr->tv     = NULL;
579                         attr->old_ir = calloc(1, sizeof(*cnst));
580                         memcpy(attr->old_ir, cnst, sizeof(*cnst));
581                         break;
582                 case iro_Unknown:
583                         assert(0 && "Unknown Const NYI");
584                         break;
585                 default:
586                         assert(0 && "Cannot create ia32_Const for this opcode");
587         }
588 }
589
590 /**
591  * Sets the AddrMode attribute
592  */
593 void set_ia32_AddrMode(ir_node *node) {
594         asmop_attr *attr = get_ia32_attr(node);
595         attr->tp         = asmop_AddrMode;
596 }
597
598 /**
599  * Returns whether or not the node is an AddrMode node.
600  */
601 int is_ia32_AddrMode(ir_node *node) {
602         asmop_attr *attr = get_ia32_attr(node);
603         return (attr->tp == asmop_AddrMode);
604 }
605
606 /* Include the generated functions */
607 #include "gen_ia32_new_nodes.c.inl"