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