0e05f3dae4466b3bd15584ca62844d4d4dd01cd7
[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       break;
120
121     case dump_node_nodeattr_txt:
122       name = get_irn_opname(n);
123       p = name + strlen(name) - 2;
124       if ((p[0] == '_' && p[1] == 'i') || is_ia32_Const(n) || is_ia32_fConst(n)) {
125         tarval *tv = get_ia32_Immop_tarval(n);
126         if (tv)
127           fprintf_tv(F, tv, 1);
128         else {
129           fprintf(F, "[SymC &%s]", get_sc_name(get_ia32_old_ir(n)));
130         }
131       }
132       else if (is_ia32_Call(n)) {
133         ir_node *sc = get_ia32_old_ir(n);
134
135         fprintf(F, "&%s ", get_sc_name(sc));
136       }
137       break;
138
139     case dump_node_info_txt:
140       attr = get_ia32_attr(n);
141
142       /* dump IN requirements */
143       if (get_irn_arity(n) > 0) {
144         reqs = get_ia32_in_req(n);
145
146         if (reqs) {
147           for (i = 0; i < get_irn_arity(n); i++) {
148             if (reqs[i]->type != arch_register_req_type_none)
149               fprintf(F, "inreq[%d]=[%s]\n", i, reqs[i]->cls->name);
150             else
151               fprintf(F, "inreq[%d]=[none]\n", i);
152           }
153           fprintf(F, "\n");
154         }
155         else
156           fprintf(F, "NO IN REQS\n");
157       }
158
159       /* dump OUT requirements */
160       if (attr->n_res > 0) {
161         reqs = get_ia32_out_req(n);
162
163         if (reqs) {
164           for (i = 0; i < attr->n_res; i++) {
165             if (reqs[i]->type != arch_register_req_type_none)
166               fprintf(F, "outreq[%d]=[%s]\n", i, reqs[i]->cls->name);
167             else
168               fprintf(F, "outreq[%d]=[none]\n", i);
169           }
170         }
171         else
172           fprintf(F, "NO OUT REQS\n");
173       }
174
175       /* dump assigned registers */
176       slots = get_ia32_slots(n);
177       if (slots && attr->n_res > 0) {
178         for (i = 0; i < attr->n_res; i++) {
179           if (slots[i]) {
180             fprintf(F, "REG[%d]=[%s]\n", i, slots[i]->name);
181           }
182           else
183             fprintf(F, "REG[%d]=[none]\n", i);
184         }
185       }
186
187       /* special for LEA */
188       if (is_ia32_Lea(n)) {
189         tarval *o  = get_ia32_offs(n);
190         tarval *tv = get_ia32_Immop_tarval(n);
191
192         fprintf(F, "LEA ");
193         if (o)
194           fprintf_tv(F, o, 0);
195         fprintf(F, "(%s, %s", get_irn_opname(get_irn_n(n, 0)), get_irn_opname(get_irn_n(n, 1)));
196         if (tv) {
197           fprintf(F, ", ");
198           fprintf_tv(F, tv, 0);
199         }
200         fprintf(F, ")\n");
201       }
202       break;
203   }
204
205   return bad;
206 }
207
208
209
210 /***************************************************************************************************
211  *        _   _                   _       __        _                    _   _               _
212  *       | | | |                 | |     / /       | |                  | | | |             | |
213  *   __ _| |_| |_ _ __   ___  ___| |_   / /_ _  ___| |_   _ __ ___   ___| |_| |__   ___   __| |___
214  *  / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
215  * | (_| | |_| |_| |    \__ \  __/ |_ / / (_| |  __/ |_  | | | | | |  __/ |_| | | | (_) | (_| \__ \
216  *  \__,_|\__|\__|_|    |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
217  *                                        __/ |
218  *                                       |___/
219  ***************************************************************************************************/
220
221 /**
222  * Wraps get_irn_generic_attr() as it takes no const ir_node, so we need to do a cast.
223  * Firm was made by people hating const :-(
224  */
225 asmop_attr *get_ia32_attr(const ir_node *node) {
226   return (asmop_attr *)get_irn_generic_attr((ir_node *)node);
227 }
228
229 /**
230  * Return the tarval of an immediate operation or NULL in case of SymConst
231  */
232 tarval *get_ia32_Immop_tarval(const ir_node *node) {
233   asmop_attr *attr = get_ia32_attr(node);
234   if (attr->tp == asmop_Const)
235     return attr->tv;
236   else
237     return NULL;
238 }
239
240 /**
241  * Return the old_ir attribute.
242  */
243 ir_node *get_ia32_old_ir(const ir_node *node) {
244   asmop_attr *attr = get_ia32_attr(node);
245   return attr->old_ir;
246 }
247
248 /**
249  * Copy the attributes from an ia32_Const to an Immop (Add_i, Sub_i, ...) node
250  */
251 void set_ia32_Immop_attr(ir_node *node, ir_node *cnst) {
252   asmop_attr *na = get_ia32_attr(node);
253   asmop_attr *ca = get_ia32_attr(cnst);
254
255   assert((is_ia32_Const(cnst) || is_ia32_fConst(cnst)) && "Need ia32_Const to set Immop attr");
256
257   na->tp     = ca->tp;
258   na->tv     = ca->tv;
259
260   if (ca->old_ir) {
261     na->old_ir = calloc(1, sizeof(*(ca->old_ir)));
262     memcpy(na->old_ir, ca->old_ir, sizeof(*(ca->old_ir)));
263   }
264   else
265     na->old_ir = NULL;
266 }
267
268 /**
269  * Copy the attributes from a Const to an ia32_Const
270  */
271 void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst) {
272   asmop_attr *attr = get_ia32_attr(ia32_cnst);
273
274   assert((is_ia32_Const(ia32_cnst) || is_ia32_fConst(ia32_cnst)) && "Need ia32_Const to set Const attr");
275
276   switch (get_irn_opcode(cnst)) {
277     case iro_Const:
278       attr->tp = asmop_Const;
279       attr->tv = get_Const_tarval(cnst);
280       break;
281     case iro_SymConst:
282       attr->tp     = asmop_SymConst;
283       attr->old_ir = calloc(1, sizeof(*cnst));
284       memcpy(attr->old_ir, cnst, sizeof(*cnst));
285       break;
286     case iro_Unknown:
287       assert(0 && "Unknown Const NYI");
288       break;
289     default:
290       assert(0 && "Cannot create ia32_Const for this opcode");
291   }
292 }
293
294 /**
295  * Sets the type of an ia32_Const.
296  */
297 void set_ia32_Const_type(ir_node *node, int type) {
298         asmop_attr *attr   = get_ia32_attr(node);
299
300         assert((is_ia32_Const(node) || is_ia32_fConst(node)) && "Need ia32_Const to set type");
301         assert((type == asmop_Const || type == asmop_SymConst) && "Unsupported ia32_Const type");
302
303         attr->tp = type;
304 }
305
306 /**
307  * Sets the attributes of an immediate operation to the specified tarval
308  */
309 void set_ia32_Immop_tarval(ir_node *node, tarval *tv) {
310         asmop_attr *attr = get_ia32_attr(node);
311
312         attr->tp = asmop_Const;
313         attr->tv = tv;
314 }
315
316 /**
317  * Sets the offset for a Lea.
318  */
319 void set_ia32_offs(ir_node *node, tarval *offs) {
320         asmop_attr *attr = get_ia32_attr(node);
321         attr->offset     = offs;
322 }
323
324 /**
325  * Gets the offset for a Lea.
326  */
327 tarval *get_ia32_offs(const ir_node *node) {
328         asmop_attr *attr = get_ia32_attr(node);
329         return attr->offset;
330 }
331
332 /**
333  * Returns the argument register requirements of an ia32 node.
334  */
335 const arch_register_req_t **get_ia32_in_req(const ir_node *node) {
336         asmop_attr *attr = get_ia32_attr(node);
337         return attr->in_req;
338 }
339
340 /**
341  * Returns the result register requirements of an ia32 node.
342  */
343 const arch_register_req_t **get_ia32_out_req(const ir_node *node) {
344         asmop_attr *attr = get_ia32_attr(node);
345         return attr->out_req;
346 }
347
348 /**
349  * Sets the OUT register requirements at position pos.
350  */
351 void set_ia32_regreq_out(ir_node *node, const arch_register_req_t *req, int pos) {
352         asmop_attr *attr   = get_ia32_attr(node);
353         attr->out_req[pos] = req;
354 }
355
356 /**
357  * Sets the IN register requirements at position pos.
358  */
359 void set_ia32_regreq_in(ir_node *node, const arch_register_req_t *req, int pos) {
360         asmop_attr *attr  = get_ia32_attr(node);
361         attr->in_req[pos] = req;
362 }
363
364 /**
365  * Returns the register flag of an ia32 node.
366  */
367 arch_irn_flags_t get_ia32_flags(const ir_node *node) {
368         asmop_attr *attr = get_ia32_attr(node);
369         return attr->flags;
370 }
371
372 /**
373  * Returns the result register slots of an ia32 node.
374  */
375 const arch_register_t **get_ia32_slots(const ir_node *node) {
376         asmop_attr *attr = get_ia32_attr(node);
377         return attr->slots;
378 }
379
380 /**
381  * Returns the name of the OUT register at position pos.
382  */
383 const char *get_ia32_out_reg_name(const ir_node *node, int pos) {
384         asmop_attr *attr = get_ia32_attr(node);
385
386         assert(is_ia32_irn(node) && "Not an ia32 node.");
387         assert(pos < attr->n_res && "Invalid OUT position.");
388         assert(attr->slots[pos]  && "No register assigned");
389
390         return attr->slots[pos]->name;
391 }
392
393 /**
394  * Returns the index of the OUT register at position pos within its register class.
395  */
396 int get_ia32_out_regnr(const ir_node *node, int pos) {
397         asmop_attr *attr = get_ia32_attr(node);
398
399         assert(is_ia32_irn(node) && "Not an ia32 node.");
400         assert(pos < attr->n_res && "Invalid OUT position.");
401         assert(attr->slots[pos]  && "No register assigned");
402
403         return attr->slots[pos]->index;
404 }
405
406 /**
407  * Returns the OUT register at position pos.
408  */
409 const arch_register_t *get_ia32_out_reg(const ir_node *node, int pos) {
410         asmop_attr *attr = get_ia32_attr(node);
411
412         assert(is_ia32_irn(node) && "Not an ia32 node.");
413         assert(pos < attr->n_res && "Invalid OUT position.");
414         assert(attr->slots[pos]  && "No register assigned");
415
416         return attr->slots[pos];
417 }
418
419 /**
420  * Sets the number of results.
421  */
422 void set_ia32_n_res(ir_node *node, int n_res) {
423         asmop_attr *attr = get_ia32_attr(node);
424         attr->n_res = n_res;
425 }
426
427 /**
428  * Returns the number of results.
429  */
430 int get_ia32_n_res(const ir_node *node) {
431         asmop_attr *attr = get_ia32_attr(node);
432         return attr->n_res;
433 }
434
435 /**
436  * Sets the flavour of an ia32 DivMod node to flavour_Div/Mod/DivMod.
437  */
438 void set_ia32_DivMod_flavour(ir_node *node, divmod_flavour_t dm_flav) {
439         asmop_attr *attr = get_ia32_attr(node);
440         attr->dm_flav    = dm_flav;
441 }
442
443 /**
444  * Returns the projnum code.
445  */
446 long get_ia32_pncode(const ir_node *node) {
447         asmop_attr *attr = get_ia32_attr(node);
448         return attr->pn_code;
449 }
450
451 /**
452  * Sets the projnum code
453  */
454 void set_ia32_pncode(ir_node *node, long code) {
455         asmop_attr *attr = get_ia32_attr(node);
456         attr->pn_code = code;
457 }
458
459 /* Include the generated functions */
460 #include "gen_ia32_new_nodes.c.inl"