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