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