cleanup and rewrite dumper interface
[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
32 #include "irprog_t.h"
33 #include "irgraph_t.h"
34 #include "irnode_t.h"
35 #include "irmode_t.h"
36 #include "ircons_t.h"
37 #include "iropt_t.h"
38 #include "irop.h"
39 #include "irvrfy_t.h"
40 #include "irprintf.h"
41 #include "xmalloc.h"
42
43 #include "../bearch.h"
44
45 #include "arm_nodes_attr.h"
46 #include "arm_new_nodes.h"
47 #include "arm_optimize.h"
48
49 #include "../beabi.h"
50 #include "bearch_arm_t.h"
51
52 /**
53  * Return the fpa immediate from the encoding.
54  */
55 const char *arm_get_fpa_imm_name(long imm_value)
56 {
57         static const char *fpa_imm[] = {
58                 "0",
59                 "1",
60                 "2",
61                 "3",
62                 "4",
63                 "5",
64                 "10",
65                 "0.5"
66         };
67         return fpa_imm[imm_value];
68 }
69
70
71 /**
72  * Dumper interface for dumping arm nodes in vcg.
73  * @param F        the output file
74  * @param n        the node to dump
75  * @param reason   indicates which kind of information should be dumped
76  */
77 static void arm_dump_node(FILE *F, ir_node *n, dump_reason_t reason)
78 {
79         ir_mode     *mode = NULL;
80         //arm_attr_t  *attr = get_arm_attr(n);
81
82         switch (reason) {
83                 case dump_node_opcode_txt:
84                         fprintf(F, "%s", get_irn_opname(n));
85                         break;
86
87                 case dump_node_mode_txt:
88                         mode = get_irn_mode(n);
89
90                         if (mode) {
91                                 fprintf(F, "[%s]", get_mode_name(mode));
92                         }
93                         else {
94                                 fprintf(F, "[?NOMODE?]");
95                         }
96                         break;
97
98                 case dump_node_nodeattr_txt:
99                         /* TODO: dump shift modifiers */
100                         break;
101
102                 case dump_node_info_txt:
103                         arch_dump_reqs_and_registers(F, n);
104
105                         if (is_arm_CopyB(n)) {
106                                 //fprintf(F, "size = %lu\n", get_arm_imm_value(n));
107                         } else {
108                                 /* TODO */
109 #if 0
110                                 long v =  get_arm_imm_value(n);
111                                 if (ARM_GET_FPA_IMM(attr)) {
112                                         fprintf(F, "immediate float value = %s\n", arm_get_fpa_imm_name(v));
113                                 } else {
114                                         fprintf(F, "immediate value = %ld (0x%08lx)\n", v, v);
115                                 }
116 #endif
117                         }
118
119 #if 0
120                         if (is_arm_CmpBra(n) && get_arm_CondJmp_proj_num(n) >= 0) {
121                                 fprintf(F, "proj_num = (%d)\n", get_arm_CondJmp_proj_num(n));
122                         }
123 #endif
124                         break;
125         }
126 }
127
128
129 /* Returns the attributes of a generic Arm node. */
130 arm_attr_t *get_arm_attr(ir_node *node)
131 {
132         assert(is_arm_irn(node) && "need arm node to get attributes");
133         return get_irn_generic_attr(node);
134 }
135
136 const arm_attr_t *get_arm_attr_const(const ir_node *node)
137 {
138         assert(is_arm_irn(node) && "need arm node to get attributes");
139         return get_irn_generic_attr_const(node);
140 }
141
142 /**
143  * Returns the attributes of an ARM SymConst node.
144  */
145 arm_SymConst_attr_t *get_arm_SymConst_attr(ir_node *node)
146 {
147         assert(is_arm_SymConst(node) || is_arm_FrameAddr(node));
148         return get_irn_generic_attr(node);
149 }
150
151 const arm_SymConst_attr_t *get_arm_SymConst_attr_const(const ir_node *node)
152 {
153         assert(is_arm_SymConst(node) || is_arm_FrameAddr(node));
154         return get_irn_generic_attr_const(node);
155 }
156
157 static const arm_fpaConst_attr_t *get_arm_fpaConst_attr_const(const ir_node *node)
158 {
159         const arm_attr_t          *attr     = get_arm_attr_const(node);
160         const arm_fpaConst_attr_t *fpa_attr = CONST_CAST_ARM_ATTR(arm_fpaConst_attr_t, attr);
161
162         return fpa_attr;
163 }
164
165 static arm_fpaConst_attr_t *get_arm_fpaConst_attr(ir_node *node)
166 {
167         arm_attr_t          *attr     = get_arm_attr(node);
168         arm_fpaConst_attr_t *fpa_attr = CAST_ARM_ATTR(arm_fpaConst_attr_t, attr);
169
170         return fpa_attr;
171 }
172
173 /* Returns the attributes of a CondJmp node. */
174 arm_CondJmp_attr_t *get_arm_CondJmp_attr(ir_node *node)
175 {
176         assert(is_arm_B(node));
177         return get_irn_generic_attr(node);
178 }
179
180 const arm_CondJmp_attr_t *get_arm_CondJmp_attr_const(const ir_node *node)
181 {
182         assert(is_arm_B(node));
183         return get_irn_generic_attr_const(node);
184 }
185
186 /* Returns the attributes of a SwitchJmp node. */
187 arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr(ir_node *node)
188 {
189         assert(is_arm_SwitchJmp(node));
190         return get_irn_generic_attr(node);
191 }
192
193 const arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr_const(const ir_node *node)
194 {
195         assert(is_arm_SwitchJmp(node));
196         return get_irn_generic_attr_const(node);
197 }
198
199 /**
200  * Returns the argument register requirements of a arm node.
201  */
202 const arch_register_req_t **get_arm_in_req_all(const ir_node *node)
203 {
204         const arm_attr_t *attr = get_arm_attr_const(node);
205         return attr->in_req;
206 }
207
208 /**
209  * Returns the argument register requirement at position pos of an arm node.
210  */
211 const arch_register_req_t *get_arm_in_req(const ir_node *node, int pos)
212 {
213         const arm_attr_t *attr = get_arm_attr_const(node);
214         return attr->in_req[pos];
215 }
216
217 /**
218  * Sets the IN register requirements at position pos.
219  */
220 void set_arm_req_in(ir_node *node, const arch_register_req_t *req, int pos)
221 {
222         arm_attr_t *attr  = get_arm_attr(node);
223         attr->in_req[pos] = req;
224 }
225
226 /**
227  * Returns the fpaConst value
228  */
229 tarval *get_fpaConst_value(const ir_node *node)
230 {
231         const arm_fpaConst_attr_t *attr = get_arm_fpaConst_attr_const(node);
232         return attr->tv;
233 }
234
235 /**
236  * Sets the tarval value
237  */
238 void set_fpaConst_value(ir_node *node, tarval *tv)
239 {
240         arm_fpaConst_attr_t *attr = get_arm_fpaConst_attr(node);
241         attr->tv = tv;
242 }
243
244 /**
245  * Returns the proj num
246  */
247 int get_arm_CondJmp_proj_num(const ir_node *node)
248 {
249         const arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr_const(node);
250         return attr->proj_num;
251 }
252
253 /**
254  * Sets the proj num
255  */
256 void set_arm_CondJmp_proj_num(ir_node *node, int proj_num)
257 {
258         arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr(node);
259         attr->proj_num   = proj_num;
260 }
261
262 /**
263  * Returns the number of projs of a SwitchJmp.
264  */
265 int get_arm_SwitchJmp_n_projs(const ir_node *node)
266 {
267         const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(node);
268         return attr->n_projs;
269 }
270
271 /**
272  * Sets the number of projs.
273  */
274 void set_arm_SwitchJmp_n_projs(ir_node *node, int n_projs)
275 {
276         arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(node);
277         attr->n_projs = n_projs;
278 }
279
280 /**
281  * Returns the default_proj_num.
282  */
283 long get_arm_SwitchJmp_default_proj_num(const ir_node *node)
284 {
285         const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(node);
286         return attr->default_proj_num;
287 }
288
289 /**
290  * Sets the default_proj_num.
291  */
292 void set_arm_SwitchJmp_default_proj_num(ir_node *node, long default_proj_num)
293 {
294         arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(node);
295         attr->default_proj_num = default_proj_num;
296 }
297
298 /* Set the ARM machine node attributes to default values. */
299 static void init_arm_attributes(ir_node *node, int flags,
300                          const arch_register_req_t ** in_reqs,
301                          const be_execution_unit_t ***execution_units,
302                                                  int n_res)
303 {
304         ir_graph       *irg  = get_irn_irg(node);
305         struct obstack *obst = get_irg_obstack(irg);
306         arm_attr_t     *attr = get_arm_attr(node);
307         backend_info_t *info;
308         (void) execution_units;
309
310         arch_irn_set_flags(node, flags);
311         attr->in_req           = in_reqs;
312         attr->instr_fl         = 0;
313
314         info            = be_get_info(node);
315         info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_res);
316         memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
317 }
318
319 static void init_arm_load_store_attributes(ir_node *res, ir_mode *ls_mode,
320                                            ir_entity *entity,
321                                            int entity_sign, long offset,
322                                            bool is_frame_entity)
323 {
324         arm_load_store_attr_t *attr = get_irn_generic_attr(res);
325         attr->load_store_mode    = ls_mode;
326         attr->entity             = entity;
327         attr->entity_sign        = entity_sign;
328         attr->is_frame_entity    = is_frame_entity;
329         attr->offset             = offset;
330         attr->base.is_load_store = true;
331 }
332
333 static void init_arm_shifter_operand(ir_node *res, unsigned immediate_value,
334                                      arm_shift_modifier shift_modifier,
335                                      unsigned shift_immediate)
336 {
337         arm_shifter_operand_t *attr = get_irn_generic_attr(res);
338         attr->immediate_value = immediate_value;
339         attr->shift_modifier  = shift_modifier;
340         attr->shift_immediate = shift_immediate;
341 }
342
343 static void init_arm_cmp_attr(ir_node *res, bool ins_permuted, bool is_unsigned)
344 {
345         arm_cmp_attr_t *attr = get_irn_generic_attr(res);
346         attr->ins_permuted = ins_permuted;
347         attr->is_unsigned  = is_unsigned;
348 }
349
350 static void init_arm_SymConst_attributes(ir_node *res, ir_entity *entity)
351 {
352         arm_SymConst_attr_t *attr = get_irn_generic_attr(res);
353         attr->entity    = entity;
354         attr->fp_offset = 0;
355 }
356
357 static void init_arm_CopyB_attributes(ir_node *res, unsigned size)
358 {
359         arm_CopyB_attr_t *attr = get_irn_generic_attr(res);
360         attr->size = size;
361 }
362
363 static int cmp_attr_arm(ir_node *a, ir_node *b)
364 {
365         arm_attr_t *attr_a = get_irn_generic_attr(a);
366         arm_attr_t *attr_b = get_irn_generic_attr(b);
367         return attr_a->instr_fl != attr_b->instr_fl;
368 }
369
370 static int cmp_attr_arm_SymConst(ir_node *a, ir_node *b)
371 {
372         const arm_SymConst_attr_t *attr_a;
373         const arm_SymConst_attr_t *attr_b;
374
375         if (cmp_attr_arm(a, b))
376                 return 1;
377
378         attr_a = get_irn_generic_attr_const(a);
379         attr_b = get_irn_generic_attr_const(b);
380         return attr_a->entity != attr_b->entity
381                 || attr_a->fp_offset != attr_b->fp_offset;
382 }
383
384 static int cmp_attr_arm_CopyB(ir_node *a, ir_node *b)
385 {
386         const arm_CopyB_attr_t *attr_a;
387         const arm_CopyB_attr_t *attr_b;
388
389         if (cmp_attr_arm(a, b))
390                 return 1;
391
392         attr_a = get_irn_generic_attr_const(a);
393         attr_b = get_irn_generic_attr_const(b);
394         return attr_a->size != attr_b->size;
395 }
396
397 static int cmp_attr_arm_CondJmp(ir_node *a, ir_node *b)
398 {
399         (void) a;
400         (void) b;
401         /* never identical */
402         return 1;
403 }
404
405 static int cmp_attr_arm_SwitchJmp(ir_node *a, ir_node *b)
406 {
407         (void) a;
408         (void) b;
409         /* never identical */
410         return 1;
411 }
412
413 static int cmp_attr_arm_fpaConst(ir_node *a, ir_node *b)
414 {
415         const arm_fpaConst_attr_t *attr_a;
416         const arm_fpaConst_attr_t *attr_b;
417
418         if (cmp_attr_arm(a, b))
419                 return 1;
420
421         attr_a = get_arm_fpaConst_attr_const(a);
422         attr_b = get_arm_fpaConst_attr_const(b);
423
424         return attr_a->tv != attr_b->tv;
425 }
426
427
428 arm_load_store_attr_t *get_arm_load_store_attr(ir_node *node)
429 {
430         return (arm_load_store_attr_t*) get_irn_generic_attr(node);
431 }
432
433 const arm_load_store_attr_t *get_arm_load_store_attr_const(const ir_node *node)
434 {
435         return (const arm_load_store_attr_t*) get_irn_generic_attr_const(node);
436 }
437
438 arm_shifter_operand_t *get_arm_shifter_operand_attr(ir_node *node)
439 {
440         return (arm_shifter_operand_t*) get_irn_generic_attr(node);
441 }
442
443 static int cmp_attr_arm_load_store(ir_node *a, ir_node *b)
444 {
445         const arm_load_store_attr_t *attr_a;
446         const arm_load_store_attr_t *attr_b;
447
448         if (cmp_attr_arm(a, b))
449                 return 1;
450
451         attr_a = get_arm_load_store_attr(a);
452         attr_b = get_arm_load_store_attr(b);
453         if (attr_a->entity != attr_b->entity
454                         || attr_a->entity_sign != attr_b->entity_sign
455                         || attr_a->offset != attr_b->offset)
456                 return 1;
457
458         return 0;
459 }
460
461 static int cmp_attr_arm_shifter_operand(ir_node *a, ir_node *b)
462 {
463         const arm_shifter_operand_t *attr_a;
464         const arm_shifter_operand_t *attr_b;
465
466         if (cmp_attr_arm(a, b))
467                 return 1;
468
469         attr_a = get_arm_shifter_operand_attr(a);
470         attr_b = get_arm_shifter_operand_attr(b);
471         if (attr_a->shift_modifier != attr_b->shift_modifier
472                         || attr_a->immediate_value != attr_b->immediate_value
473                         || attr_a->shift_immediate != attr_b->shift_immediate)
474                 return 1;
475
476         return 0;
477 }
478
479 static int cmp_attr_arm_cmp(ir_node *a, ir_node *b)
480 {
481         const arm_cmp_attr_t *attr_a;
482         const arm_cmp_attr_t *attr_b;
483
484         if (cmp_attr_arm(a, b))
485                 return 1;
486
487         attr_a = get_irn_generic_attr_const(a);
488         attr_b = get_irn_generic_attr_const(b);
489         if (attr_a->ins_permuted != attr_b->ins_permuted
490                         || attr_a->is_unsigned != attr_b->is_unsigned)
491                 return 1;
492         return 0;
493 }
494
495 /** copies the ARM attributes of a node. */
496 static void arm_copy_attr(ir_graph *irg, const ir_node *old_node,
497                           ir_node *new_node)
498 {
499         struct obstack   *obst    = get_irg_obstack(irg);
500         const arm_attr_t *attr_old = get_arm_attr_const(old_node);
501         arm_attr_t       *attr_new = get_arm_attr(new_node);
502         backend_info_t   *old_info = be_get_info(old_node);
503         backend_info_t   *new_info = be_get_info(new_node);
504
505         /* copy the attributes */
506         memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));
507
508         /* copy out flags */
509         new_info->out_infos =
510                 DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
511 }
512
513
514
515 /* Include the generated constructor functions */
516 #include "gen_arm_new_nodes.c.inl"