added doxygen comments
[libfirm] / ir / be / benode.c
1 /*
2  * Copyright (C) 1995-2007 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       Backend node support for generic backend nodes.
23  * @author      Sebastian Hack
24  * @date        17.05.2005
25  * @version     $Id$
26  *
27  * Backend node support for generic backend nodes.
28  * This file provides Perm, Copy, Spill and Reload nodes.
29  */
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include <stdlib.h>
35
36 #include "obst.h"
37 #include "set.h"
38 #include "pmap.h"
39 #include "util.h"
40 #include "debug.h"
41 #include "fourcc.h"
42 #include "offset.h"
43 #include "bitfiddle.h"
44 #include "raw_bitset.h"
45
46 #include "irop_t.h"
47 #include "irmode_t.h"
48 #include "irnode_t.h"
49 #include "ircons_t.h"
50 #include "irprintf.h"
51 #include "irgwalk.h"
52 #include "iropt_t.h"
53
54 #include "be_t.h"
55 #include "belive_t.h"
56 #include "besched_t.h"
57 #include "benode_t.h"
58
59 #include "beirgmod.h"
60
61 #define OUT_POS(x) (-((x) + 1))
62
63 /* Sometimes we want to put const nodes into get_irn_generic_attr ... */
64 #define get_irn_attr(irn) get_irn_generic_attr((ir_node *) (irn))
65
66 static unsigned be_node_tag = FOURCC('B', 'E', 'N', 'O');
67
68 typedef struct {
69         arch_register_req_t req;
70         arch_irn_flags_t    flags;
71 } be_req_t;
72
73 typedef struct {
74         const arch_register_t *reg;
75         be_req_t req;
76         be_req_t in_req;
77 } be_reg_data_t;
78
79 /** The generic be nodes attribute type. */
80 typedef struct {
81         be_reg_data_t         *reg_data;
82 } be_node_attr_t;
83
84 /** The be_Return nodes attribute type. */
85 typedef struct {
86         be_node_attr_t node_attr;
87         int            num_ret_vals;  /**< number of return values */
88 } be_return_attr_t;
89
90 /** The be_Stack attribute type. */
91 typedef struct {
92         be_node_attr_t node_attr;
93         int offset;           /**< The offset by which the stack shall be expanded/shrinked. */
94 } be_stack_attr_t;
95
96 /** The be_Frame attribute type. */
97 typedef struct {
98         be_node_attr_t node_attr;
99         ir_entity *ent;
100         int offset;
101 } be_frame_attr_t;
102
103 /** The be_Call attribute type. */
104 typedef struct {
105         be_node_attr_t node_attr;
106         ir_entity *ent;      /**< The called entity if this is a static call. */
107         ir_type *call_tp;    /**< The call type, copied from the original Call node. */
108 } be_call_attr_t;
109
110 typedef struct {
111         be_node_attr_t node_attr;
112         ir_entity **in_entities;
113         ir_entity **out_entities;
114 } be_memperm_attr_t;
115
116 ir_op *op_be_Spill;
117 ir_op *op_be_Reload;
118 ir_op *op_be_Perm;
119 ir_op *op_be_MemPerm;
120 ir_op *op_be_Copy;
121 ir_op *op_be_Keep;
122 ir_op *op_be_CopyKeep;
123 ir_op *op_be_Call;
124 ir_op *op_be_Return;
125 ir_op *op_be_IncSP;
126 ir_op *op_be_AddSP;
127 ir_op *op_be_SubSP;
128 ir_op *op_be_SetSP;
129 ir_op *op_be_RegParams;
130 ir_op *op_be_StackParam;
131 ir_op *op_be_FrameAddr;
132 ir_op *op_be_FrameLoad;
133 ir_op *op_be_FrameStore;
134 ir_op *op_be_Barrier;
135
136 static int beo_base = -1;
137
138 static const ir_op_ops be_node_op_ops;
139
140 #define N   irop_flag_none
141 #define L   irop_flag_labeled
142 #define C   irop_flag_commutative
143 #define X   irop_flag_cfopcode
144 #define I   irop_flag_ip_cfopcode
145 #define F   irop_flag_fragile
146 #define Y   irop_flag_forking
147 #define H   irop_flag_highlevel
148 #define c   irop_flag_constlike
149 #define K   irop_flag_keep
150 #define M   irop_flag_machine
151
152
153 /**
154  * Compare two node attributes.
155  *
156  * @return zero if both attributes are identically
157  */
158 static int cmp_node_attr(be_node_attr_t *a, be_node_attr_t *b) {
159         int i, len;
160
161         if(ARR_LEN(a->reg_data) != ARR_LEN(b->reg_data))
162                 return 1;
163
164         len = ARR_LEN(a->reg_data);
165         for (i = 0; i < len; ++i) {
166                 if (a->reg_data[i].reg != b->reg_data[i].reg ||
167                                 memcmp(&a->reg_data[i].in_req, &b->reg_data[i].in_req, sizeof(b->reg_data[i].in_req)) ||
168                             memcmp(&a->reg_data[i].req,    &b->reg_data[i].req,    sizeof(a->reg_data[i].req)))
169                         return 1;
170         }
171
172         return 0;
173 }
174
175 /**
176  * Compare the attributes of two FrameAddr nodes.
177  *
178  * @return zero if both attributes are identically
179  */
180 static int FrameAddr_cmp_attr(ir_node *a, ir_node *b) {
181         be_frame_attr_t *a_attr = get_irn_attr(a);
182         be_frame_attr_t *b_attr = get_irn_attr(b);
183
184         if (a_attr->ent == b_attr->ent && a_attr->offset == b_attr->offset)
185                 return cmp_node_attr(&a_attr->node_attr, &b_attr->node_attr);
186         return 1;
187 }
188
189 static INLINE be_req_t *get_be_req(const ir_node *node, int pos)
190 {
191         int idx;
192         be_node_attr_t *attr;
193         be_reg_data_t *rd;
194
195         assert(is_be_node(node));
196         attr = get_irn_attr(node);
197
198         if(pos < 0) {
199                 idx = -(pos + 1);
200         } else {
201                 idx = pos;
202                 assert(idx < get_irn_arity(node));
203         }
204         assert(idx < ARR_LEN(attr->reg_data));
205         rd = &attr->reg_data[idx];
206
207         return pos < 0 ? &rd->req : &rd->in_req;
208 }
209
210 static INLINE arch_register_req_t *get_req(const ir_node *node, int pos)
211 {
212         be_req_t *bereq = get_be_req(node, pos);
213         return &bereq->req;
214 }
215
216 void be_node_init(void) {
217         static int inited = 0;
218
219         if(inited)
220                 return;
221
222         inited = 1;
223
224         /* Acquire all needed opcodes. */
225         beo_base = get_next_ir_opcodes(beo_Last - 1);
226
227         op_be_Spill      = new_ir_op(beo_base + beo_Spill,      "be_Spill",      op_pin_state_mem_pinned, N, oparity_unary,    0, sizeof(be_frame_attr_t),   &be_node_op_ops);
228         op_be_Reload     = new_ir_op(beo_base + beo_Reload,     "be_Reload",     op_pin_state_mem_pinned, N, oparity_zero,     0, sizeof(be_frame_attr_t),   &be_node_op_ops);
229         op_be_Perm       = new_ir_op(beo_base + beo_Perm,       "be_Perm",       op_pin_state_pinned,     N, oparity_variable, 0, sizeof(be_node_attr_t),    &be_node_op_ops);
230         op_be_MemPerm    = new_ir_op(beo_base + beo_MemPerm,    "be_MemPerm",    op_pin_state_mem_pinned, N, oparity_variable, 0, sizeof(be_memperm_attr_t), &be_node_op_ops);
231         op_be_Copy       = new_ir_op(beo_base + beo_Copy,       "be_Copy",       op_pin_state_floats,     N, oparity_unary,    0, sizeof(be_node_attr_t),    &be_node_op_ops);
232         op_be_Keep       = new_ir_op(beo_base + beo_Keep,       "be_Keep",       op_pin_state_pinned,     K, oparity_dynamic,  0, sizeof(be_node_attr_t),    &be_node_op_ops);
233         op_be_CopyKeep   = new_ir_op(beo_base + beo_CopyKeep,   "be_CopyKeep",   op_pin_state_pinned,     K, oparity_variable, 0, sizeof(be_node_attr_t),    &be_node_op_ops);
234         op_be_Call       = new_ir_op(beo_base + beo_Call,       "be_Call",       op_pin_state_pinned,     F, oparity_variable, 0, sizeof(be_call_attr_t),    &be_node_op_ops);
235         op_be_Return     = new_ir_op(beo_base + beo_Return,     "be_Return",     op_pin_state_pinned,     X, oparity_dynamic,  0, sizeof(be_return_attr_t),  &be_node_op_ops);
236         op_be_AddSP      = new_ir_op(beo_base + beo_AddSP,      "be_AddSP",      op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_node_attr_t),    &be_node_op_ops);
237         op_be_SubSP      = new_ir_op(beo_base + beo_SubSP,      "be_SubSP",      op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_node_attr_t),    &be_node_op_ops);
238         op_be_SetSP      = new_ir_op(beo_base + beo_SetSP,      "be_SetSP",      op_pin_state_pinned,     N, oparity_binary,   0, sizeof(be_stack_attr_t),   &be_node_op_ops);
239         op_be_IncSP      = new_ir_op(beo_base + beo_IncSP,      "be_IncSP",      op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_stack_attr_t),   &be_node_op_ops);
240         op_be_RegParams  = new_ir_op(beo_base + beo_RegParams,  "be_RegParams",  op_pin_state_pinned,     N, oparity_zero,     0, sizeof(be_node_attr_t),    &be_node_op_ops);
241         op_be_StackParam = new_ir_op(beo_base + beo_StackParam, "be_StackParam", op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_frame_attr_t),   &be_node_op_ops);
242         op_be_FrameAddr  = new_ir_op(beo_base + beo_FrameAddr,  "be_FrameAddr",  op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_frame_attr_t),   &be_node_op_ops);
243         op_be_FrameLoad  = new_ir_op(beo_base + beo_FrameLoad,  "be_FrameLoad",  op_pin_state_pinned,     N, oparity_any,      0, sizeof(be_frame_attr_t),   &be_node_op_ops);
244         op_be_FrameStore = new_ir_op(beo_base + beo_FrameStore, "be_FrameStore", op_pin_state_pinned,     N, oparity_any,      0, sizeof(be_frame_attr_t),   &be_node_op_ops);
245         op_be_Barrier    = new_ir_op(beo_base + beo_Barrier,    "be_Barrier",    op_pin_state_pinned,     N, oparity_dynamic,  0, sizeof(be_node_attr_t),    &be_node_op_ops);
246
247         set_op_tag(op_be_Spill,      &be_node_tag);
248         set_op_tag(op_be_Reload,     &be_node_tag);
249         set_op_tag(op_be_Perm,       &be_node_tag);
250         set_op_tag(op_be_MemPerm,    &be_node_tag);
251         set_op_tag(op_be_Copy,       &be_node_tag);
252         set_op_tag(op_be_Keep,       &be_node_tag);
253         set_op_tag(op_be_CopyKeep,   &be_node_tag);
254         set_op_tag(op_be_Call,       &be_node_tag);
255         set_op_tag(op_be_Return,     &be_node_tag);
256         set_op_tag(op_be_AddSP,      &be_node_tag);
257         set_op_tag(op_be_SubSP,      &be_node_tag);
258         set_op_tag(op_be_SetSP,      &be_node_tag);
259         set_op_tag(op_be_IncSP,      &be_node_tag);
260         set_op_tag(op_be_RegParams,  &be_node_tag);
261         set_op_tag(op_be_StackParam, &be_node_tag);
262         set_op_tag(op_be_FrameLoad,  &be_node_tag);
263         set_op_tag(op_be_FrameStore, &be_node_tag);
264         set_op_tag(op_be_FrameAddr,  &be_node_tag);
265         set_op_tag(op_be_Barrier,    &be_node_tag);
266
267         op_be_FrameAddr->ops.node_cmp_attr = FrameAddr_cmp_attr;
268 }
269
270 /**
271  * Initializes the generic attribute of all be nodes and return ir.
272  */
273 static void *init_node_attr(ir_node *node, int max_reg_data)
274 {
275         ir_graph *irg = get_irn_irg(node);
276         struct obstack *obst = get_irg_obstack(irg);
277         be_node_attr_t *a = get_irn_attr(node);
278
279         memset(a, 0, sizeof(get_op_attr_size(get_irn_op(node))));
280
281         if(max_reg_data >= 0) {
282                 a->reg_data = NEW_ARR_D(be_reg_data_t, obst, max_reg_data);
283                 memset(a->reg_data, 0, max_reg_data * sizeof(a->reg_data[0]));
284         } else {
285                 a->reg_data = NEW_ARR_F(be_reg_data_t, 0);
286         }
287
288         return a;
289 }
290
291 static void add_register_req(ir_node *node)
292 {
293         be_node_attr_t *a = get_irn_attr(node);
294         be_reg_data_t regreq;
295         memset(&regreq, 0, sizeof(regreq));
296         ARR_APP1(be_reg_data_t, a->reg_data, regreq);
297 }
298
299 int is_be_node(const ir_node *irn)
300 {
301         return get_op_tag(get_irn_op(irn)) == &be_node_tag;
302 }
303
304 be_opcode_t be_get_irn_opcode(const ir_node *irn)
305 {
306         return is_be_node(irn) ? get_irn_opcode(irn) - beo_base : beo_NoBeOp;
307 }
308
309 /**
310  * Skip Proj nodes and return their Proj numbers.
311  *
312  * If *node is a Proj or Proj(Proj) node, skip it.
313  *
314  * @param node  points to the node to be skipped
315  *
316  * @return 0 if *node was no Proj node, its Proj number else.
317  */
318 static int redir_proj(const ir_node **node)
319 {
320         const ir_node *n = *node;
321
322         if(is_Proj(n)) {
323                 ir_node *irn;
324
325                 *node = irn = get_Proj_pred(n);
326                 if(is_Proj(irn)) {
327                         assert(get_irn_mode(irn) == mode_T);
328                         *node = get_Proj_pred(irn);
329                 }
330                 return get_Proj_proj(n);
331         }
332
333         return 0;
334 }
335
336 static be_reg_data_t *retrieve_reg_data(const ir_node *node)
337 {
338         be_node_attr_t *attr;
339         int pos = 0;
340
341         if(is_Proj(node)) {
342                 pos = get_Proj_proj(node);
343                 node = get_Proj_pred(node);
344         }
345
346         assert(is_be_node(node));
347         attr = get_irn_attr(node);
348         assert(pos >= 0 && pos < ARR_LEN(attr->reg_data) && "illegal proj number");
349
350         return &attr->reg_data[pos];
351 }
352
353 static void
354 be_node_set_irn_reg(const void *_self, ir_node *irn, const arch_register_t *reg)
355 {
356         be_reg_data_t *r = retrieve_reg_data(irn);
357         r->reg = reg;
358 }
359
360 ir_node *be_new_Spill(const arch_register_class_t *cls, const arch_register_class_t *cls_frame,
361         ir_graph *irg, ir_node *bl, ir_node *frame, ir_node *to_spill)
362 {
363         be_frame_attr_t *a;
364         ir_node         *in[2];
365         ir_node         *res;
366
367         in[0]     = frame;
368         in[1]     = to_spill;
369         res       = new_ir_node(NULL, irg, bl, op_be_Spill, mode_M, 2, in);
370         a         = init_node_attr(res, 2);
371         a->ent    = NULL;
372         a->offset = 0;
373
374         be_node_set_reg_class(res, be_pos_Spill_frame, cls_frame);
375         be_node_set_reg_class(res, be_pos_Spill_val, cls);
376         return res;
377 }
378
379 ir_node *be_new_Reload(const arch_register_class_t *cls, const arch_register_class_t *cls_frame,
380         ir_graph *irg, ir_node *bl, ir_node *frame, ir_node *mem, ir_mode *mode)
381 {
382         ir_node *in[2];
383         ir_node *res;
384
385         in[0] = frame;
386         in[1] = mem;
387         res   = new_ir_node(NULL, irg, bl, op_be_Reload, mode, 2, in);
388
389         init_node_attr(res, 2);
390         be_node_set_reg_class(res, -1, cls);
391         be_node_set_reg_class(res, be_pos_Reload_frame, cls_frame);
392         be_node_set_flags(res, -1, arch_irn_flags_rematerializable);
393         return res;
394 }
395
396 ir_node *be_get_Reload_mem(const ir_node *irn)
397 {
398         assert(be_is_Reload(irn));
399         return get_irn_n(irn, be_pos_Reload_mem);
400 }
401
402 ir_node *be_get_Reload_frame(const ir_node *irn)
403 {
404         assert(be_is_Reload(irn));
405         return get_irn_n(irn, be_pos_Reload_frame);
406 }
407
408 ir_node *be_get_Spill_val(const ir_node *irn)
409 {
410         assert(be_is_Spill(irn));
411         return get_irn_n(irn, be_pos_Spill_val);
412 }
413
414 ir_node *be_get_Spill_frame(const ir_node *irn)
415 {
416         assert(be_is_Spill(irn));
417         return get_irn_n(irn, be_pos_Spill_frame);
418 }
419
420 ir_node *be_new_Perm(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, int n, ir_node *in[])
421 {
422         int i;
423         ir_node *irn = new_ir_node(NULL, irg, bl, op_be_Perm, mode_T, n, in);
424         init_node_attr(irn, n);
425         for(i = 0; i < n; ++i) {
426                 be_node_set_reg_class(irn, i, cls);
427                 be_node_set_reg_class(irn, OUT_POS(i), cls);
428         }
429
430         return irn;
431 }
432
433 ir_node *be_new_MemPerm(const arch_env_t *arch_env, ir_graph *irg, ir_node *bl, int n, ir_node *in[])
434 {
435         int i;
436         ir_node *frame = get_irg_frame(irg);
437         const arch_register_class_t *cls_frame = arch_get_irn_reg_class(arch_env, frame, -1);
438         ir_node *irn;
439         const arch_register_t *sp = arch_env->isa->sp;
440         be_memperm_attr_t *attr;
441         ir_node **real_in;
442
443         real_in = alloca((n+1) * sizeof(real_in[0]));
444         real_in[0] = frame;
445         memcpy(&real_in[1], in, n * sizeof(real_in[0]));
446
447         irn =  new_ir_node(NULL, irg, bl, op_be_MemPerm, mode_T, n+1, real_in);
448
449         init_node_attr(irn, n + 1);
450         be_node_set_reg_class(irn, 0, sp->reg_class);
451         for(i = 0; i < n; ++i) {
452                 be_node_set_reg_class(irn, i + 1, cls_frame);
453                 be_node_set_reg_class(irn, OUT_POS(i), cls_frame);
454         }
455
456         attr = get_irn_attr(irn);
457
458         attr->in_entities = obstack_alloc(irg->obst, n * sizeof(attr->in_entities[0]));
459         memset(attr->in_entities, 0, n * sizeof(attr->in_entities[0]));
460         attr->out_entities = obstack_alloc(irg->obst, n*sizeof(attr->out_entities[0]));
461         memset(attr->out_entities, 0, n*sizeof(attr->out_entities[0]));
462
463         return irn;
464 }
465
466
467 ir_node *be_new_Copy(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *op)
468 {
469         ir_node *in[1];
470         ir_node *res;
471         arch_register_req_t *req;
472
473         in[0] = op;
474         res   = new_ir_node(NULL, irg, bl, op_be_Copy, get_irn_mode(op), 1, in);
475         init_node_attr(res, 1);
476         be_node_set_reg_class(res, 0, cls);
477         be_node_set_reg_class(res, OUT_POS(0), cls);
478
479         req = get_req(res, OUT_POS(0));
480         req->cls = cls;
481         req->type = arch_register_req_type_should_be_same;
482         req->other_same = 0;
483
484         return res;
485 }
486
487 ir_node *be_get_Copy_op(const ir_node *cpy) {
488         return get_irn_n(cpy, be_pos_Copy_op);
489 }
490
491 void be_set_Copy_op(ir_node *cpy, ir_node *op) {
492         set_irn_n(cpy, be_pos_Copy_op, op);
493 }
494
495 ir_node *be_new_Keep(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, int n, ir_node *in[])
496 {
497         int i;
498         ir_node *res;
499
500         res = new_ir_node(NULL, irg, bl, op_be_Keep, mode_ANY, -1, NULL);
501         init_node_attr(res, -1);
502
503         for(i = 0; i < n; ++i) {
504                 add_irn_n(res, in[i]);
505                 add_register_req(res);
506                 be_node_set_reg_class(res, i, cls);
507         }
508         keep_alive(res);
509
510         return res;
511 }
512
513 void be_Keep_add_node(ir_node *keep, const arch_register_class_t *cls, ir_node *node)
514 {
515         int n;
516
517         assert(be_is_Keep(keep));
518         n = add_irn_n(keep, node);
519         add_register_req(keep);
520         be_node_set_reg_class(keep, n, cls);
521 }
522
523 ir_node *be_new_Call(dbg_info *dbg, ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *sp, ir_node *ptr,
524                      int n_outs, int n, ir_node *in[], ir_type *call_tp)
525 {
526         be_call_attr_t *a;
527         int real_n = be_pos_Call_first_arg + n;
528         ir_node *irn;
529         ir_node **real_in;
530
531         NEW_ARR_A(ir_node *, real_in, real_n);
532         real_in[be_pos_Call_mem] = mem;
533         real_in[be_pos_Call_sp]  = sp;
534         real_in[be_pos_Call_ptr] = ptr;
535         memcpy(&real_in[be_pos_Call_first_arg], in, n * sizeof(in[0]));
536
537         irn = new_ir_node(dbg, irg, bl, op_be_Call, mode_T, real_n, real_in);
538         a = init_node_attr(irn, (n_outs > real_n ? n_outs : real_n));
539         a->ent     = NULL;
540         a->call_tp = call_tp;
541         return irn;
542 }
543
544 /* Gets the call entity or NULL if this is no static call. */
545 ir_entity *be_Call_get_entity(const ir_node *call) {
546         be_call_attr_t *a = get_irn_attr(call);
547         assert(be_is_Call(call));
548         return a->ent;
549 }
550
551 /* Sets the call entity. */
552 void be_Call_set_entity(ir_node *call, ir_entity *ent) {
553         be_call_attr_t *a = get_irn_attr(call);
554         assert(be_is_Call(call));
555         a->ent = ent;
556 }
557
558 /* Gets the call type. */
559 ir_type *be_Call_get_type(ir_node *call) {
560         be_call_attr_t *a = get_irn_attr(call);
561         assert(be_is_Call(call));
562         return a->call_tp;
563 }
564
565 /* Sets the call type. */
566 void be_Call_set_type(ir_node *call, ir_type *call_tp) {
567         be_call_attr_t *a = get_irn_attr(call);
568         assert(be_is_Call(call));
569         a->call_tp = call_tp;
570 }
571
572 /* Construct a new be_Return. */
573 ir_node *be_new_Return(dbg_info *dbg, ir_graph *irg, ir_node *block, int n_res,
574                        int n, ir_node *in[])
575 {
576         be_return_attr_t *a;
577         ir_node *res;
578         int i;
579
580         res = new_ir_node(dbg, irg, block, op_be_Return, mode_X, -1, NULL);
581         init_node_attr(res, -1);
582         for(i = 0; i < n; ++i) {
583                 add_irn_n(res, in[i]);
584                 add_register_req(res);
585         }
586
587         a = get_irn_attr(res);
588         a->num_ret_vals = n_res;
589
590         return res;
591 }
592
593 /* Returns the number of real returns values */
594 int be_Return_get_n_rets(ir_node *ret)
595 {
596         be_return_attr_t *a = get_irn_attr(ret);
597         return a->num_ret_vals;
598 }
599
600 int be_Return_append_node(ir_node *ret, ir_node *node)
601 {
602         int pos;
603
604         pos = add_irn_n(ret, node);
605         add_register_req(ret);
606
607         return pos;
608 }
609
610 ir_node *be_new_IncSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, int offset)
611 {
612         be_stack_attr_t *a;
613         ir_node *irn;
614         ir_node *in[1];
615
616         in[0]     = old_sp;
617         irn       = new_ir_node(NULL, irg, bl, op_be_IncSP, sp->reg_class->mode, sizeof(in) / sizeof(in[0]), in);
618         a         = init_node_attr(irn, 1);
619         a->offset = offset;
620
621         be_node_set_flags(irn, -1, arch_irn_flags_ignore | arch_irn_flags_modify_sp);
622
623         /* Set output constraint to stack register. */
624         be_node_set_reg_class(irn, 0, sp->reg_class);
625         be_set_constr_single_reg(irn, BE_OUT_POS(0), sp);
626         be_node_set_irn_reg(NULL, irn, sp);
627
628         return irn;
629 }
630
631 ir_node *be_new_AddSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *sz)
632 {
633         be_node_attr_t *a;
634         ir_node *irn;
635         ir_node *in[be_pos_AddSP_last];
636
637         in[be_pos_AddSP_old_sp] = old_sp;
638         in[be_pos_AddSP_size]   = sz;
639
640         irn = new_ir_node(NULL, irg, bl, op_be_AddSP, mode_T, be_pos_AddSP_last, in);
641         a   = init_node_attr(irn, be_pos_AddSP_last);
642
643         be_node_set_flags(irn, OUT_POS(pn_be_AddSP_res), arch_irn_flags_ignore | arch_irn_flags_modify_sp);
644
645         /* Set output constraint to stack register. */
646         be_set_constr_single_reg(irn, be_pos_AddSP_old_sp, sp);
647         be_node_set_reg_class(irn, be_pos_AddSP_size, arch_register_get_class(sp));
648         be_set_constr_single_reg(irn, OUT_POS(pn_be_AddSP_res), sp);
649         a->reg_data[pn_be_AddSP_res].reg = sp;
650
651         return irn;
652 }
653
654 ir_node *be_new_SubSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *sz)
655 {
656         be_node_attr_t *a;
657         ir_node *irn;
658         ir_node *in[be_pos_SubSP_last];
659
660         in[be_pos_SubSP_old_sp] = old_sp;
661         in[be_pos_SubSP_size]   = sz;
662
663         irn = new_ir_node(NULL, irg, bl, op_be_SubSP, mode_T, be_pos_SubSP_last, in);
664         a   = init_node_attr(irn, be_pos_SubSP_last);
665
666         be_node_set_flags(irn, OUT_POS(pn_be_SubSP_res), arch_irn_flags_ignore | arch_irn_flags_modify_sp);
667
668         /* Set output constraint to stack register. */
669         be_set_constr_single_reg(irn, be_pos_SubSP_old_sp, sp);
670         be_node_set_reg_class(irn, be_pos_SubSP_size, arch_register_get_class(sp));
671         be_set_constr_single_reg(irn, OUT_POS(pn_be_SubSP_res), sp);
672         a->reg_data[pn_be_SubSP_res].reg = sp;
673
674         return irn;
675 }
676
677 ir_node *be_new_SetSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *op, ir_node *mem)
678 {
679         be_node_attr_t *a;
680         ir_node *irn;
681         ir_node *in[3];
682
683         in[0]    = mem;
684         in[1]    = old_sp;
685         in[2]    = op;
686         irn      = new_ir_node(NULL, irg, bl, op_be_SetSP, get_irn_mode(old_sp), 3, in);
687         a        = init_node_attr(irn, 3);
688
689         be_node_set_flags(irn, OUT_POS(0), arch_irn_flags_ignore | arch_irn_flags_modify_sp);
690
691         /* Set output constraint to stack register. */
692         be_set_constr_single_reg(irn, OUT_POS(0), sp);
693         be_node_set_reg_class(irn, be_pos_AddSP_size, sp->reg_class);
694         be_node_set_reg_class(irn, be_pos_AddSP_old_sp, sp->reg_class);
695
696         return irn;
697 }
698
699 ir_node *be_new_StackParam(const arch_register_class_t *cls, const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_mode *mode, ir_node *frame_pointer, ir_entity *ent)
700 {
701         be_frame_attr_t *a;
702         ir_node *irn;
703         ir_node *in[1];
704
705         in[0] = frame_pointer;
706         irn = new_ir_node(NULL, irg, bl, op_be_StackParam, mode, 1, in);
707         a = init_node_attr(irn, 1);
708         a->ent = ent;
709
710         be_node_set_reg_class(irn, 0, cls_frame);
711         be_node_set_reg_class(irn, OUT_POS(0), cls);
712         return irn;
713 }
714
715 ir_node *be_new_RegParams(ir_graph *irg, ir_node *bl, int n_outs)
716 {
717         ir_node *res;
718         int i;
719
720         res = new_ir_node(NULL, irg, bl, op_be_RegParams, mode_T, 0, NULL);
721         init_node_attr(res, -1);
722         for(i = 0; i < n_outs; ++i)
723                 add_register_req(res);
724
725         return res;
726 }
727
728 ir_node *be_RegParams_append_out_reg(ir_node *regparams,
729                                      const arch_env_t *arch_env,
730                                      const arch_register_t *reg)
731 {
732         ir_graph *irg = get_irn_irg(regparams);
733         ir_node *block = get_nodes_block(regparams);
734         be_node_attr_t *attr = get_irn_attr(regparams);
735         const arch_register_class_t *cls = arch_register_get_class(reg);
736         ir_mode *mode = arch_register_class_mode(cls);
737         int n = ARR_LEN(attr->reg_data);
738         ir_node *proj;
739
740         assert(be_is_RegParams(regparams));
741         proj = new_r_Proj(irg, block, regparams, mode, n);
742         add_register_req(regparams);
743         be_set_constr_single_reg(regparams, BE_OUT_POS(n), reg);
744         arch_set_irn_register(arch_env, proj, reg);
745
746         /* TODO decide, whether we need to set ignore/modify sp flags here? */
747
748         return proj;
749 }
750
751 ir_node *be_new_FrameLoad(const arch_register_class_t *cls_frame, const arch_register_class_t *cls_data,
752                                                   ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *frame, ir_entity *ent)
753 {
754         be_frame_attr_t *a;
755         ir_node *irn;
756         ir_node *in[2];
757
758         in[0]  = mem;
759         in[1]  = frame;
760         irn    = new_ir_node(NULL, irg, bl, op_be_FrameLoad, mode_T, 2, in);
761         a      = init_node_attr(irn, 3);
762         a->ent = ent;
763         a->offset = 0;
764         be_node_set_reg_class(irn, 1, cls_frame);
765         be_node_set_reg_class(irn, OUT_POS(pn_Load_res), cls_data);
766         return irn;
767 }
768
769 ir_node *be_new_FrameStore(const arch_register_class_t *cls_frame, const arch_register_class_t *cls_data,
770                                                    ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *frame, ir_node *data, ir_entity *ent)
771 {
772         be_frame_attr_t *a;
773         ir_node *irn;
774         ir_node *in[3];
775
776         in[0]  = mem;
777         in[1]  = frame;
778         in[2]  = data;
779         irn    = new_ir_node(NULL, irg, bl, op_be_FrameStore, mode_T, 3, in);
780         a      = init_node_attr(irn, 3);
781         a->ent = ent;
782         a->offset = 0;
783         be_node_set_reg_class(irn, 1, cls_frame);
784         be_node_set_reg_class(irn, 2, cls_data);
785         return irn;
786 }
787
788 ir_node *be_new_FrameAddr(const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_node *frame, ir_entity *ent)
789 {
790         be_frame_attr_t *a;
791         ir_node *irn;
792         ir_node *in[1];
793
794         in[0]  = frame;
795         irn    = new_ir_node(NULL, irg, bl, op_be_FrameAddr, get_irn_mode(frame), 1, in);
796         a      = init_node_attr(irn, 1);
797         a->ent = ent;
798         a->offset = 0;
799         be_node_set_reg_class(irn, 0, cls_frame);
800         be_node_set_reg_class(irn, OUT_POS(0), cls_frame);
801
802         return optimize_node(irn);
803 }
804
805 ir_node *be_new_CopyKeep(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *src, int n, ir_node *in_keep[], ir_mode *mode)
806 {
807         ir_node *irn;
808         ir_node **in = (ir_node **) alloca((n + 1) * sizeof(in[0]));
809
810         in[0] = src;
811         memcpy(&in[1], in_keep, n * sizeof(in[0]));
812         irn   = new_ir_node(NULL, irg, bl, op_be_CopyKeep, mode, n + 1, in);
813         init_node_attr(irn, n + 1);
814         be_node_set_reg_class(irn, OUT_POS(0), cls);
815         be_node_set_reg_class(irn, 0, cls);
816
817         return irn;
818 }
819
820 ir_node *be_new_CopyKeep_single(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *src, ir_node *keep, ir_mode *mode)
821 {
822         ir_node *in[1];
823
824         in[0] = keep;
825         return be_new_CopyKeep(cls, irg, bl, src, 1, in, mode);
826 }
827
828 ir_node *be_get_CopyKeep_op(const ir_node *cpy) {
829         return get_irn_n(cpy, be_pos_CopyKeep_op);
830 }
831
832 void be_set_CopyKeep_op(ir_node *cpy, ir_node *op) {
833         set_irn_n(cpy, be_pos_CopyKeep_op, op);
834 }
835
836 ir_node *be_new_Barrier(ir_graph *irg, ir_node *bl, int n, ir_node *in[])
837 {
838         ir_node *res;
839         int i;
840
841         res = new_ir_node(NULL, irg, bl, op_be_Barrier, mode_T, -1, NULL);
842         init_node_attr(res, -1);
843         for(i = 0; i < n; ++i) {
844                 add_irn_n(res, in[i]);
845                 add_register_req(res);
846         }
847
848         return res;
849 }
850
851 ir_node *be_Barrier_append_node(ir_node *barrier, ir_node *node)
852 {
853         ir_graph *irg = get_irn_irg(barrier);
854         ir_node *block = get_nodes_block(barrier);
855         ir_mode *mode = get_irn_mode(node);
856         int n = add_irn_n(barrier, node);
857
858         ir_node *proj = new_r_Proj(irg, block, barrier, mode, n);
859         add_register_req(barrier);
860
861         return proj;
862 }
863
864 int be_is_Spill         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Spill          ; }
865 int be_is_Reload        (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Reload         ; }
866 int be_is_Copy          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Copy           ; }
867 int be_is_CopyKeep      (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_CopyKeep       ; }
868 int be_is_Perm          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Perm           ; }
869 int be_is_MemPerm       (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_MemPerm        ; }
870 int be_is_Keep          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Keep           ; }
871 int be_is_Call          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Call           ; }
872 int be_is_Return        (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Return         ; }
873 int be_is_IncSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_IncSP          ; }
874 int be_is_SetSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_SetSP          ; }
875 int be_is_AddSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_AddSP          ; }
876 int be_is_SubSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_SubSP          ; }
877 int be_is_RegParams     (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_RegParams      ; }
878 int be_is_StackParam    (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_StackParam     ; }
879 int be_is_FrameAddr     (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameAddr      ; }
880 int be_is_FrameLoad     (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameLoad      ; }
881 int be_is_FrameStore    (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameStore     ; }
882 int be_is_Barrier       (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Barrier        ; }
883
884 int be_has_frame_entity(const ir_node *irn)
885 {
886         switch(be_get_irn_opcode(irn)) {
887         case beo_StackParam:
888         case beo_Spill:
889         case beo_Reload:
890         case beo_FrameStore:
891         case beo_FrameLoad:
892         case beo_FrameAddr:
893                 return 1;
894         default:
895                 return 0;
896         }
897 }
898
899 ir_entity *be_get_frame_entity(const ir_node *irn)
900 {
901         if (be_has_frame_entity(irn)) {
902                 be_frame_attr_t *a = get_irn_attr(irn);
903                 return a->ent;
904         }
905         return NULL;
906 }
907
908 int be_get_frame_offset(const ir_node *irn)
909 {
910         assert(is_be_node(irn));
911         if (be_has_frame_entity(irn)) {
912                 be_frame_attr_t *a = get_irn_attr(irn);
913                 return a->offset;
914         }
915         return 0;
916 }
917
918 void be_set_MemPerm_in_entity(const ir_node *irn, int n, ir_entity *ent)
919 {
920         be_memperm_attr_t *attr = get_irn_attr(irn);
921
922         assert(be_is_MemPerm(irn));
923         assert(n < be_get_MemPerm_entity_arity(irn));
924
925         attr->in_entities[n] = ent;
926 }
927
928 ir_entity* be_get_MemPerm_in_entity(const ir_node* irn, int n)
929 {
930         be_memperm_attr_t *attr = get_irn_attr(irn);
931
932         assert(be_is_MemPerm(irn));
933         assert(n < be_get_MemPerm_entity_arity(irn));
934
935         return attr->in_entities[n];
936 }
937
938 void be_set_MemPerm_out_entity(const ir_node *irn, int n, ir_entity *ent)
939 {
940         be_memperm_attr_t *attr = get_irn_attr(irn);
941
942         assert(be_is_MemPerm(irn));
943         assert(n < be_get_MemPerm_entity_arity(irn));
944
945         attr->out_entities[n] = ent;
946 }
947
948 ir_entity* be_get_MemPerm_out_entity(const ir_node* irn, int n)
949 {
950         be_memperm_attr_t *attr = get_irn_attr(irn);
951
952         assert(be_is_MemPerm(irn));
953         assert(n < be_get_MemPerm_entity_arity(irn));
954
955         return attr->out_entities[n];
956 }
957
958 int be_get_MemPerm_entity_arity(const ir_node *irn)
959 {
960         return get_irn_arity(irn) - 1;
961 }
962
963 void be_set_constr_single_reg(ir_node *node, int pos, const arch_register_t *reg)
964 {
965         arch_register_req_t *req = get_req(node, pos);
966         const arch_register_class_t *cls = arch_register_get_class(reg);
967         ir_graph *irg = get_irn_irg(node);
968         struct obstack *obst = get_irg_obstack(irg);
969         unsigned *limited_bitset;
970
971         assert(req->cls == NULL || req->cls == cls);
972         assert(! (req->type & arch_register_req_type_limited));
973         assert(req->limited == NULL);
974
975         limited_bitset = rbitset_obstack_alloc(obst, arch_register_class_n_regs(cls));
976         rbitset_set(limited_bitset, arch_register_get_index(reg));
977
978         req->cls = cls;
979         req->type |= arch_register_req_type_limited;
980         req->limited = limited_bitset;
981 }
982
983 void be_set_constr_limited(ir_node *node, int pos, const arch_register_req_t *req)
984 {
985         ir_graph *irg = get_irn_irg(node);
986         struct obstack *obst = get_irg_obstack(irg);
987         arch_register_req_t *r = get_req(node, pos);
988
989         assert(arch_register_req_is(req, limited));
990         assert(! (req->type & (arch_register_req_type_should_be_same | arch_register_req_type_should_be_different)));
991         memcpy(r, req, sizeof(r[0]));
992         r->limited = rbitset_duplicate_obstack_alloc(obst, req->limited, req->cls->n_regs);
993 }
994
995 void be_node_set_flags(ir_node *irn, int pos, arch_irn_flags_t flags)
996 {
997         be_req_t *bereq = get_be_req(irn, pos);
998         bereq->flags = flags;
999 }
1000
1001 void be_node_set_reg_class(ir_node *irn, int pos, const arch_register_class_t *cls)
1002 {
1003         arch_register_req_t *req = get_req(irn, pos);
1004
1005         req->cls = cls;
1006
1007         if (cls == NULL) {
1008                 req->type = arch_register_req_type_none;
1009         } else if (req->type == arch_register_req_type_none) {
1010                 req->type = arch_register_req_type_normal;
1011         }
1012 }
1013
1014 void be_node_set_req_type(ir_node *irn, int pos, arch_register_req_type_t type)
1015 {
1016         arch_register_req_t *req = get_req(irn, pos);
1017         req->type = type;
1018 }
1019
1020 ir_node *be_get_IncSP_pred(ir_node *irn) {
1021         assert(be_is_IncSP(irn));
1022         return get_irn_n(irn, 0);
1023 }
1024
1025 void be_set_IncSP_pred(ir_node *incsp, ir_node *pred) {
1026         assert(be_is_IncSP(incsp));
1027         set_irn_n(incsp, 0, pred);
1028 }
1029
1030 ir_node *be_get_IncSP_mem(ir_node *irn) {
1031         assert(be_is_IncSP(irn));
1032         return get_irn_n(irn, 1);
1033 }
1034
1035 void be_set_IncSP_offset(ir_node *irn, int offset)
1036 {
1037         be_stack_attr_t *a = get_irn_attr(irn);
1038         assert(be_is_IncSP(irn));
1039         a->offset = offset;
1040 }
1041
1042 int be_get_IncSP_offset(const ir_node *irn)
1043 {
1044         be_stack_attr_t *a = get_irn_attr(irn);
1045         assert(be_is_IncSP(irn));
1046         return a->offset;
1047 }
1048
1049 ir_node *be_spill(const arch_env_t *arch_env, ir_node *irn)
1050 {
1051         ir_node                     *bl        = get_nodes_block(irn);
1052         ir_graph                    *irg       = get_irn_irg(bl);
1053         ir_node                     *frame     = get_irg_frame(irg);
1054         const arch_register_class_t *cls       = arch_get_irn_reg_class(arch_env, irn, -1);
1055         const arch_register_class_t *cls_frame = arch_get_irn_reg_class(arch_env, frame, -1);
1056         ir_node                     *spill;
1057
1058         spill = be_new_Spill(cls, cls_frame, irg, bl, frame, irn);
1059         return spill;
1060 }
1061
1062 ir_node *be_reload(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_node *insert, ir_mode *mode, ir_node *spill)
1063 {
1064         ir_node  *reload;
1065         ir_node  *bl    = is_Block(insert) ? insert : get_nodes_block(insert);
1066         ir_graph *irg   = get_irn_irg(bl);
1067         ir_node  *frame = get_irg_frame(irg);
1068         const arch_register_class_t *cls_frame = arch_get_irn_reg_class(arch_env, frame, -1);
1069
1070         assert(be_is_Spill(spill) || (is_Phi(spill) && get_irn_mode(spill) == mode_M));
1071
1072         reload = be_new_Reload(cls, cls_frame, irg, bl, frame, spill, mode);
1073
1074         if (is_Block(insert)) {
1075                 insert = sched_skip(insert, 0, sched_skip_cf_predicator, (void *) arch_env);
1076                 sched_add_after(insert, reload);
1077         } else {
1078                 sched_add_before(insert, reload);
1079         }
1080
1081         return reload;
1082 }
1083
1084 /*
1085   ____              ____
1086  |  _ \ ___  __ _  |  _ \ ___  __ _ ___
1087  | |_) / _ \/ _` | | |_) / _ \/ _` / __|
1088  |  _ <  __/ (_| | |  _ <  __/ (_| \__ \
1089  |_| \_\___|\__, | |_| \_\___|\__, |___/
1090             |___/                |_|
1091
1092 */
1093
1094
1095 static const
1096 arch_register_req_t *get_out_reg_req(const ir_node *irn, int out_pos)
1097 {
1098         const be_node_attr_t *a = get_irn_attr(irn);
1099
1100         if(out_pos >= ARR_LEN(a->reg_data)) {
1101                 return arch_no_register_req;
1102         }
1103
1104         return &a->reg_data[out_pos].req.req;
1105 }
1106
1107 static const
1108 arch_register_req_t *get_in_reg_req(const ir_node *irn, int pos)
1109 {
1110         const be_node_attr_t *a = get_irn_attr(irn);
1111
1112         if(pos >= get_irn_arity(irn) || pos >= ARR_LEN(a->reg_data))
1113                 return arch_no_register_req;
1114
1115         return &a->reg_data[pos].in_req.req;
1116 }
1117
1118 static const arch_register_req_t *
1119 be_node_get_irn_reg_req(const void *self, const ir_node *irn, int pos)
1120 {
1121         int out_pos = pos;
1122
1123         if (pos < 0) {
1124                 if (get_irn_mode(irn) == mode_T)
1125                         return arch_no_register_req;
1126
1127                 out_pos = redir_proj((const ir_node **)&irn);
1128                 assert(is_be_node(irn));
1129                 return get_out_reg_req(irn, out_pos);
1130         } else if (is_be_node(irn)) {
1131                 /*
1132                  * For spills and reloads, we return "none" as requirement for frame
1133                  * pointer, so every input is ok. Some backends need this (e.g. STA).
1134                  */
1135                 if ((be_is_Spill(irn)  && pos == be_pos_Spill_frame) ||
1136                                 (be_is_Reload(irn) && pos == be_pos_Reload_frame))
1137                         return arch_no_register_req;
1138
1139                 return get_in_reg_req(irn, pos);
1140         }
1141
1142         return arch_no_register_req;
1143 }
1144
1145 const arch_register_t *
1146 be_node_get_irn_reg(const void *_self, const ir_node *irn)
1147 {
1148         be_reg_data_t *r;
1149
1150         if (get_irn_mode(irn) == mode_T)
1151                 return NULL;
1152         r = retrieve_reg_data(irn);
1153         return r->reg;
1154 }
1155
1156 static arch_irn_class_t be_node_classify(const void *_self, const ir_node *irn)
1157 {
1158         redir_proj((const ir_node **) &irn);
1159
1160         switch(be_get_irn_opcode(irn)) {
1161 #define XXX(a,b) case beo_ ## a: return arch_irn_class_ ## b
1162                 XXX(Spill, spill);
1163                 XXX(Reload, reload);
1164                 XXX(Perm, perm);
1165                 XXX(Copy, copy);
1166                 XXX(Return, branch);
1167                 XXX(StackParam, stackparam);
1168 #undef XXX
1169                 default:
1170                 return arch_irn_class_normal;
1171         }
1172
1173         return 0;
1174 }
1175
1176 static arch_irn_flags_t be_node_get_flags(const void *_self, const ir_node *node)
1177 {
1178         be_req_t *bereq;
1179         int pos = -1;
1180
1181         if(is_Proj(node)) {
1182                 pos = OUT_POS(get_Proj_proj(node));
1183                 node = skip_Proj_const(node);
1184         }
1185
1186         bereq = get_be_req(node, pos);
1187
1188         return bereq->flags;
1189 }
1190
1191 static ir_entity *be_node_get_frame_entity(const void *self, const ir_node *irn)
1192 {
1193         return be_get_frame_entity(irn);
1194 }
1195
1196 static void be_node_set_frame_entity(const void *self, ir_node *irn, ir_entity *ent)
1197 {
1198         be_frame_attr_t *a;
1199
1200         assert(be_has_frame_entity(irn));
1201
1202         a = get_irn_attr(irn);
1203         a->ent = ent;
1204 }
1205
1206 static void be_node_set_frame_offset(const void *self, ir_node *irn, int offset)
1207 {
1208         if(be_has_frame_entity(irn)) {
1209                 be_frame_attr_t *a = get_irn_attr(irn);
1210                 a->offset = offset;
1211         }
1212 }
1213
1214 static int be_node_get_sp_bias(const void *self, const ir_node *irn)
1215 {
1216         return be_is_IncSP(irn) ? be_get_IncSP_offset(irn) : 0;
1217 }
1218
1219 /*
1220   ___ ____  _   _   _   _                 _ _
1221  |_ _|  _ \| \ | | | | | | __ _ _ __   __| | | ___ _ __
1222   | || |_) |  \| | | |_| |/ _` | '_ \ / _` | |/ _ \ '__|
1223   | ||  _ <| |\  | |  _  | (_| | | | | (_| | |  __/ |
1224  |___|_| \_\_| \_| |_| |_|\__,_|_| |_|\__,_|_|\___|_|
1225
1226 */
1227
1228 static const arch_irn_ops_if_t be_node_irn_ops_if = {
1229         be_node_get_irn_reg_req,
1230         be_node_set_irn_reg,
1231         be_node_get_irn_reg,
1232         be_node_classify,
1233         be_node_get_flags,
1234         be_node_get_frame_entity,
1235         be_node_set_frame_entity,
1236         be_node_set_frame_offset,
1237         be_node_get_sp_bias,
1238         NULL,    /* get_inverse             */
1239         NULL,    /* get_op_estimated_cost   */
1240         NULL,    /* possible_memory_operand */
1241         NULL,    /* perform_memory_operand  */
1242 };
1243
1244 static const arch_irn_ops_t be_node_irn_ops = {
1245         &be_node_irn_ops_if
1246 };
1247
1248 const void *be_node_get_irn_ops(const arch_irn_handler_t *self, const ir_node *irn)
1249 {
1250         redir_proj((const ir_node **) &irn);
1251         return is_be_node(irn) ? &be_node_irn_ops : NULL;
1252 }
1253
1254 const arch_irn_handler_t be_node_irn_handler = {
1255         be_node_get_irn_ops
1256 };
1257
1258 /*
1259   ____  _     _   ___ ____  _   _   _   _                 _ _
1260  |  _ \| |__ (_) |_ _|  _ \| \ | | | | | | __ _ _ __   __| | | ___ _ __
1261  | |_) | '_ \| |  | || |_) |  \| | | |_| |/ _` | '_ \ / _` | |/ _ \ '__|
1262  |  __/| | | | |  | ||  _ <| |\  | |  _  | (_| | | | | (_| | |  __/ |
1263  |_|   |_| |_|_| |___|_| \_\_| \_| |_| |_|\__,_|_| |_|\__,_|_|\___|_|
1264
1265 */
1266
1267 typedef struct {
1268         const arch_register_t *reg;
1269         arch_register_req_t    req;
1270         arch_irn_flags_t       flags;
1271 } phi_attr_t;
1272
1273 typedef struct {
1274         arch_irn_handler_t irn_handler;
1275         arch_irn_ops_t     irn_ops;
1276         const arch_env_t   *arch_env;
1277         pmap               *phi_attrs;
1278 } phi_handler_t;
1279
1280 #define get_phi_handler_from_handler(h)  container_of(h, phi_handler_t, irn_handler)
1281 #define get_phi_handler_from_ops(h)      container_of(h, phi_handler_t, irn_ops)
1282
1283 static
1284 const void *phi_get_irn_ops(const arch_irn_handler_t *handler,
1285                             const ir_node *irn)
1286 {
1287         const phi_handler_t *h;
1288         if(!is_Phi(irn) || !mode_is_datab(get_irn_mode(irn)))
1289                 return NULL;
1290
1291         h = get_phi_handler_from_handler(handler);
1292         return &h->irn_ops;
1293 }
1294
1295 static INLINE
1296 phi_attr_t *get_Phi_attr(const phi_handler_t *handler, const ir_node *phi)
1297 {
1298         phi_attr_t *attr = pmap_get(handler->phi_attrs, (void*) phi);
1299         if(attr == NULL) {
1300                 ir_graph *irg = get_irn_irg(phi);
1301                 struct obstack *obst = get_irg_obstack(irg);
1302                 attr = obstack_alloc(obst, sizeof(attr[0]));
1303                 memset(attr, 0, sizeof(attr[0]));
1304                 pmap_insert(handler->phi_attrs, phi, attr);
1305         }
1306
1307         return attr;
1308 }
1309
1310 /**
1311  * Get register class of a Phi.
1312  */
1313 static
1314 const arch_register_req_t *get_Phi_reg_req_recursive(const phi_handler_t *h,
1315                                                      const ir_node *phi,
1316                                                      pset **visited)
1317 {
1318         int n = get_irn_arity(phi);
1319         ir_node *op;
1320         int i;
1321
1322         if(*visited && pset_find_ptr(*visited, phi))
1323                 return NULL;
1324
1325         for(i = 0; i < n; ++i) {
1326                 op = get_irn_n(phi, i);
1327                 /* Matze: don't we unnecessary constraint our phis with this?
1328                  * we only need to take the regclass IMO*/
1329                 if(!is_Phi(op))
1330                         return arch_get_register_req(h->arch_env, op, BE_OUT_POS(0));
1331         }
1332
1333         /*
1334          * The operands of that Phi were all Phis themselves.
1335          * We have to start a DFS for a non-Phi argument now.
1336          */
1337         if(!*visited)
1338                 *visited = pset_new_ptr(16);
1339
1340         pset_insert_ptr(*visited, phi);
1341
1342         for(i = 0; i < n; ++i) {
1343                 const arch_register_req_t *req;
1344                 op = get_irn_n(phi, i);
1345                 req = get_Phi_reg_req_recursive(h, op, visited);
1346                 if(req != NULL)
1347                         return req;
1348         }
1349
1350         return NULL;
1351 }
1352
1353 static
1354 const arch_register_req_t *phi_get_irn_reg_req(const void *self,
1355                                                const ir_node *irn, int pos)
1356 {
1357         phi_handler_t *phi_handler = get_phi_handler_from_ops(self);
1358         phi_attr_t *attr;
1359
1360         if(!mode_is_datab(get_irn_mode(irn)))
1361                 return arch_no_register_req;
1362
1363         attr = get_Phi_attr(phi_handler, irn);
1364
1365         if(attr->req.type == arch_register_req_type_none) {
1366                 pset *visited = NULL;
1367                 const arch_register_req_t *req;
1368                 req = get_Phi_reg_req_recursive(phi_handler, irn, &visited);
1369
1370                 memcpy(&attr->req, req, sizeof(req[0]));
1371                 assert(attr->req.cls != NULL);
1372                 attr->req.type = arch_register_req_type_normal;
1373
1374                 if(visited != NULL)
1375                         del_pset(visited);
1376         }
1377
1378         return &attr->req;
1379 }
1380
1381 void be_set_phi_reg_req(const arch_env_t *arch_env, ir_node *node,
1382                         const arch_register_req_t *req)
1383 {
1384         const arch_irn_ops_t *ops = arch_get_irn_ops(arch_env, node);
1385         const phi_handler_t *handler = get_phi_handler_from_ops(ops);
1386         phi_attr_t *attr;
1387
1388         assert(mode_is_datab(get_irn_mode(node)));
1389
1390         attr = get_Phi_attr(handler, node);
1391         memcpy(&attr->req, req, sizeof(req[0]));
1392 }
1393
1394 void be_set_phi_flags(const arch_env_t *arch_env, ir_node *node,
1395                       arch_irn_flags_t flags)
1396 {
1397         const arch_irn_ops_t *ops = arch_get_irn_ops(arch_env, node);
1398         const phi_handler_t *handler = get_phi_handler_from_ops(ops);
1399         phi_attr_t *attr;
1400
1401         assert(mode_is_datab(get_irn_mode(node)));
1402
1403         attr = get_Phi_attr(handler, node);
1404         attr->flags = flags;
1405 }
1406
1407 static
1408 void phi_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg)
1409 {
1410         phi_handler_t *h = get_phi_handler_from_ops(self);
1411         phi_attr_t *attr = get_Phi_attr(h, irn);
1412         attr->reg = reg;
1413 }
1414
1415 static
1416 const arch_register_t *phi_get_irn_reg(const void *self, const ir_node *irn)
1417 {
1418         phi_handler_t *h = get_phi_handler_from_ops(self);
1419         phi_attr_t *attr = get_Phi_attr(h, irn);
1420         return attr->reg;
1421 }
1422
1423 static
1424 arch_irn_class_t phi_classify(const void *self, const ir_node *irn)
1425 {
1426         return arch_irn_class_normal;
1427 }
1428
1429 static
1430 arch_irn_flags_t phi_get_flags(const void *self, const ir_node *irn)
1431 {
1432         phi_handler_t *h = get_phi_handler_from_ops(self);
1433         phi_attr_t *attr = get_Phi_attr(h, irn);
1434         return attr->flags;
1435 }
1436
1437 static
1438 ir_entity *phi_get_frame_entity(const void *_self, const ir_node *irn)
1439 {
1440         return NULL;
1441 }
1442
1443 static
1444 void phi_set_frame_entity(const void *_self, ir_node *irn, ir_entity *ent)
1445 {
1446         assert(0);
1447 }
1448
1449 static
1450 void phi_set_frame_offset(const void *_self, ir_node *irn, int bias)
1451 {
1452         assert(0);
1453 }
1454
1455 static
1456 int phi_get_sp_bias(const void* self, const ir_node *irn)
1457 {
1458         return 0;
1459 }
1460
1461 static
1462 const arch_irn_ops_if_t phi_irn_ops = {
1463         phi_get_irn_reg_req,
1464         phi_set_irn_reg,
1465         phi_get_irn_reg,
1466         phi_classify,
1467         phi_get_flags,
1468         phi_get_frame_entity,
1469         phi_set_frame_entity,
1470         phi_set_frame_offset,
1471         phi_get_sp_bias,
1472         NULL,    /* get_inverse             */
1473         NULL,    /* get_op_estimated_cost   */
1474         NULL,    /* possible_memory_operand */
1475         NULL,    /* perform_memory_operand  */
1476 };
1477
1478 arch_irn_handler_t *be_phi_handler_new(const arch_env_t *arch_env)
1479 {
1480         phi_handler_t *h           = xmalloc(sizeof(h[0]));
1481         h->irn_handler.get_irn_ops = phi_get_irn_ops;
1482         h->irn_ops.impl            = &phi_irn_ops;
1483         h->arch_env                = arch_env;
1484         h->phi_attrs               = pmap_create();
1485         return (arch_irn_handler_t *) h;
1486 }
1487
1488 void be_phi_handler_free(arch_irn_handler_t *handler)
1489 {
1490         phi_handler_t *h = (void *) handler;
1491         pmap_destroy(h->phi_attrs);
1492         free(handler);
1493 }
1494
1495 void be_phi_handler_reset(arch_irn_handler_t *handler)
1496 {
1497         phi_handler_t *h = get_phi_handler_from_handler(handler);
1498         if(h->phi_attrs)
1499                 pmap_destroy(h->phi_attrs);
1500         h->phi_attrs = pmap_create();
1501 }
1502
1503 /*
1504   _   _           _        ____                        _
1505  | \ | | ___   __| | ___  |  _ \ _   _ _ __ ___  _ __ (_)_ __   __ _
1506  |  \| |/ _ \ / _` |/ _ \ | | | | | | | '_ ` _ \| '_ \| | '_ \ / _` |
1507  | |\  | (_) | (_| |  __/ | |_| | |_| | | | | | | |_) | | | | | (_| |
1508  |_| \_|\___/ \__,_|\___| |____/ \__,_|_| |_| |_| .__/|_|_| |_|\__, |
1509                                                 |_|            |___/
1510 */
1511
1512 /**
1513  * Dumps a register requirement to a file.
1514  */
1515 static void dump_node_req(FILE *f, int idx, const arch_register_req_t *req,
1516                           const ir_node *node)
1517 {
1518         int did_something = 0;
1519         char buf[16];
1520         const char *prefix = buf;
1521
1522         snprintf(buf, sizeof(buf), "#%d ", idx);
1523         buf[sizeof(buf) - 1] = '\0';
1524
1525         if(req->cls != 0) {
1526                 char tmp[256];
1527                 fprintf(f, prefix);
1528                 arch_register_req_format(tmp, sizeof(tmp), req, node);
1529                 fprintf(f, "%s", tmp);
1530                 did_something = 1;
1531         }
1532
1533         if(did_something)
1534                 fprintf(f, "\n");
1535 }
1536
1537 /**
1538  * Dumps node register requirements to a file.
1539  */
1540 static void dump_node_reqs(FILE *f, ir_node *node)
1541 {
1542         int i;
1543         be_node_attr_t *a = get_irn_attr(node);
1544         int len = ARR_LEN(a->reg_data);
1545
1546         fprintf(f, "registers: \n");
1547         for(i = 0; i < len; ++i) {
1548                 be_reg_data_t *rd = &a->reg_data[i];
1549                 if(rd->reg)
1550                         fprintf(f, "#%d: %s\n", i, rd->reg->name);
1551         }
1552
1553         fprintf(f, "in requirements:\n");
1554         for(i = 0; i < len; ++i) {
1555                 dump_node_req(f, i, &a->reg_data[i].in_req.req, node);
1556         }
1557
1558         fprintf(f, "\nout requirements:\n");
1559         for(i = 0; i < len; ++i) {
1560                 dump_node_req(f, i, &a->reg_data[i].req.req, node);
1561         }
1562 }
1563
1564 /**
1565  * ir_op-Operation: dump a be node to file
1566  */
1567 static int dump_node(ir_node *irn, FILE *f, dump_reason_t reason)
1568 {
1569         be_node_attr_t *at = get_irn_attr(irn);
1570
1571         assert(is_be_node(irn));
1572
1573         switch(reason) {
1574                 case dump_node_opcode_txt:
1575                         fprintf(f, get_op_name(get_irn_op(irn)));
1576                         break;
1577                 case dump_node_mode_txt:
1578                         fprintf(f, get_mode_name(get_irn_mode(irn)));
1579                         break;
1580                 case dump_node_nodeattr_txt:
1581                         break;
1582                 case dump_node_info_txt:
1583                         dump_node_reqs(f, irn);
1584
1585                         if(be_has_frame_entity(irn)) {
1586                                 be_frame_attr_t *a = (be_frame_attr_t *) at;
1587                                 if (a->ent) {
1588                                         int bits = get_type_size_bits(get_entity_type(a->ent));
1589                                         ir_fprintf(f, "frame entity: %+F, offset 0x%x (%d), size 0x%x (%d) bits\n",
1590                                           a->ent, a->offset, a->offset, bits, bits);
1591                                 }
1592
1593                         }
1594
1595                         switch(be_get_irn_opcode(irn)) {
1596                         case beo_IncSP:
1597                                 {
1598                                         be_stack_attr_t *a = (be_stack_attr_t *) at;
1599                                         if (a->offset == BE_STACK_FRAME_SIZE_EXPAND)
1600                                                 fprintf(f, "offset: FRAME_SIZE\n");
1601                                         else if(a->offset == BE_STACK_FRAME_SIZE_SHRINK)
1602                                                 fprintf(f, "offset: -FRAME SIZE\n");
1603                                         else
1604                                                 fprintf(f, "offset: %u\n", a->offset);
1605                                 }
1606                                 break;
1607                         case beo_Call:
1608                                 {
1609                                         be_call_attr_t *a = (be_call_attr_t *) at;
1610
1611                                         if (a->ent)
1612                                                 fprintf(f, "\ncalling: %s\n", get_entity_name(a->ent));
1613                                 }
1614                                 break;
1615                         case beo_MemPerm:
1616                                 {
1617                                         int i;
1618                                         for(i = 0; i < be_get_MemPerm_entity_arity(irn); ++i) {
1619                                                 ir_entity *in, *out;
1620                                                 in = be_get_MemPerm_in_entity(irn, i);
1621                                                 out = be_get_MemPerm_out_entity(irn, i);
1622                                                 if(in) {
1623                                                         fprintf(f, "\nin[%d]: %s\n", i, get_entity_name(in));
1624                                                 }
1625                                                 if(out) {
1626                                                         fprintf(f, "\nout[%d]: %s\n", i, get_entity_name(out));
1627                                                 }
1628                                         }
1629                                 }
1630                                 break;
1631
1632                         default:
1633                                 break;
1634                         }
1635         }
1636
1637         return 0;
1638 }
1639
1640 /**
1641  * ir_op-Operation:
1642  * Copies the backend specific attributes from old node to new node.
1643  */
1644 static void copy_attr(const ir_node *old_node, ir_node *new_node)
1645 {
1646         be_node_attr_t *old_attr = get_irn_attr(old_node);
1647         be_node_attr_t *new_attr = get_irn_attr(new_node);
1648         struct obstack *obst = get_irg_obstack(get_irn_irg(new_node));
1649         unsigned i, len;
1650
1651         assert(is_be_node(old_node));
1652         assert(is_be_node(new_node));
1653
1654         memcpy(new_attr, old_attr, get_op_attr_size(get_irn_op(old_node)));
1655         new_attr->reg_data = NULL;
1656
1657         if(old_attr->reg_data != NULL)
1658                 len = ARR_LEN(old_attr->reg_data);
1659         else
1660                 len = 0;
1661
1662         if(get_irn_op(old_node)->opar == oparity_dynamic
1663                         || be_is_RegParams(old_node)) {
1664                 new_attr->reg_data = NEW_ARR_F(be_reg_data_t, len);
1665         } else {
1666                 new_attr->reg_data = NEW_ARR_D(be_reg_data_t, obst, len);
1667         }
1668
1669         if(len > 0) {
1670                 memcpy(new_attr->reg_data, old_attr->reg_data, len * sizeof(be_reg_data_t));
1671                 for(i = 0; i < len; ++i) {
1672                         const be_reg_data_t *rd = &old_attr->reg_data[i];
1673                         be_reg_data_t *newrd = &new_attr->reg_data[i];
1674                         if(arch_register_req_is(&rd->req.req, limited)) {
1675                                 const arch_register_req_t *req = &rd->req.req;
1676                                 arch_register_req_t *new_req = &newrd->req.req;
1677                                 new_req->limited
1678                                         = rbitset_duplicate_obstack_alloc(obst, req->limited, req->cls->n_regs);
1679                         }
1680                         if(arch_register_req_is(&rd->in_req.req, limited)) {
1681                                 const arch_register_req_t *req = &rd->in_req.req;
1682                                 arch_register_req_t *new_req = &newrd->in_req.req;
1683                                 new_req->limited
1684                                         = rbitset_duplicate_obstack_alloc(obst, req->limited, req->cls->n_regs);
1685                         }
1686                 }
1687         }
1688 }
1689
1690 static const ir_op_ops be_node_op_ops = {
1691         NULL,
1692         NULL,
1693         NULL,
1694         NULL,
1695         NULL,
1696         copy_attr,
1697         NULL,
1698         NULL,
1699         NULL,
1700         NULL,
1701         NULL,
1702         dump_node,
1703         NULL
1704 };