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