Made everything really kaputt
[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 "firm_common_t.h"
21 #include "irvrfy_t.h"
22
23 #include "../bearch.h"
24
25 #include "ia32_nodes_attr.h"
26 #include "ia32_new_nodes.h"
27
28
29
30 /***********************************************************************************
31  *      _                                   _       _             __
32  *     | |                                 (_)     | |           / _|
33  *   __| |_   _ _ __ ___  _ __   ___ _ __   _ _ __ | |_ ___ _ __| |_ __ _  ___ ___
34  *  / _` | | | | '_ ` _ \| '_ \ / _ \ '__| | | '_ \| __/ _ \ '__|  _/ _` |/ __/ _ \
35  * | (_| | |_| | | | | | | |_) |  __/ |    | | | | | ||  __/ |  | || (_| | (_|  __/
36  *  \__,_|\__,_|_| |_| |_| .__/ \___|_|    |_|_| |_|\__\___|_|  |_| \__,_|\___\___|
37  *                       | |
38  *                       |_|
39  ***********************************************************************************/
40
41 /**
42  * Prints a tarval to file F.
43  * @param F         output file
44  * @param tv        tarval
45  * @param brackets  1 == print square brackets around tarval
46  */
47 static void fprintf_tv(FILE *F, tarval *tv, int brackets) {
48   char buf[1024];
49   tarval_snprintf(buf, sizeof(buf), tv);
50
51   if (brackets)
52     fprintf(F, "[%s]", buf);
53   else
54     fprintf(F, "%s", buf);
55 }
56
57 /**
58  * Returns the name of a SymConst.
59  * @param symc  the SymConst
60  * @return name of the SymConst
61  */
62 const char *get_sc_name(ir_node *symc) {
63   if (get_irn_opcode(symc) != iro_SymConst)
64     return "NONE";
65
66   switch (get_SymConst_kind(symc)) {
67     case symconst_addr_name:
68       return get_id_str(get_SymConst_name(symc));
69
70     case symconst_addr_ent:
71       return get_entity_ld_name(get_SymConst_entity(symc));
72
73     default:
74       assert(0 && "Unsupported SymConst");
75   }
76 }
77
78 /**
79  * Dumper interface for dumping ia32 nodes in vcg.
80  * @param n        the node to dump
81  * @param F        the output file
82  * @param reason   indicates which kind of information should be dumped
83  * @return 0 on success or != 0 on failure
84  */
85 static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) {
86   const char *name, *p;
87   ir_mode    *mode = NULL;
88   int        bad   = 0;
89   asmop_attr *attr;
90   int        i;
91   const arch_register_req_t **reqs;
92   const arch_register_t     **slots;
93
94   switch (reason) {
95     case dump_node_opcode_txt:
96       name = get_irn_opname(n);
97       fprintf(F, "%s", name);
98       break;
99
100     case dump_node_mode_txt:
101       mode = get_irn_mode(n);
102
103       if (mode == mode_BB || mode == mode_ANY || mode == mode_BAD || mode == mode_T) {
104         mode = NULL;
105       }
106       else if (is_ia32_Load(n)) {
107         mode = get_irn_mode(get_irn_n(n, 1));
108       }
109       else if (is_ia32_Store(n)) {
110         mode = get_irn_mode(get_irn_n(n, 2));
111       }
112
113       if (mode)
114         fprintf(F, "[%s]", get_mode_name(mode));
115       break;
116
117     case dump_node_nodeattr_txt:
118       name = get_irn_opname(n);
119       p = name + strlen(name) - 2;
120       if ((p[0] == '_' && p[1] == 'i') || is_ia32_Const(n)) {
121         tarval *tv = get_ia32_Immop_tarval(n);
122         if (tv)
123           fprintf_tv(F, tv, 1);
124         else {
125           fprintf(F, "[SymC &%s]", get_sc_name(get_ia32_old_ir(n)));
126         }
127       }
128       else if (is_ia32_Call(n)) {
129         ir_node *sc = get_ia32_old_ir(get_ia32_old_ir(n));
130
131         fprintf(F, "&%s ", get_sc_name(sc));
132       }
133       break;
134
135     case dump_node_info_txt:
136       attr = get_ia32_attr(n);
137
138       /* dump IN requirements */
139       if (get_irn_arity(n) > 0) {
140         reqs = get_ia32_in_req(n);
141
142         if (reqs) {
143           for (i = 0; i < get_irn_arity(n); i++) {
144             if (reqs[i]->type != arch_register_req_type_none)
145               fprintf(F, "inreq[%d]=[%s]\n", i, reqs[i]->cls->name);
146             else
147               fprintf(F, "inreq[%d]=[none]\n", i);
148           }
149           fprintf(F, "\n");
150         }
151         else
152           fprintf(F, "NO IN REQS\n");
153       }
154
155       /* dump OUT requirements */
156       if (attr->n_res > 0) {
157         reqs = get_ia32_out_req(n);
158
159         if (reqs) {
160           for (i = 0; i < attr->n_res; i++) {
161             if (reqs[i]->type != arch_register_req_type_none)
162               fprintf(F, "outreq[%d]=[%s]\n", i, reqs[i]->cls->name);
163             else
164               fprintf(F, "outreq[%d]=[none]\n", i);
165           }
166         }
167         else
168           fprintf(F, "NO OUT REQS\n");
169       }
170
171       /* dump assigned registers */
172       slots = get_ia32_slots(n);
173       if (slots && attr->n_res > 0) {
174         for (i = 0; i < attr->n_res; i++) {
175           if (slots[i]) {
176             fprintf(F, "REG[%d]=[%s]\n", i, slots[i]->name);
177           }
178           else
179             fprintf(F, "REG[%d]=[none]\n", i);
180         }
181       }
182
183       /* special for LEA */
184       if (is_ia32_Lea(n)) {
185         tarval *o  = get_ia32_offs(n);
186         tarval *tv = get_ia32_Immop_tarval(n);
187
188         fprintf(F, "LEA ");
189         if (o)
190           fprintf_tv(F, o, 0);
191         fprintf(F, "(%s, %s", get_irn_opname(get_irn_n(n, 0)), get_irn_opname(get_irn_n(n, 1)));
192         if (tv) {
193           fprintf(F, ", ");
194           fprintf_tv(F, tv, 0);
195         }
196         fprintf(F, ")\n");
197       }
198       break;
199   }
200
201   return bad;
202 }
203
204
205
206 /***************************************************************************************************
207  *        _   _                   _       __        _                    _   _               _
208  *       | | | |                 | |     / /       | |                  | | | |             | |
209  *   __ _| |_| |_ _ __   ___  ___| |_   / /_ _  ___| |_   _ __ ___   ___| |_| |__   ___   __| |___
210  *  / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
211  * | (_| | |_| |_| |    \__ \  __/ |_ / / (_| |  __/ |_  | | | | | |  __/ |_| | | | (_) | (_| \__ \
212  *  \__,_|\__|\__|_|    |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
213  *                                        __/ |
214  *                                       |___/
215  ***************************************************************************************************/
216
217 /**
218  * Wraps get_irn_generic_attr() as it takes no const ir_node, so we need to do a cast.
219  * Firm was made by people hating const :-(
220  */
221 asmop_attr *get_ia32_attr(const ir_node *node) {
222   return (asmop_attr *)get_irn_generic_attr((ir_node *)node);
223 }
224
225 /**
226  * Return the tarval of an immediate operation or NULL in case of SymConst
227  */
228 tarval *get_ia32_Immop_tarval(const ir_node *node) {
229   asmop_attr *attr = get_ia32_attr(node);
230   if (attr->tp == asmop_Const)
231     return attr->tv;
232   else
233     return NULL;
234 }
235
236 /**
237  * Return the old_ir attribute.
238  */
239 ir_node *get_ia32_old_ir(const ir_node *node) {
240   asmop_attr *attr = get_ia32_attr(node);
241   return attr->old_ir;
242 }
243
244 /**
245  * Copy the attributes from an ia32_Const to an Immop (Add_i, Sub_i, ...) node
246  */
247 void set_ia32_Immop_attr(ir_node *node, ir_node *cnst) {
248   asmop_attr *na = get_ia32_attr(node);
249   asmop_attr *ca = get_ia32_attr(cnst);
250
251   assert(is_ia32_Const(cnst) && "Need ia32_Const to set Immop attr");
252
253   na->tp     = ca->tp;
254   na->tv     = ca->tv;
255   na->old_ir = ca->old_ir;
256 }
257
258 /**
259  * Copy the attributes from a Const to an ia32_Const
260  */
261 void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst) {
262   asmop_attr *attr = get_ia32_attr(ia32_cnst);
263
264   assert(is_ia32_Const(ia32_cnst) && "Need ia32_Const to set Const attr");
265
266   switch (get_irn_opcode(cnst)) {
267     case iro_Const:
268       attr->tp = asmop_Const;
269       attr->tv = get_Const_tarval(cnst);
270       break;
271     case iro_SymConst:
272       attr->tp     = asmop_SymConst;
273       attr->old_ir = calloc(1, sizeof(*cnst));
274       memcpy(attr->old_ir, cnst, sizeof(*cnst));
275       break;
276     case iro_Unknown:
277       assert(0 && "Unknown Const NYI");
278       break;
279     default:
280       assert(0 && "Cannot create ia32_Const for this opcode");
281   }
282 }
283
284 /**
285  * Sets the type of an ia32_Const.
286  */
287 void set_ia32_Const_type(ir_node *node, int type) {
288   asmop_attr *attr   = get_ia32_attr(node);
289
290   assert(is_ia32_Const(node) && "Need ia32_Const to set type");
291   assert((type == asmop_Const || type == asmop_SymConst) && "Unsupported ia32_Const type");
292
293   attr->tp = type;
294 }
295
296 /**
297  * Sets the attributes of an immediate operation to the specified tarval
298  */
299 void set_ia32_Immop_tarval(ir_node *node, tarval *tv) {
300   asmop_attr *attr = get_ia32_attr(node);
301
302   attr->tp = asmop_Const;
303   attr->tv = tv;
304 }
305
306 /**
307  * Sets the offset for a Lea.
308  */
309 void set_ia32_offs(ir_node *node, tarval *offs) {
310   asmop_attr *attr = get_ia32_attr(node);
311   attr->offset     = offs;
312 }
313
314 /**
315  * Gets the offset for a Lea.
316  */
317 tarval *get_ia32_offs(const ir_node *node) {
318   asmop_attr *attr = get_ia32_attr(node);
319   return attr->offset;
320 }
321
322 /**
323  * Returns the argument register requirements of an ia32 node.
324  */
325 const arch_register_req_t **get_ia32_in_req(const ir_node *node) {
326   asmop_attr *attr = get_ia32_attr(node);
327   return attr->in_req;
328 }
329
330 /**
331  * Returns the result register requirements of an ia32 node.
332  */
333 const arch_register_req_t **get_ia32_out_req(const ir_node *node) {
334   asmop_attr *attr = get_ia32_attr(node);
335   return attr->out_req;
336 }
337
338 /**
339  * Returns the register flag of an ia32 node.
340  */
341 arch_irn_flags_t get_ia32_flags(const ir_node *node) {
342   asmop_attr *attr = get_ia32_attr(node);
343   return attr->flags;
344 }
345
346 /**
347  * Returns the result register slots of an ia32 node.
348  */
349 const arch_register_t **get_ia32_slots(const ir_node *node) {
350   asmop_attr *attr = get_ia32_attr(node);
351   return attr->slots;
352 }
353
354 /**
355  * Returns the name of the IN register at position pos.
356  */
357 const char *get_ia32_in_reg_name(const ir_node *node, int pos) {
358   assert(0 && "in reg name not yet implemented");
359 }
360
361 /**
362  * Returns the name of the OUT register at position pos.
363  */
364 const char *get_ia32_out_reg_name(const ir_node *node, int pos) {
365   asmop_attr *attr = get_ia32_attr(node);
366
367   assert(is_ia32_irn(node) && "Not an ia32 node.");
368   assert(pos < attr->n_res && "Invalid OUT position.");
369
370   return attr->slots[pos]->name;
371 }
372
373 /**
374  * Returns the index of the IN register at position pos within its register class.
375  */
376 int get_ia32_in_regnr(const ir_node *node, int pos) {
377   assert(0 && "in reg nr not yet implemented");
378 }
379
380 /**
381  * Returns the index of the OUT register at position pos within its register class.
382  */
383 int get_ia32_out_regnr(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
389   return attr->slots[pos]->index;
390 }
391
392 /**
393  * Sets the number of results.
394  */
395 void set_ia32_n_res(ir_node *node, int n_res) {
396   asmop_attr *attr = get_ia32_attr(node);
397   attr->n_res = n_res;
398 }
399
400 /**
401  * Returns the number of results.
402  */
403 int get_ia32_n_res(const ir_node *node) {
404   asmop_attr *attr = get_ia32_attr(node);
405   return attr->n_res;
406 }
407
408 /**
409  * Sets the flavour of an ia32 DivMod node to flavour_Div/Mod/DivMod.
410  */
411 void set_ia32_DivMod_flavour(ir_node *node, divmod_flavour_t dm_flav) {
412   asmop_attr *attr = get_ia32_attr(node);
413   attr->dm_flav    = dm_flav;
414 }
415
416 /* include generated register allocator interface */
417 #include "gen_ia32_regalloc_if.c.inl"
418
419 /* Include the generated functions */
420 #include "gen_ia32_new_nodes.c.inl"