Explicitly initialize the is_load_store attribute.
[libfirm] / ir / be / arm / arm_new_nodes.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief  This file implements the creation of the architecture specific firm
23  *         opcodes and the corresponding node constructors for the arm
24  *         assembler irg.
25  * @author Oliver Richter, Tobias Gneist
26  * @version $Id$
27  */
28 #include "config.h"
29
30 #include <stdlib.h>
31 #include <stdbool.h>
32
33 #include "irprog_t.h"
34 #include "irgraph_t.h"
35 #include "irnode_t.h"
36 #include "irmode_t.h"
37 #include "ircons_t.h"
38 #include "iropt_t.h"
39 #include "irop.h"
40 #include "irvrfy_t.h"
41 #include "irprintf.h"
42 #include "xmalloc.h"
43
44 #include "../bearch.h"
45
46 #include "arm_nodes_attr.h"
47 #include "arm_new_nodes.h"
48 #include "arm_optimize.h"
49
50 #include "../beabi.h"
51 #include "bearch_arm_t.h"
52
53 const char *arm_get_fpa_imm_name(long imm_value)
54 {
55         static const char *fpa_imm[] = {
56                 "0",
57                 "1",
58                 "2",
59                 "3",
60                 "4",
61                 "5",
62                 "10",
63                 "0.5"
64         };
65         return fpa_imm[imm_value];
66 }
67
68 static bool arm_has_symconst_attr(const ir_node *node)
69 {
70         return is_arm_SymConst(node) || is_arm_FrameAddr(node) || is_arm_Bl(node);
71 }
72
73 static bool has_load_store_attr(const ir_node *node)
74 {
75         return is_arm_Ldr(node) || is_arm_Str(node) || is_arm_LinkLdrPC(node)
76                 || is_arm_Ldf(node) || is_arm_Stf(node);
77 }
78
79 static bool has_shifter_operand(const ir_node *node)
80 {
81         return is_arm_Add(node) || is_arm_And(node) || is_arm_Or(node)
82                 || is_arm_Eor(node) || is_arm_Bic(node) || is_arm_Sub(node)
83                 || is_arm_Rsb(node) || is_arm_Mov(node) || is_arm_Mvn(node)
84                 || is_arm_Cmp(node) || is_arm_Tst(node) || is_arm_LinkMovPC(node);
85 }
86
87 static bool has_cmp_attr(const ir_node *node)
88 {
89         return is_arm_Cmp(node) || is_arm_Tst(node);
90 }
91
92 static bool has_farith_attr(const ir_node *node)
93 {
94         return is_arm_Adf(node) || is_arm_Muf(node) || is_arm_Suf(node)
95             || is_arm_Dvf(node) || is_arm_Mvf(node) || is_arm_FltX(node);
96 }
97
98 /**
99  * Dumper interface for dumping arm nodes in vcg.
100  * @param F        the output file
101  * @param n        the node to dump
102  * @param reason   indicates which kind of information should be dumped
103  */
104 static void arm_dump_node(FILE *F, ir_node *n, dump_reason_t reason)
105 {
106         switch (reason) {
107         case dump_node_opcode_txt:
108                 fprintf(F, "%s", get_irn_opname(n));
109
110                 if (arm_has_symconst_attr(n)) {
111                         const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(n);
112                         if (attr->entity != NULL) {
113                                 fputc(' ', F);
114                                 fputs(get_entity_name(attr->entity), F);
115                         }
116                 }
117                 break;
118
119         case dump_node_mode_txt:
120                 /* mode isn't relevant in the backend */
121                 break;
122
123         case dump_node_nodeattr_txt:
124                 /* TODO: dump shift modifiers */
125                 break;
126
127         case dump_node_info_txt:
128                 arch_dump_reqs_and_registers(F, n);
129
130                 if (has_load_store_attr(n)) {
131                         const arm_load_store_attr_t *attr
132                                 = get_arm_load_store_attr_const(n);
133                         ir_fprintf(F, "load_store_mode = %+F\n", attr->load_store_mode);
134                         ir_fprintf(F, "entity = %+F\n", attr->entity);
135                         fprintf(F, "offset = %ld\n", attr->offset);
136                         fprintf(F, "is_frame_entity = %s\n",
137                                         attr->is_frame_entity ? "yes" : "no");
138                         fprintf(F, "entity_sign = %s\n",
139                                         attr->entity_sign ? "yes" : "no");
140                 }
141                 if (has_shifter_operand(n)) {
142                         const arm_shifter_operand_t *attr
143                                 = get_arm_shifter_operand_attr_const(n);
144                         switch (attr->shift_modifier) {
145                         case ARM_SHF_REG:
146                                 break;
147                         case ARM_SHF_IMM:
148                                 fprintf(F, "modifier = imm %d ror %d\n",
149                                                 attr->immediate_value, attr->shift_immediate);
150                                 break;
151                         case ARM_SHF_ASR_IMM:
152                                 fprintf(F, "modifier = V >>s %d\n", attr->shift_immediate);
153                                 break;
154                         case ARM_SHF_ASR_REG:
155                                 fprintf(F, "modifier = V >>s R\n");
156                                 break;
157                         case ARM_SHF_LSL_IMM:
158                                 fprintf(F, "modifier = V << %d\n", attr->shift_immediate);
159                                 break;
160                         case ARM_SHF_LSL_REG:
161                                 fprintf(F, "modifier = V << R\n");
162                                 break;
163                         case ARM_SHF_LSR_IMM:
164                                 fprintf(F, "modifier = V >> %d\n", attr->shift_immediate);
165                                 break;
166                         case ARM_SHF_LSR_REG:
167                                 fprintf(F, "modifier = V >> R\n");
168                                 break;
169                         case ARM_SHF_ROR_IMM:
170                                 fprintf(F, "modifier = V ROR %d\n", attr->shift_immediate);
171                                 break;
172                         case ARM_SHF_ROR_REG:
173                                 fprintf(F, "modifier = V ROR R\n");
174                                 break;
175                         case ARM_SHF_RRX:
176                                 fprintf(F, "modifier = RRX\n");
177                                 break;
178                         default:
179                         case ARM_SHF_INVALID:
180                                 fprintf(F, "modifier = INVALID SHIFT MODIFIER\n");
181                                 break;
182                         }
183                 }
184                 if (has_cmp_attr(n)) {
185                         const arm_cmp_attr_t *attr = get_arm_cmp_attr_const(n);
186                         fprintf(F, "cmp_attr =");
187                         if (attr->is_unsigned) {
188                                 fprintf(F, " unsigned");
189                         }
190                         if (attr->ins_permuted) {
191                                 fprintf(F, " inputs swapped");
192                         }
193                         fputc('\n', F);
194                 }
195                 if (arm_has_symconst_attr(n)) {
196                         const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(n);
197
198                         fprintf(F, "entity = ");
199                         if (attr->entity != NULL) {
200                                 fprintf(F, "'%s'", get_entity_name(attr->entity));
201                         } else {
202                                 fputs("NULL", F);
203                         }
204                         fputc('\n', F);
205                         fprintf(F, "frame offset = %d\n", attr->fp_offset);
206                 }
207                 if (has_farith_attr(n)) {
208                         const arm_farith_attr_t *attr = get_arm_farith_attr_const(n);
209                         ir_fprintf(F, "arithmetic mode = %+F\n", attr->mode);
210                 }
211                 break;
212         }
213 }
214
215 arm_attr_t *get_arm_attr(ir_node *node)
216 {
217         assert(is_arm_irn(node) && "need arm node to get attributes");
218         return get_irn_generic_attr(node);
219 }
220
221 const arm_attr_t *get_arm_attr_const(const ir_node *node)
222 {
223         assert(is_arm_irn(node) && "need arm node to get attributes");
224         return get_irn_generic_attr_const(node);
225 }
226
227 static bool has_symconst_attr(const ir_node *node)
228 {
229         return is_arm_SymConst(node) || is_arm_FrameAddr(node) || is_arm_Bl(node);
230 }
231
232 arm_SymConst_attr_t *get_arm_SymConst_attr(ir_node *node)
233 {
234         assert(has_symconst_attr(node));
235         return get_irn_generic_attr(node);
236 }
237
238 const arm_SymConst_attr_t *get_arm_SymConst_attr_const(const ir_node *node)
239 {
240         assert(has_symconst_attr(node));
241         return get_irn_generic_attr_const(node);
242 }
243
244 static const arm_fConst_attr_t *get_arm_fConst_attr_const(const ir_node *node)
245 {
246         assert(is_arm_fConst(node));
247         return get_irn_generic_attr_const(node);
248 }
249
250 static arm_fConst_attr_t *get_arm_fConst_attr(ir_node *node)
251 {
252         assert(is_arm_fConst(node));
253         return get_irn_generic_attr(node);
254 }
255
256 arm_farith_attr_t *get_arm_farith_attr(ir_node *node)
257 {
258         assert(has_farith_attr(node));
259         return get_irn_generic_attr(node);
260 }
261
262 const arm_farith_attr_t *get_arm_farith_attr_const(const ir_node *node)
263 {
264         assert(has_farith_attr(node));
265         return get_irn_generic_attr_const(node);
266 }
267
268 arm_CondJmp_attr_t *get_arm_CondJmp_attr(ir_node *node)
269 {
270         assert(is_arm_B(node));
271         return get_irn_generic_attr(node);
272 }
273
274 const arm_CondJmp_attr_t *get_arm_CondJmp_attr_const(const ir_node *node)
275 {
276         assert(is_arm_B(node));
277         return get_irn_generic_attr_const(node);
278 }
279
280 arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr(ir_node *node)
281 {
282         assert(is_arm_SwitchJmp(node));
283         return get_irn_generic_attr(node);
284 }
285
286 const arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr_const(const ir_node *node)
287 {
288         assert(is_arm_SwitchJmp(node));
289         return get_irn_generic_attr_const(node);
290 }
291
292 void set_arm_in_req_all(ir_node *node, const arch_register_req_t **reqs)
293 {
294         arm_attr_t *attr = get_arm_attr(node);
295         attr->in_req = reqs;
296 }
297
298 const arch_register_req_t *get_arm_in_req(const ir_node *node, int pos)
299 {
300         const arm_attr_t *attr = get_arm_attr_const(node);
301         return attr->in_req[pos];
302 }
303
304 void set_arm_req_in(ir_node *node, const arch_register_req_t *req, int pos)
305 {
306         arm_attr_t *attr  = get_arm_attr(node);
307         attr->in_req[pos] = req;
308 }
309
310 tarval *get_fConst_value(const ir_node *node)
311 {
312         const arm_fConst_attr_t *attr = get_arm_fConst_attr_const(node);
313         return attr->tv;
314 }
315
316 void set_fConst_value(ir_node *node, tarval *tv)
317 {
318         arm_fConst_attr_t *attr = get_arm_fConst_attr(node);
319         attr->tv = tv;
320 }
321
322 pn_Cmp get_arm_CondJmp_pnc(const ir_node *node)
323 {
324         const arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr_const(node);
325         return attr->pnc;
326 }
327
328 void set_arm_CondJmp_pnc(ir_node *node, pn_Cmp pnc)
329 {
330         arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr(node);
331         attr->pnc = pnc;
332 }
333
334 int get_arm_SwitchJmp_n_projs(const ir_node *node)
335 {
336         const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(node);
337         return attr->n_projs;
338 }
339
340 void set_arm_SwitchJmp_n_projs(ir_node *node, int n_projs)
341 {
342         arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(node);
343         attr->n_projs = n_projs;
344 }
345
346 long get_arm_SwitchJmp_default_proj_num(const ir_node *node)
347 {
348         const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(node);
349         return attr->default_proj_num;
350 }
351
352 void set_arm_SwitchJmp_default_proj_num(ir_node *node, long default_proj_num)
353 {
354         arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(node);
355         attr->default_proj_num = default_proj_num;
356 }
357
358 /* Set the ARM machine node attributes to default values. */
359 static void init_arm_attributes(ir_node *node, int flags,
360                          const arch_register_req_t ** in_reqs,
361                          const be_execution_unit_t ***execution_units,
362                                                  int n_res)
363 {
364         ir_graph       *irg  = get_irn_irg(node);
365         struct obstack *obst = get_irg_obstack(irg);
366         arm_attr_t     *attr = get_arm_attr(node);
367         backend_info_t *info;
368         (void) execution_units;
369
370         arch_irn_set_flags(node, flags);
371         attr->in_req           = in_reqs;
372         attr->is_load_store    = false;
373
374         info            = be_get_info(node);
375         info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_res);
376         memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
377 }
378
379 static void init_arm_load_store_attributes(ir_node *res, ir_mode *ls_mode,
380                                            ir_entity *entity,
381                                            int entity_sign, long offset,
382                                            bool is_frame_entity)
383 {
384         arm_load_store_attr_t *attr = get_irn_generic_attr(res);
385         attr->load_store_mode    = ls_mode;
386         attr->entity             = entity;
387         attr->entity_sign        = entity_sign;
388         attr->is_frame_entity    = is_frame_entity;
389         attr->offset             = offset;
390         attr->base.is_load_store = true;
391 }
392
393 static void init_arm_shifter_operand(ir_node *res, unsigned immediate_value,
394                                      arm_shift_modifier_t shift_modifier,
395                                      unsigned shift_immediate)
396 {
397         arm_shifter_operand_t *attr = get_irn_generic_attr(res);
398         attr->immediate_value = immediate_value;
399         attr->shift_modifier  = shift_modifier;
400         attr->shift_immediate = shift_immediate;
401 }
402
403 static void init_arm_cmp_attr(ir_node *res, bool ins_permuted, bool is_unsigned)
404 {
405         arm_cmp_attr_t *attr = get_irn_generic_attr(res);
406         attr->ins_permuted = ins_permuted;
407         attr->is_unsigned  = is_unsigned;
408 }
409
410 static void init_arm_SymConst_attributes(ir_node *res, ir_entity *entity,
411                                          int symconst_offset)
412 {
413         arm_SymConst_attr_t *attr = get_irn_generic_attr(res);
414         attr->entity    = entity;
415         attr->fp_offset = symconst_offset;
416 }
417
418 static void init_arm_farith_attributes(ir_node *res, ir_mode *mode)
419 {
420         arm_farith_attr_t *attr = get_irn_generic_attr(res);
421         attr->mode = mode;
422 }
423
424 static void init_arm_CopyB_attributes(ir_node *res, unsigned size)
425 {
426         arm_CopyB_attr_t *attr = get_irn_generic_attr(res);
427         attr->size = size;
428 }
429
430 static int cmp_attr_arm(ir_node *a, ir_node *b)
431 {
432         (void) a;
433         (void) b;
434         return 0;
435 }
436
437 static int cmp_attr_arm_SymConst(ir_node *a, ir_node *b)
438 {
439         const arm_SymConst_attr_t *attr_a;
440         const arm_SymConst_attr_t *attr_b;
441
442         if (cmp_attr_arm(a, b))
443                 return 1;
444
445         attr_a = get_irn_generic_attr_const(a);
446         attr_b = get_irn_generic_attr_const(b);
447         return attr_a->entity != attr_b->entity
448                 || attr_a->fp_offset != attr_b->fp_offset;
449 }
450
451 static int cmp_attr_arm_CopyB(ir_node *a, ir_node *b)
452 {
453         const arm_CopyB_attr_t *attr_a;
454         const arm_CopyB_attr_t *attr_b;
455
456         if (cmp_attr_arm(a, b))
457                 return 1;
458
459         attr_a = get_irn_generic_attr_const(a);
460         attr_b = get_irn_generic_attr_const(b);
461         return attr_a->size != attr_b->size;
462 }
463
464 static int cmp_attr_arm_CondJmp(ir_node *a, ir_node *b)
465 {
466         (void) a;
467         (void) b;
468         /* never identical */
469         return 1;
470 }
471
472 static int cmp_attr_arm_SwitchJmp(ir_node *a, ir_node *b)
473 {
474         (void) a;
475         (void) b;
476         /* never identical */
477         return 1;
478 }
479
480 static int cmp_attr_arm_fConst(ir_node *a, ir_node *b)
481 {
482         const arm_fConst_attr_t *attr_a;
483         const arm_fConst_attr_t *attr_b;
484
485         if (cmp_attr_arm(a, b))
486                 return 1;
487
488         attr_a = get_arm_fConst_attr_const(a);
489         attr_b = get_arm_fConst_attr_const(b);
490
491         return attr_a->tv != attr_b->tv;
492 }
493
494
495 arm_load_store_attr_t *get_arm_load_store_attr(ir_node *node)
496 {
497         return (arm_load_store_attr_t*) get_irn_generic_attr(node);
498 }
499
500 const arm_load_store_attr_t *get_arm_load_store_attr_const(const ir_node *node)
501 {
502         return (const arm_load_store_attr_t*) get_irn_generic_attr_const(node);
503 }
504
505 arm_shifter_operand_t *get_arm_shifter_operand_attr(ir_node *node)
506 {
507         return (arm_shifter_operand_t*) get_irn_generic_attr(node);
508 }
509
510 const arm_shifter_operand_t *get_arm_shifter_operand_attr_const(
511                 const ir_node *node)
512 {
513         return (const arm_shifter_operand_t*) get_irn_generic_attr_const(node);
514 }
515
516 arm_cmp_attr_t *get_arm_cmp_attr(ir_node *node)
517 {
518         return (arm_cmp_attr_t*) get_irn_generic_attr(node);
519 }
520
521 const arm_cmp_attr_t *get_arm_cmp_attr_const(const ir_node *node)
522 {
523         return (const arm_cmp_attr_t*) get_irn_generic_attr_const(node);
524 }
525
526 static int cmp_attr_arm_load_store(ir_node *a, ir_node *b)
527 {
528         const arm_load_store_attr_t *attr_a;
529         const arm_load_store_attr_t *attr_b;
530
531         if (cmp_attr_arm(a, b))
532                 return 1;
533
534         attr_a = get_arm_load_store_attr(a);
535         attr_b = get_arm_load_store_attr(b);
536         if (attr_a->entity != attr_b->entity
537                         || attr_a->entity_sign != attr_b->entity_sign
538                         || attr_a->offset != attr_b->offset)
539                 return 1;
540
541         return 0;
542 }
543
544 static int cmp_attr_arm_shifter_operand(ir_node *a, ir_node *b)
545 {
546         const arm_shifter_operand_t *attr_a;
547         const arm_shifter_operand_t *attr_b;
548
549         if (cmp_attr_arm(a, b))
550                 return 1;
551
552         attr_a = get_arm_shifter_operand_attr(a);
553         attr_b = get_arm_shifter_operand_attr(b);
554         if (attr_a->shift_modifier != attr_b->shift_modifier
555                         || attr_a->immediate_value != attr_b->immediate_value
556                         || attr_a->shift_immediate != attr_b->shift_immediate)
557                 return 1;
558
559         return 0;
560 }
561
562 static int cmp_attr_arm_cmp(ir_node *a, ir_node *b)
563 {
564         const arm_cmp_attr_t *attr_a;
565         const arm_cmp_attr_t *attr_b;
566
567         if (cmp_attr_arm(a, b))
568                 return 1;
569
570         attr_a = get_irn_generic_attr_const(a);
571         attr_b = get_irn_generic_attr_const(b);
572         if (attr_a->ins_permuted != attr_b->ins_permuted
573                         || attr_a->is_unsigned != attr_b->is_unsigned)
574                 return 1;
575         return 0;
576 }
577
578 static int cmp_attr_arm_farith(ir_node *a, ir_node *b)
579 {
580         const arm_farith_attr_t *attr_a;
581         const arm_farith_attr_t *attr_b;
582
583         if (cmp_attr_arm(a, b))
584                 return 1;
585
586         attr_a = get_arm_farith_attr_const(a);
587         attr_b = get_arm_farith_attr_const(b);
588         return attr_a->mode != attr_b->mode;
589 }
590
591 /** copies the ARM attributes of a node. */
592 static void arm_copy_attr(ir_graph *irg, const ir_node *old_node,
593                           ir_node *new_node)
594 {
595         struct obstack   *obst    = get_irg_obstack(irg);
596         const arm_attr_t *attr_old = get_arm_attr_const(old_node);
597         arm_attr_t       *attr_new = get_arm_attr(new_node);
598         backend_info_t   *old_info = be_get_info(old_node);
599         backend_info_t   *new_info = be_get_info(new_node);
600
601         /* copy the attributes */
602         memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));
603
604         /* copy out flags */
605         new_info->out_infos =
606                 DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
607 }
608
609
610 /* Include the generated constructor functions */
611 #include "gen_arm_new_nodes.c.inl"