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