beifg: Factorise code to count interference components.
[libfirm] / ir / be / benode.c
1 /*
2  * This file is part of libFirm.
3  * Copyright (C) 2012 University of Karlsruhe.
4  */
5
6 /**
7  * @file
8  * @brief       Backend node support for generic backend nodes.
9  * @author      Sebastian Hack
10  * @date        17.05.2005
11  *
12  * Backend node support for generic backend nodes.
13  * This file provides Perm, Copy, Spill and Reload nodes.
14  */
15 #include "config.h"
16
17 #include <stdlib.h>
18
19 #include "beirg.h"
20 #include "obst.h"
21 #include "set.h"
22 #include "pmap.h"
23 #include "util.h"
24 #include "debug.h"
25 #include "fourcc.h"
26 #include "bitfiddle.h"
27 #include "raw_bitset.h"
28 #include "error.h"
29 #include "array_t.h"
30
31 #include "irop_t.h"
32 #include "irmode_t.h"
33 #include "irnode_t.h"
34 #include "ircons_t.h"
35 #include "irprintf.h"
36 #include "irgwalk.h"
37 #include "iropt_t.h"
38 #include "irbackedge_t.h"
39 #include "irverify_t.h"
40
41 #include "be_t.h"
42 #include "belive_t.h"
43 #include "besched.h"
44 #include "benode.h"
45 #include "bearch.h"
46
47 #include "beirgmod.h"
48
49 typedef struct be_node_attr_t {
50         except_attr  exc;
51 } be_node_attr_t;
52
53 /** The be_Return nodes attribute type. */
54 typedef struct {
55         be_node_attr_t base;
56         int            num_ret_vals; /**< number of return values */
57         unsigned       pop;          /**< number of bytes that should be popped */
58         int            emit_pop;     /**< if set, emit pop bytes, even if pop = 0 */
59 } be_return_attr_t;
60
61 /** The be_IncSP attribute type. */
62 typedef struct {
63         be_node_attr_t base;
64         int            offset;    /**< The offset by which the stack shall be
65                                        expanded/shrinked. */
66         int            align;     /**< whether stack should be aligned after the
67                                        IncSP */
68 } be_incsp_attr_t;
69
70 /** The be_Frame attribute type. */
71 typedef struct {
72         be_node_attr_t  base;
73         ir_entity      *ent;
74         int             offset;
75 } be_frame_attr_t;
76
77 /** The be_Call attribute type. */
78 typedef struct {
79         be_node_attr_t  base;
80         ir_entity      *ent;        /**< called entity if this is a static call. */
81         unsigned        pop;
82         ir_type        *call_tp;    /**< call type, copied from the original Call */
83 } be_call_attr_t;
84
85 typedef struct {
86         be_node_attr_t base;
87         ir_entity    **in_entities;
88         ir_entity    **out_entities;
89 } be_memperm_attr_t;
90
91 ir_op *op_be_Spill;
92 ir_op *op_be_Reload;
93 ir_op *op_be_Perm;
94 ir_op *op_be_MemPerm;
95 ir_op *op_be_Copy;
96 ir_op *op_be_Keep;
97 ir_op *op_be_CopyKeep;
98 ir_op *op_be_Call;
99 ir_op *op_be_Return;
100 ir_op *op_be_IncSP;
101 ir_op *op_be_AddSP;
102 ir_op *op_be_SubSP;
103 ir_op *op_be_Start;
104 ir_op *op_be_FrameAddr;
105
106 /**
107  * Compare the attributes of two be_FrameAddr nodes.
108  *
109  * @return zero if both nodes have identically attributes
110  */
111 static int FrameAddr_cmp_attr(const ir_node *a, const ir_node *b)
112 {
113         const be_frame_attr_t *a_attr = (const be_frame_attr_t*)get_irn_generic_attr_const(a);
114         const be_frame_attr_t *b_attr = (const be_frame_attr_t*)get_irn_generic_attr_const(b);
115
116         if (a_attr->ent != b_attr->ent || a_attr->offset != b_attr->offset)
117                 return 1;
118
119         return be_nodes_equal(a, b);
120 }
121
122 /**
123  * Compare the attributes of two be_Return nodes.
124  *
125  * @return zero if both nodes have identically attributes
126  */
127 static int Return_cmp_attr(const ir_node *a, const ir_node *b)
128 {
129         const be_return_attr_t *a_attr = (const be_return_attr_t*)get_irn_generic_attr_const(a);
130         const be_return_attr_t *b_attr = (const be_return_attr_t*)get_irn_generic_attr_const(b);
131
132         if (a_attr->num_ret_vals != b_attr->num_ret_vals)
133                 return 1;
134         if (a_attr->pop != b_attr->pop)
135                 return 1;
136         if (a_attr->emit_pop != b_attr->emit_pop)
137                 return 1;
138
139         return be_nodes_equal(a, b);
140 }
141
142 /**
143  * Compare the attributes of two be_IncSP nodes.
144  *
145  * @return zero if both nodes have identically attributes
146  */
147 static int IncSP_cmp_attr(const ir_node *a, const ir_node *b)
148 {
149         const be_incsp_attr_t *a_attr = (const be_incsp_attr_t*)get_irn_generic_attr_const(a);
150         const be_incsp_attr_t *b_attr = (const be_incsp_attr_t*)get_irn_generic_attr_const(b);
151
152         if (a_attr->offset != b_attr->offset)
153                 return 1;
154
155         return be_nodes_equal(a, b);
156 }
157
158 /**
159  * Compare the attributes of two be_Call nodes.
160  *
161  * @return zero if both nodes have identically attributes
162  */
163 static int Call_cmp_attr(const ir_node *a, const ir_node *b)
164 {
165         const be_call_attr_t *a_attr = (const be_call_attr_t*)get_irn_generic_attr_const(a);
166         const be_call_attr_t *b_attr = (const be_call_attr_t*)get_irn_generic_attr_const(b);
167
168         if (a_attr->ent != b_attr->ent ||
169                 a_attr->call_tp != b_attr->call_tp)
170                 return 1;
171
172         return be_nodes_equal(a, b);
173 }
174
175 static arch_register_req_t *allocate_reg_req(ir_graph *const irg)
176 {
177         struct obstack *obst = be_get_be_obst(irg);
178
179         arch_register_req_t *req = OALLOCZ(obst, arch_register_req_t);
180         return req;
181 }
182
183 void be_set_constr_in(ir_node *node, int pos, const arch_register_req_t *req)
184 {
185         backend_info_t *info = be_get_info(node);
186         assert(pos < get_irn_arity(node));
187         info->in_reqs[pos] = req;
188 }
189
190 void be_set_constr_out(ir_node *node, int pos, const arch_register_req_t *req)
191 {
192         backend_info_t *info = be_get_info(node);
193         info->out_infos[pos].req = req;
194 }
195
196 /**
197  * Initializes the generic attribute of all be nodes and return it.
198  */
199 static void init_node_attr(ir_node *node, int n_inputs, int n_outputs)
200 {
201         assert(n_outputs >= 0);
202
203         ir_graph       *irg  = get_irn_irg(node);
204         struct obstack *obst = be_get_be_obst(irg);
205         backend_info_t *info = be_get_info(node);
206         const arch_register_req_t **in_reqs;
207
208         if (n_inputs >= 0) {
209                 int i;
210                 assert(n_inputs == get_irn_arity(node));
211                 in_reqs = OALLOCN(obst, const arch_register_req_t*, n_inputs);
212                 for (i = 0; i < n_inputs; ++i) {
213                         in_reqs[i] = arch_no_register_req;
214                 }
215         } else {
216                 in_reqs = NEW_ARR_F(const arch_register_req_t*, 0);
217         }
218         info->in_reqs = in_reqs;
219
220         info->out_infos = NEW_ARR_DZ(reg_out_info_t, obst, n_outputs);
221         for (int i = 0; i < n_outputs; ++i) {
222                 info->out_infos[i].req = arch_no_register_req;
223         }
224 }
225
226 static void add_register_req_in(ir_node *node, const arch_register_req_t *req)
227 {
228         backend_info_t *info = be_get_info(node);
229         ARR_APP1(const arch_register_req_t*, info->in_reqs, req);
230 }
231
232 ir_node *be_new_Spill(const arch_register_class_t *cls,
233                 const arch_register_class_t *cls_frame, ir_node *bl,
234                 ir_node *frame, ir_node *to_spill)
235 {
236         be_frame_attr_t *a;
237         ir_node         *in[2];
238         ir_node         *res;
239         ir_graph        *irg = get_Block_irg(bl);
240
241         in[0]     = frame;
242         in[1]     = to_spill;
243         res       = new_ir_node(NULL, irg, bl, op_be_Spill, mode_M, 2, in);
244         init_node_attr(res, 2, 1);
245         a         = (be_frame_attr_t*) get_irn_generic_attr(res);
246         a->ent    = NULL;
247         a->offset = 0;
248         a->base.exc.pin_state = op_pin_state_pinned;
249
250         be_node_set_reg_class_in(res, n_be_Spill_frame, cls_frame);
251         be_node_set_reg_class_in(res, n_be_Spill_val, cls);
252         arch_set_irn_register_req_out(res, 0, arch_no_register_req);
253         arch_add_irn_flags(res, arch_irn_flags_spill);
254
255         return res;
256 }
257
258 ir_node *be_new_Reload(const arch_register_class_t *cls,
259                 const arch_register_class_t *cls_frame, ir_node *block,
260                 ir_node *frame, ir_node *mem, ir_mode *mode)
261 {
262         ir_node  *in[2];
263         ir_node  *res;
264         ir_graph *irg = get_Block_irg(block);
265         be_frame_attr_t *a;
266
267         in[0] = frame;
268         in[1] = mem;
269         res   = new_ir_node(NULL, irg, block, op_be_Reload, mode, 2, in);
270
271         init_node_attr(res, 2, 1);
272         be_node_set_reg_class_out(res, 0, cls);
273
274         be_node_set_reg_class_in(res, n_be_Reload_frame, cls_frame);
275         arch_set_irn_flags(res, arch_irn_flags_rematerializable);
276
277         a         = (be_frame_attr_t*) get_irn_generic_attr(res);
278         a->ent    = NULL;
279         a->offset = 0;
280         a->base.exc.pin_state = op_pin_state_pinned;
281
282         return res;
283 }
284
285 ir_node *be_get_Reload_mem(const ir_node *irn)
286 {
287         assert(be_is_Reload(irn));
288         return get_irn_n(irn, n_be_Reload_mem);
289 }
290
291 ir_node *be_get_Reload_frame(const ir_node *irn)
292 {
293         assert(be_is_Reload(irn));
294         return get_irn_n(irn, n_be_Reload_frame);
295 }
296
297 ir_node *be_get_Spill_val(const ir_node *irn)
298 {
299         assert(be_is_Spill(irn));
300         return get_irn_n(irn, n_be_Spill_val);
301 }
302
303 ir_node *be_get_Spill_frame(const ir_node *irn)
304 {
305         assert(be_is_Spill(irn));
306         return get_irn_n(irn, n_be_Spill_frame);
307 }
308
309 ir_node *be_new_Perm(const arch_register_class_t *cls, ir_node *block,
310                      int n, ir_node *in[])
311 {
312         int            i;
313         ir_graph       *irg = get_Block_irg(block);
314         be_node_attr_t *attr;
315
316         ir_node *irn = new_ir_node(NULL, irg, block, op_be_Perm, mode_T, n, in);
317         init_node_attr(irn, n, n);
318         attr                = (be_node_attr_t*) get_irn_generic_attr(irn);
319         attr->exc.pin_state = op_pin_state_pinned;
320         for (i = 0; i < n; ++i) {
321                 const ir_node             *input = in[i];
322                 const arch_register_req_t *req   = arch_get_irn_register_req(input);
323                 if (req->width == 1) {
324                         be_set_constr_in(irn, i, cls->class_req);
325                         be_set_constr_out(irn, i, cls->class_req);
326                 } else {
327                         arch_register_req_t *const new_req = allocate_reg_req(irg);
328                         new_req->cls   = cls;
329                         new_req->type  = (req->type & arch_register_req_type_aligned);
330                         new_req->width = req->width;
331                         be_set_constr_in(irn, i, new_req);
332                         be_set_constr_out(irn, i, new_req);
333                 }
334         }
335
336         return irn;
337 }
338
339 void be_Perm_reduce(ir_node *perm, int new_size, int *map)
340 {
341         int             arity      = get_irn_arity(perm);
342         const arch_register_req_t **old_in_reqs
343                 = ALLOCAN(const arch_register_req_t*, arity);
344         reg_out_info_t  *old_infos = ALLOCAN(reg_out_info_t, arity);
345         backend_info_t  *info      = be_get_info(perm);
346         ir_node        **new_in;
347         int              i;
348
349         assert(be_is_Perm(perm));
350         assert(new_size <= arity);
351
352         new_in = ALLOCAN(ir_node*, new_size);
353
354         /* save the old register data */
355         memcpy(old_in_reqs, info->in_reqs, arity * sizeof(old_in_reqs[0]));
356         memcpy(old_infos, info->out_infos, arity * sizeof(old_infos[0]));
357
358         /* compose the new in array and set the new register data directly */
359         for (i = 0; i < new_size; ++i) {
360                 int idx = map[i];
361                 new_in[i]          = get_irn_n(perm, idx);
362                 info->in_reqs[i]   = old_in_reqs[idx];
363                 info->out_infos[i] = old_infos[idx];
364         }
365
366         set_irn_in(perm, new_size, new_in);
367 }
368
369 ir_node *be_new_MemPerm(ir_node *block, int n, ir_node *in[])
370 {
371         ir_graph                     *irg       = get_Block_irg(block);
372         const arch_env_t             *arch_env  = be_get_irg_arch_env(irg);
373         ir_node                      *frame     = get_irg_frame(irg);
374         const arch_register_t        *sp        = arch_env->sp;
375         ir_node                      *irn;
376         be_memperm_attr_t            *attr;
377         ir_node                     **real_in;
378
379         real_in = ALLOCAN(ir_node*, n + 1);
380         real_in[0] = frame;
381         memcpy(&real_in[1], in, n * sizeof(real_in[0]));
382
383         irn = new_ir_node(NULL, irg, block, op_be_MemPerm, mode_T, n+1, real_in);
384
385         init_node_attr(irn, n + 1, n);
386         be_node_set_reg_class_in(irn, 0, sp->reg_class);
387
388         attr               = (be_memperm_attr_t*)get_irn_generic_attr(irn);
389         attr->in_entities  = OALLOCNZ(get_irg_obstack(irg), ir_entity*, n);
390         attr->out_entities = OALLOCNZ(get_irg_obstack(irg), ir_entity*, n);
391
392         return irn;
393 }
394
395 ir_node *be_new_Copy(ir_node *bl, ir_node *op)
396 {
397         ir_node *in[1];
398         ir_node *res;
399         be_node_attr_t *attr;
400         ir_graph *irg = get_Block_irg(bl);
401         const arch_register_req_t   *in_req = arch_get_irn_register_req(op);
402         const arch_register_class_t *cls    = in_req->cls;
403
404         in[0] = op;
405         res   = new_ir_node(NULL, irg, bl, op_be_Copy, get_irn_mode(op), 1, in);
406         init_node_attr(res, 1, 1);
407         attr = (be_node_attr_t*) get_irn_generic_attr(res);
408         attr->exc.pin_state = op_pin_state_floats;
409         be_node_set_reg_class_in(res, 0, cls);
410         be_node_set_reg_class_out(res, 0, cls);
411
412         arch_register_req_t *const req = allocate_reg_req(irg);
413         req->cls        = cls;
414         req->type       = arch_register_req_type_should_be_same
415                 | (in_req->type & arch_register_req_type_aligned);
416         req->other_same = 1U << 0;
417         req->width      = in_req->width;
418         be_set_constr_out(res, 0, req);
419
420         return res;
421 }
422
423 ir_node *be_get_Copy_op(const ir_node *cpy)
424 {
425         return get_irn_n(cpy, n_be_Copy_op);
426 }
427
428 ir_node *be_new_Keep(ir_node *block, int n, ir_node *in[])
429 {
430         int i;
431         ir_node *res;
432         ir_graph *irg = get_Block_irg(block);
433         be_node_attr_t *attr;
434
435         res = new_ir_node(NULL, irg, block, op_be_Keep, mode_ANY, -1, NULL);
436         init_node_attr(res, -1, 1);
437         attr = (be_node_attr_t*) get_irn_generic_attr(res);
438         attr->exc.pin_state = op_pin_state_pinned;
439
440         for (i = 0; i < n; ++i) {
441                 ir_node *pred = in[i];
442                 add_irn_n(res, pred);
443                 const arch_register_req_t *req = arch_get_irn_register_req(pred);
444                 req = req->cls != NULL ? req->cls->class_req : arch_no_register_req;
445                 add_register_req_in(res, req);
446         }
447         keep_alive(res);
448
449         return res;
450 }
451
452 void be_Keep_add_node(ir_node *keep, const arch_register_class_t *cls, ir_node *node)
453 {
454         assert(be_is_Keep(keep));
455         add_irn_n(keep, node);
456         add_register_req_in(keep, cls->class_req);
457 }
458
459 ir_node *be_new_Call(dbg_info *dbg, ir_node *bl, ir_node *mem,
460                 const arch_register_req_t *sp_req, ir_node *sp,
461                 const arch_register_req_t *ptr_req, ir_node *ptr,
462                 int n_outs, int n, ir_node *in[], ir_type *call_tp)
463 {
464         be_call_attr_t *a;
465         int real_n = n_be_Call_first_arg + n;
466         ir_node **real_in;
467
468         NEW_ARR_A(ir_node *, real_in, real_n);
469         real_in[n_be_Call_mem] = mem;
470         real_in[n_be_Call_sp]  = sp;
471         real_in[n_be_Call_ptr] = ptr;
472         memcpy(&real_in[n_be_Call_first_arg], in, n * sizeof(in[0]));
473
474         ir_graph *const irg = get_Block_irg(bl);
475         ir_node  *const irn = new_ir_node(dbg, irg, bl, op_be_Call, mode_T, real_n, real_in);
476         init_node_attr(irn, real_n, n_outs);
477         a                     = (be_call_attr_t*)get_irn_generic_attr(irn);
478         a->ent                = NULL;
479         a->call_tp            = call_tp;
480         a->pop                = 0;
481         a->base.exc.pin_state = op_pin_state_pinned;
482         be_set_constr_in(irn, n_be_Call_sp, sp_req);
483         be_set_constr_in(irn, n_be_Call_ptr, ptr_req);
484         return irn;
485 }
486
487 ir_entity *be_Call_get_entity(const ir_node *call)
488 {
489         const be_call_attr_t *a = (const be_call_attr_t*)get_irn_generic_attr_const(call);
490         assert(be_is_Call(call));
491         return a->ent;
492 }
493
494 void be_Call_set_entity(ir_node *call, ir_entity *ent)
495 {
496         be_call_attr_t *a = (be_call_attr_t*)get_irn_generic_attr(call);
497         assert(be_is_Call(call));
498         a->ent = ent;
499 }
500
501 ir_type *be_Call_get_type(ir_node *call)
502 {
503         const be_call_attr_t *a = (const be_call_attr_t*)get_irn_generic_attr_const(call);
504         assert(be_is_Call(call));
505         return a->call_tp;
506 }
507
508 void be_Call_set_type(ir_node *call, ir_type *call_tp)
509 {
510         be_call_attr_t *a = (be_call_attr_t*)get_irn_generic_attr(call);
511         assert(be_is_Call(call));
512         a->call_tp = call_tp;
513 }
514
515 void be_Call_set_pop(ir_node *call, unsigned pop)
516 {
517         be_call_attr_t *a = (be_call_attr_t*)get_irn_generic_attr(call);
518         a->pop = pop;
519 }
520
521 unsigned be_Call_get_pop(const ir_node *call)
522 {
523         const be_call_attr_t *a = (const be_call_attr_t*)get_irn_generic_attr_const(call);
524         return a->pop;
525 }
526
527 ir_node *be_new_Return(dbg_info *const dbg, ir_node *const block, int const n_res, unsigned const pop, int const n, ir_node **const in)
528 {
529         ir_graph *const irg = get_Block_irg(block);
530         ir_node  *const res = new_ir_node(dbg, irg, block, op_be_Return, mode_X, n, in);
531         init_node_attr(res, n, 1);
532         be_set_constr_out(res, 0, arch_no_register_req);
533
534         be_return_attr_t *const a = (be_return_attr_t*)get_irn_generic_attr(res);
535         a->num_ret_vals       = n_res;
536         a->pop                = pop;
537         a->emit_pop           = 0;
538         a->base.exc.pin_state = op_pin_state_pinned;
539
540         return res;
541 }
542
543 int be_Return_get_n_rets(const ir_node *ret)
544 {
545         const be_return_attr_t *a = (const be_return_attr_t*)get_irn_generic_attr_const(ret);
546         return a->num_ret_vals;
547 }
548
549 unsigned be_Return_get_pop(const ir_node *ret)
550 {
551         const be_return_attr_t *a = (const be_return_attr_t*)get_irn_generic_attr_const(ret);
552         return a->pop;
553 }
554
555 int be_Return_get_emit_pop(const ir_node *ret)
556 {
557         const be_return_attr_t *a = (const be_return_attr_t*)get_irn_generic_attr_const(ret);
558         return a->emit_pop;
559 }
560
561 void be_Return_set_emit_pop(ir_node *ret, int emit_pop)
562 {
563         be_return_attr_t *a = (be_return_attr_t*)get_irn_generic_attr(ret);
564         a->emit_pop = emit_pop;
565 }
566
567 ir_node *be_new_IncSP(const arch_register_t *sp, ir_node *bl,
568                       ir_node *old_sp, int offset, int align)
569 {
570         be_incsp_attr_t *a;
571         ir_node *irn;
572         ir_node *in[1];
573         ir_graph *irg = get_Block_irg(bl);
574
575         in[0]     = old_sp;
576         irn       = new_ir_node(NULL, irg, bl, op_be_IncSP, sp->reg_class->mode,
577                                 ARRAY_SIZE(in), in);
578         init_node_attr(irn, 1, 1);
579         a                     = (be_incsp_attr_t*)get_irn_generic_attr(irn);
580         a->offset             = offset;
581         a->align              = align;
582         a->base.exc.pin_state = op_pin_state_pinned;
583
584         /* Set output constraint to stack register. */
585         be_node_set_reg_class_in(irn, 0, sp->reg_class);
586         be_set_constr_single_reg_out(irn, 0, sp, arch_register_req_type_produces_sp);
587
588         return irn;
589 }
590
591 ir_node *be_new_AddSP(const arch_register_t *sp, ir_node *bl, ir_node *old_sp,
592                 ir_node *sz)
593 {
594         ir_node *irn;
595         ir_node *in[n_be_AddSP_last];
596         ir_graph *irg;
597         be_node_attr_t *attr;
598
599         in[n_be_AddSP_old_sp] = old_sp;
600         in[n_be_AddSP_size]   = sz;
601
602         irg = get_Block_irg(bl);
603         irn = new_ir_node(NULL, irg, bl, op_be_AddSP, mode_T, n_be_AddSP_last, in);
604         init_node_attr(irn, n_be_AddSP_last, pn_be_AddSP_last);
605         attr = (be_node_attr_t*) get_irn_generic_attr(irn);
606         attr->exc.pin_state = op_pin_state_pinned;
607
608         /* Set output constraint to stack register. */
609         be_set_constr_single_reg_in(irn, n_be_AddSP_old_sp, sp,
610                                     arch_register_req_type_none);
611         be_node_set_reg_class_in(irn, n_be_AddSP_size, sp->reg_class);
612         be_set_constr_single_reg_out(irn, pn_be_AddSP_sp, sp,
613                                      arch_register_req_type_produces_sp);
614
615         return irn;
616 }
617
618 ir_node *be_new_SubSP(const arch_register_t *sp, ir_node *bl, ir_node *old_sp, ir_node *sz)
619 {
620         ir_node *irn;
621         ir_node *in[n_be_SubSP_last];
622         ir_graph *irg;
623         be_node_attr_t *attr;
624
625         in[n_be_SubSP_old_sp] = old_sp;
626         in[n_be_SubSP_size]   = sz;
627
628         irg = get_Block_irg(bl);
629         irn = new_ir_node(NULL, irg, bl, op_be_SubSP, mode_T, n_be_SubSP_last, in);
630         init_node_attr(irn, n_be_SubSP_last, pn_be_SubSP_last);
631         attr = (be_node_attr_t*) get_irn_generic_attr(irn);
632         attr->exc.pin_state = op_pin_state_pinned;
633
634         /* Set output constraint to stack register. */
635         be_set_constr_single_reg_in(irn, n_be_SubSP_old_sp, sp,
636                                     arch_register_req_type_none);
637         be_node_set_reg_class_in(irn, n_be_SubSP_size, sp->reg_class);
638         be_set_constr_single_reg_out(irn, pn_be_SubSP_sp, sp, arch_register_req_type_produces_sp);
639
640         return irn;
641 }
642
643 ir_node *be_new_Start(dbg_info *dbgi, ir_node *bl, int n_outs)
644 {
645         ir_node *res;
646         ir_graph *irg = get_Block_irg(bl);
647         be_node_attr_t *attr;
648
649         res = new_ir_node(dbgi, irg, bl, op_be_Start, mode_T, 0, NULL);
650         init_node_attr(res, 0, n_outs);
651         attr = (be_node_attr_t*) get_irn_generic_attr(res);
652         attr->exc.pin_state = op_pin_state_pinned;
653
654         return res;
655 }
656
657 ir_node *be_new_FrameAddr(const arch_register_class_t *cls_frame, ir_node *bl, ir_node *frame, ir_entity *ent)
658 {
659         be_frame_attr_t *a;
660         ir_node *irn;
661         ir_node *in[1];
662         ir_graph *irg = get_Block_irg(bl);
663
664         in[0]  = frame;
665         irn    = new_ir_node(NULL, irg, bl, op_be_FrameAddr, get_irn_mode(frame), 1, in);
666         init_node_attr(irn, 1, 1);
667         a                     = (be_frame_attr_t*)get_irn_generic_attr(irn);
668         a->ent                = ent;
669         a->offset             = 0;
670         a->base.exc.pin_state = op_pin_state_floats;
671         be_node_set_reg_class_in(irn, 0, cls_frame);
672         be_node_set_reg_class_out(irn, 0, cls_frame);
673
674         return optimize_node(irn);
675 }
676
677 ir_node *be_get_FrameAddr_frame(const ir_node *node)
678 {
679         assert(be_is_FrameAddr(node));
680         return get_irn_n(node, n_be_FrameAddr_ptr);
681 }
682
683 ir_entity *be_get_FrameAddr_entity(const ir_node *node)
684 {
685         const be_frame_attr_t *attr = (const be_frame_attr_t*)get_irn_generic_attr_const(node);
686         return attr->ent;
687 }
688
689 ir_node *be_new_CopyKeep(ir_node *bl, ir_node *src, int n, ir_node *in_keep[])
690 {
691         ir_node  *irn;
692         ir_node **in = ALLOCAN(ir_node*, n + 1);
693         ir_graph *irg = get_Block_irg(bl);
694         const arch_register_req_t   *req  = arch_get_irn_register_req(src);
695         const arch_register_class_t *cls  = req->cls;
696         ir_mode                     *mode = get_irn_mode(src);
697         be_node_attr_t *attr;
698
699         in[0] = src;
700         memcpy(&in[1], in_keep, n * sizeof(in[0]));
701         irn   = new_ir_node(NULL, irg, bl, op_be_CopyKeep, mode, n + 1, in);
702         init_node_attr(irn, n + 1, 1);
703         attr = (be_node_attr_t*) get_irn_generic_attr(irn);
704         attr->exc.pin_state = op_pin_state_floats;
705         be_node_set_reg_class_in(irn, 0, cls);
706         be_node_set_reg_class_out(irn, 0, cls);
707         for (int i = 0; i < n; ++i) {
708                 ir_node *pred = in_keep[i];
709                 const arch_register_req_t *req = arch_get_irn_register_req(pred);
710                 req = req->cls != NULL ? req->cls->class_req : arch_no_register_req;
711                 be_set_constr_in(irn, i+1, req);
712         }
713
714         return irn;
715 }
716
717 ir_node *be_new_CopyKeep_single(ir_node *bl, ir_node *src, ir_node *keep)
718 {
719         return be_new_CopyKeep(bl, src, 1, &keep);
720 }
721
722 ir_node *be_get_CopyKeep_op(const ir_node *cpy)
723 {
724         return get_irn_n(cpy, n_be_CopyKeep_op);
725 }
726
727 void be_set_CopyKeep_op(ir_node *cpy, ir_node *op)
728 {
729         set_irn_n(cpy, n_be_CopyKeep_op, op);
730 }
731
732 static bool be_has_frame_entity(const ir_node *irn)
733 {
734         switch (get_irn_opcode(irn)) {
735         case beo_Spill:
736         case beo_Reload:
737         case beo_FrameAddr:
738                 return true;
739         default:
740                 return false;
741         }
742 }
743
744 ir_entity *be_get_frame_entity(const ir_node *irn)
745 {
746         if (be_has_frame_entity(irn)) {
747                 const be_frame_attr_t *a = (const be_frame_attr_t*)get_irn_generic_attr_const(irn);
748                 return a->ent;
749         }
750         return NULL;
751 }
752
753 int be_get_frame_offset(const ir_node *irn)
754 {
755         assert(is_be_node(irn));
756         if (be_has_frame_entity(irn)) {
757                 const be_frame_attr_t *a = (const be_frame_attr_t*)get_irn_generic_attr_const(irn);
758                 return a->offset;
759         }
760         return 0;
761 }
762
763 void be_set_MemPerm_in_entity(const ir_node *irn, int n, ir_entity *ent)
764 {
765         const be_memperm_attr_t *attr = (const be_memperm_attr_t*)get_irn_generic_attr_const(irn);
766
767         assert(be_is_MemPerm(irn));
768         assert(n < be_get_MemPerm_entity_arity(irn));
769
770         attr->in_entities[n] = ent;
771 }
772
773 ir_entity* be_get_MemPerm_in_entity(const ir_node* irn, int n)
774 {
775         const be_memperm_attr_t *attr = (const be_memperm_attr_t*)get_irn_generic_attr_const(irn);
776
777         assert(be_is_MemPerm(irn));
778         assert(n < be_get_MemPerm_entity_arity(irn));
779
780         return attr->in_entities[n];
781 }
782
783 void be_set_MemPerm_out_entity(const ir_node *irn, int n, ir_entity *ent)
784 {
785         const be_memperm_attr_t *attr = (const be_memperm_attr_t*)get_irn_generic_attr_const(irn);
786
787         assert(be_is_MemPerm(irn));
788         assert(n < be_get_MemPerm_entity_arity(irn));
789
790         attr->out_entities[n] = ent;
791 }
792
793 ir_entity* be_get_MemPerm_out_entity(const ir_node* irn, int n)
794 {
795         const be_memperm_attr_t *attr = (const be_memperm_attr_t*)get_irn_generic_attr_const(irn);
796
797         assert(be_is_MemPerm(irn));
798         assert(n < be_get_MemPerm_entity_arity(irn));
799
800         return attr->out_entities[n];
801 }
802
803 int be_get_MemPerm_entity_arity(const ir_node *irn)
804 {
805         return get_irn_arity(irn) - 1;
806 }
807
808 const arch_register_req_t *be_create_reg_req(struct obstack *obst,
809                 const arch_register_t *reg, arch_register_req_type_t additional_types)
810 {
811         arch_register_req_t         *req = OALLOC(obst, arch_register_req_t);
812         const arch_register_class_t *cls = reg->reg_class;
813         unsigned                    *limited_bitset;
814
815         limited_bitset = rbitset_obstack_alloc(obst, arch_register_class_n_regs(cls));
816         rbitset_set(limited_bitset, reg->index);
817
818         req->type    = arch_register_req_type_limited | additional_types;
819         req->cls     = cls;
820         req->limited = limited_bitset;
821         req->width   = 1;
822         return req;
823 }
824
825 void be_set_constr_single_reg_in(ir_node *node, int pos,
826                 const arch_register_t *reg, arch_register_req_type_t additional_types)
827 {
828         const arch_register_req_t *req;
829
830         if (additional_types == 0) {
831                 req = reg->single_req;
832         } else {
833                 ir_graph       *irg  = get_irn_irg(node);
834                 struct obstack *obst = be_get_be_obst(irg);
835                 req = be_create_reg_req(obst, reg, additional_types);
836         }
837         be_set_constr_in(node, pos, req);
838 }
839
840 void be_set_constr_single_reg_out(ir_node *node, int pos,
841                 const arch_register_t *reg, arch_register_req_type_t additional_types)
842 {
843         ir_graph                  *irg  = get_irn_irg(node);
844         be_irg_t                  *birg = be_birg_from_irg(irg);
845         const arch_register_req_t *req;
846
847         /* if we have an ignore register, add ignore flag and just assign it */
848         if (!rbitset_is_set(birg->allocatable_regs, reg->global_index)) {
849                 additional_types |= arch_register_req_type_ignore;
850         }
851
852         if (additional_types == 0) {
853                 req = reg->single_req;
854         } else {
855                 struct obstack *obst = be_get_be_obst(irg);
856                 req = be_create_reg_req(obst, reg, additional_types);
857         }
858
859         arch_set_irn_register_out(node, pos, reg);
860         be_set_constr_out(node, pos, req);
861 }
862
863 void be_node_set_reg_class_in(ir_node *irn, int pos,
864                               const arch_register_class_t *cls)
865 {
866         be_set_constr_in(irn, pos, cls->class_req);
867 }
868
869 void be_node_set_reg_class_out(ir_node *irn, int pos,
870                                const arch_register_class_t *cls)
871 {
872         be_set_constr_out(irn, pos, cls->class_req);
873 }
874
875 ir_node *be_get_IncSP_pred(ir_node *irn)
876 {
877         assert(be_is_IncSP(irn));
878         return get_irn_n(irn, 0);
879 }
880
881 void be_set_IncSP_pred(ir_node *incsp, ir_node *pred)
882 {
883         assert(be_is_IncSP(incsp));
884         set_irn_n(incsp, 0, pred);
885 }
886
887 void be_set_IncSP_offset(ir_node *irn, int offset)
888 {
889         be_incsp_attr_t *a = (be_incsp_attr_t*)get_irn_generic_attr(irn);
890         assert(be_is_IncSP(irn));
891         a->offset = offset;
892 }
893
894 int be_get_IncSP_offset(const ir_node *irn)
895 {
896         const be_incsp_attr_t *a = (const be_incsp_attr_t*)get_irn_generic_attr_const(irn);
897         assert(be_is_IncSP(irn));
898         return a->offset;
899 }
900
901 int be_get_IncSP_align(const ir_node *irn)
902 {
903         const be_incsp_attr_t *a = (const be_incsp_attr_t*)get_irn_generic_attr_const(irn);
904         assert(be_is_IncSP(irn));
905         return a->align;
906 }
907
908 static ir_entity *be_node_get_frame_entity(const ir_node *irn)
909 {
910         return be_get_frame_entity(irn);
911 }
912
913 void be_node_set_frame_entity(ir_node *irn, ir_entity *ent)
914 {
915         be_frame_attr_t *a;
916
917         assert(be_has_frame_entity(irn));
918
919         a = (be_frame_attr_t*)get_irn_generic_attr(irn);
920         a->ent = ent;
921 }
922
923 static void be_node_set_frame_offset(ir_node *irn, int offset)
924 {
925         be_frame_attr_t *a;
926
927         if (!be_has_frame_entity(irn))
928                 return;
929
930         a = (be_frame_attr_t*)get_irn_generic_attr(irn);
931         a->offset = offset;
932 }
933
934 static int be_node_get_sp_bias(const ir_node *irn)
935 {
936         if (be_is_IncSP(irn))
937                 return be_get_IncSP_offset(irn);
938         if (be_is_Call(irn))
939                 return -(int)be_Call_get_pop(irn);
940
941         return 0;
942 }
943
944
945
946 /* for be nodes */
947 static const arch_irn_ops_t be_node_irn_ops = {
948         be_node_get_frame_entity,
949         be_node_set_frame_offset,
950         be_node_get_sp_bias,
951         NULL,    /* get_op_estimated_cost   */
952         NULL,    /* possible_memory_operand */
953         NULL,    /* perform_memory_operand  */
954 };
955
956 static int get_start_reg_index(ir_graph *irg, const arch_register_t *reg)
957 {
958         ir_node *start  = get_irg_start(irg);
959
960         /* do a naive linear search... */
961         be_foreach_out(start, i) {
962                 arch_register_req_t const *const out_req = arch_get_irn_register_req_out(start, i);
963                 if (!arch_register_req_is(out_req, limited))
964                         continue;
965                 if (out_req->cls != reg->reg_class)
966                         continue;
967                 if (!rbitset_is_set(out_req->limited, reg->index))
968                         continue;
969                 return i;
970         }
971         panic("Tried querying undefined register '%s' at Start", reg->name);
972 }
973
974 ir_node *be_get_initial_reg_value(ir_graph *irg, const arch_register_t *reg)
975 {
976         int      i     = get_start_reg_index(irg, reg);
977         ir_node *start = get_irg_start(irg);
978         ir_mode *mode  = arch_register_class_mode(reg->reg_class);
979
980         foreach_out_edge(start, edge) {
981                 ir_node *proj = get_edge_src_irn(edge);
982                 if (!is_Proj(proj)) // maybe End/Anchor
983                         continue;
984                 if (get_Proj_proj(proj) == i) {
985                         return proj;
986                 }
987         }
988         return new_r_Proj(start, mode, i);
989 }
990
991 static ir_entity* dummy_get_frame_entity(const ir_node *node)
992 {
993         (void) node;
994         return NULL;
995 }
996
997 static void dummy_set_frame_offset(ir_node *node, int bias)
998 {
999         (void) node;
1000         (void) bias;
1001         panic("should not be called");
1002 }
1003
1004 static int dummy_get_sp_bias(const ir_node *node)
1005 {
1006         (void) node;
1007         return 0;
1008 }
1009
1010 /* for "middleend" nodes */
1011 static const arch_irn_ops_t dummy_be_irn_ops = {
1012         dummy_get_frame_entity,
1013         dummy_set_frame_offset,
1014         dummy_get_sp_bias,
1015         NULL,      /* get_op_estimated_cost */
1016         NULL,      /* possible_memory_operand */
1017         NULL,      /* perform_memory_operand */
1018 };
1019
1020
1021
1022 ir_node *be_new_Phi(ir_node *block, int n_ins, ir_node **ins, ir_mode *mode,
1023                     const arch_register_req_t *req)
1024 {
1025         ir_graph       *irg  = get_irn_irg(block);
1026         struct obstack *obst = be_get_be_obst(irg);
1027         backend_info_t *info;
1028         int             i;
1029
1030         ir_node *phi = new_ir_node(NULL, irg, block, op_Phi, mode, n_ins, ins);
1031         phi->attr.phi.u.backedge = new_backedge_arr(get_irg_obstack(irg), n_ins);
1032         info = be_get_info(phi);
1033         info->out_infos = NEW_ARR_DZ(reg_out_info_t, obst, 1);
1034         info->in_reqs   = OALLOCN(obst, const arch_register_req_t*, n_ins);
1035
1036         info->out_infos[0].req = req;
1037         for (i = 0; i < n_ins; ++i) {
1038                 info->in_reqs[i] = req;
1039         }
1040         irn_verify_irg(phi, irg);
1041         phi = optimize_node(phi);
1042         return phi;
1043 }
1044
1045 void be_set_phi_reg_req(ir_node *node, const arch_register_req_t *req)
1046 {
1047         int arity = get_irn_arity(node);
1048         int i;
1049
1050         backend_info_t *info = be_get_info(node);
1051         info->out_infos[0].req = req;
1052         for (i = 0; i < arity; ++i) {
1053                 info->in_reqs[i] = req;
1054         }
1055
1056         assert(mode_is_datab(get_irn_mode(node)));
1057 }
1058
1059 void be_dump_phi_reg_reqs(FILE *F, const ir_node *node, dump_reason_t reason)
1060 {
1061         ir_graph *irg = get_irn_irg(node);
1062         if (!irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_BACKEND))
1063                 return;
1064
1065         switch (reason) {
1066         case dump_node_opcode_txt:
1067                 fputs(get_op_name(get_irn_op(node)), F);
1068                 break;
1069         case dump_node_mode_txt:
1070                 fprintf(F, "%s", get_mode_name(get_irn_mode(node)));
1071                 break;
1072         case dump_node_nodeattr_txt:
1073                 break;
1074         case dump_node_info_txt:
1075                 arch_dump_reqs_and_registers(F, node);
1076                 break;
1077
1078         default:
1079                 break;
1080         }
1081 }
1082
1083 static const arch_irn_ops_t phi_irn_ops = {
1084         dummy_get_frame_entity,
1085         dummy_set_frame_offset,
1086         dummy_get_sp_bias,
1087         NULL,    /* get_op_estimated_cost   */
1088         NULL,    /* possible_memory_operand */
1089         NULL,    /* perform_memory_operand  */
1090 };
1091
1092
1093
1094 /**
1095  * ir_op-Operation: dump a be node to file
1096  */
1097 static void dump_node(FILE *f, const ir_node *irn, dump_reason_t reason)
1098 {
1099         assert(is_be_node(irn));
1100
1101         switch (reason) {
1102                 case dump_node_opcode_txt:
1103                         fputs(get_op_name(get_irn_op(irn)), f);
1104                         break;
1105                 case dump_node_mode_txt:
1106                         if (be_is_Copy(irn) || be_is_CopyKeep(irn)) {
1107                                 fprintf(f, "%s", get_mode_name(get_irn_mode(irn)));
1108                         }
1109                         break;
1110                 case dump_node_nodeattr_txt:
1111                         if (be_is_Call(irn)) {
1112                                 const be_call_attr_t *a = (const be_call_attr_t*)get_irn_generic_attr_const(irn);
1113                                 if (a->ent)
1114                                         fprintf(f, " [%s] ", get_entity_name(a->ent));
1115                         }
1116                         if (be_is_IncSP(irn)) {
1117                                 const be_incsp_attr_t *attr = (const be_incsp_attr_t*)get_irn_generic_attr_const(irn);
1118                                 fprintf(f, " [%d] ", attr->offset);
1119                         }
1120                         break;
1121                 case dump_node_info_txt:
1122                         arch_dump_reqs_and_registers(f, irn);
1123
1124                         if (be_has_frame_entity(irn)) {
1125                                 const be_frame_attr_t *a = (const be_frame_attr_t*)get_irn_generic_attr_const(irn);
1126                                 if (a->ent) {
1127                                         unsigned size = get_type_size_bytes(get_entity_type(a->ent));
1128                                         ir_fprintf(f, "frame entity: %+F, offset 0x%x (%d), size 0x%x (%d) bytes\n",
1129                                           a->ent, a->offset, a->offset, size, size);
1130                                 }
1131
1132                         }
1133
1134                         switch (get_irn_opcode(irn)) {
1135                         case beo_IncSP: {
1136                                 const be_incsp_attr_t *a = (const be_incsp_attr_t*)get_irn_generic_attr_const(irn);
1137                                 fprintf(f, "align: %d\n", a->align);
1138                                 fprintf(f, "offset: %d\n", a->offset);
1139                                 break;
1140                         }
1141                         case beo_Call: {
1142                                 const be_call_attr_t *a = (const be_call_attr_t*)get_irn_generic_attr_const(irn);
1143
1144                                 if (a->ent)
1145                                         fprintf(f, "\ncalling: %s\n", get_entity_name(a->ent));
1146                                 break;
1147                         }
1148                         case beo_MemPerm: {
1149                                 int i;
1150                                 for (i = 0; i < be_get_MemPerm_entity_arity(irn); ++i) {
1151                                         ir_entity *in, *out;
1152                                         in = be_get_MemPerm_in_entity(irn, i);
1153                                         out = be_get_MemPerm_out_entity(irn, i);
1154                                         if (in) {
1155                                                 fprintf(f, "\nin[%d]: %s\n", i, get_entity_name(in));
1156                                         }
1157                                         if (out) {
1158                                                 fprintf(f, "\nout[%d]: %s\n", i, get_entity_name(out));
1159                                         }
1160                                 }
1161                                 break;
1162                         }
1163
1164                         default:
1165                                 break;
1166                         }
1167         }
1168 }
1169
1170 /**
1171  * ir_op-Operation:
1172  * Copies the backend specific attributes from old node to new node.
1173  */
1174 static void copy_attr(ir_graph *irg, const ir_node *old_node, ir_node *new_node)
1175 {
1176         const void     *old_attr = get_irn_generic_attr_const(old_node);
1177         void           *new_attr = get_irn_generic_attr(new_node);
1178         struct obstack *obst     = be_get_be_obst(irg);
1179         backend_info_t *old_info = be_get_info(old_node);
1180         backend_info_t *new_info = be_get_info(new_node);
1181
1182         assert(is_be_node(old_node));
1183         assert(is_be_node(new_node));
1184
1185         memcpy(new_attr, old_attr, get_op_attr_size(get_irn_op(old_node)));
1186
1187         new_info->flags     = old_info->flags;
1188         new_info->out_infos = old_info->out_infos ? DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos) : NULL;
1189
1190         /* input infos */
1191         if (old_info->in_reqs != NULL) {
1192                 unsigned n_ins = get_irn_arity(old_node);
1193                 /* need dynamic in infos? */
1194                 if (get_irn_op(old_node)->opar == oparity_dynamic) {
1195                         new_info->in_reqs = NEW_ARR_F(const arch_register_req_t*, n_ins);
1196                 } else {
1197                         new_info->in_reqs = OALLOCN(obst,const arch_register_req_t*, n_ins);
1198                 }
1199                 memcpy(new_info->in_reqs, old_info->in_reqs,
1200                        n_ins * sizeof(new_info->in_reqs[0]));
1201         } else {
1202                 new_info->in_reqs = NULL;
1203         }
1204 }
1205
1206 int is_be_node(const ir_node *irn)
1207 {
1208         return get_op_ops(get_irn_op(irn))->be_ops == &be_node_irn_ops;
1209 }
1210
1211 static ir_op *new_be_op(unsigned code, const char *name, op_pin_state p,
1212                         irop_flags flags, op_arity opar, size_t attr_size)
1213 {
1214         ir_op *res = new_ir_op(code, name, p, flags, opar, 0, attr_size);
1215         res->ops.dump_node = dump_node;
1216         res->ops.copy_attr = copy_attr;
1217         res->ops.be_ops    = &be_node_irn_ops;
1218         return res;
1219 }
1220
1221 void be_init_op(void)
1222 {
1223         unsigned opc;
1224
1225         assert(op_be_Spill == NULL);
1226
1227         /* Acquire all needed opcodes. */
1228         op_be_Spill     = new_be_op(beo_Spill,     "be_Spill",     op_pin_state_exc_pinned, irop_flag_none,                          oparity_unary,    sizeof(be_frame_attr_t));
1229         op_be_Reload    = new_be_op(beo_Reload,    "be_Reload",    op_pin_state_exc_pinned, irop_flag_none,                          oparity_zero,     sizeof(be_frame_attr_t));
1230         op_be_Perm      = new_be_op(beo_Perm,      "be_Perm",      op_pin_state_exc_pinned, irop_flag_none,                          oparity_variable, sizeof(be_node_attr_t));
1231         op_be_MemPerm   = new_be_op(beo_MemPerm,   "be_MemPerm",   op_pin_state_exc_pinned, irop_flag_none,                          oparity_variable, sizeof(be_memperm_attr_t));
1232         op_be_Copy      = new_be_op(beo_Copy,      "be_Copy",      op_pin_state_exc_pinned, irop_flag_none,                          oparity_unary,    sizeof(be_node_attr_t));
1233         op_be_Keep      = new_be_op(beo_Keep,      "be_Keep",      op_pin_state_exc_pinned, irop_flag_keep,                          oparity_dynamic,  sizeof(be_node_attr_t));
1234         op_be_CopyKeep  = new_be_op(beo_CopyKeep,  "be_CopyKeep",  op_pin_state_exc_pinned, irop_flag_keep,                          oparity_variable, sizeof(be_node_attr_t));
1235         op_be_Call      = new_be_op(beo_Call,      "be_Call",      op_pin_state_exc_pinned, irop_flag_fragile|irop_flag_uses_memory, oparity_variable, sizeof(be_call_attr_t));
1236         ir_op_set_memory_index(op_be_Call, n_be_Call_mem);
1237         ir_op_set_fragile_indices(op_be_Call, pn_be_Call_X_regular, pn_be_Call_X_except);
1238         op_be_Return    = new_be_op(beo_Return,    "be_Return",    op_pin_state_exc_pinned, irop_flag_cfopcode,                      oparity_variable, sizeof(be_return_attr_t));
1239         op_be_AddSP     = new_be_op(beo_AddSP,     "be_AddSP",     op_pin_state_exc_pinned, irop_flag_none,                          oparity_unary,    sizeof(be_node_attr_t));
1240         op_be_SubSP     = new_be_op(beo_SubSP,     "be_SubSP",     op_pin_state_exc_pinned, irop_flag_none,                          oparity_unary,    sizeof(be_node_attr_t));
1241         op_be_IncSP     = new_be_op(beo_IncSP,     "be_IncSP",     op_pin_state_exc_pinned, irop_flag_none,                          oparity_unary,    sizeof(be_incsp_attr_t));
1242         op_be_Start     = new_be_op(beo_Start,     "be_Start",     op_pin_state_exc_pinned, irop_flag_none,                          oparity_zero,     sizeof(be_node_attr_t));
1243         op_be_FrameAddr = new_be_op(beo_FrameAddr, "be_FrameAddr", op_pin_state_exc_pinned, irop_flag_none,                          oparity_unary,    sizeof(be_frame_attr_t));
1244
1245         op_be_Spill->ops.node_cmp_attr     = FrameAddr_cmp_attr;
1246         op_be_Reload->ops.node_cmp_attr    = FrameAddr_cmp_attr;
1247         op_be_Perm->ops.node_cmp_attr      = be_nodes_equal;
1248         op_be_MemPerm->ops.node_cmp_attr   = be_nodes_equal;
1249         op_be_Copy->ops.node_cmp_attr      = be_nodes_equal;
1250         op_be_Keep->ops.node_cmp_attr      = be_nodes_equal;
1251         op_be_CopyKeep->ops.node_cmp_attr  = be_nodes_equal;
1252         op_be_Call->ops.node_cmp_attr      = Call_cmp_attr;
1253         op_be_Return->ops.node_cmp_attr    = Return_cmp_attr;
1254         op_be_AddSP->ops.node_cmp_attr     = be_nodes_equal;
1255         op_be_SubSP->ops.node_cmp_attr     = be_nodes_equal;
1256         op_be_IncSP->ops.node_cmp_attr     = IncSP_cmp_attr;
1257         op_be_Start->ops.node_cmp_attr     = be_nodes_equal;
1258         op_be_FrameAddr->ops.node_cmp_attr = FrameAddr_cmp_attr;
1259
1260         /* attach out dummy_ops to middle end nodes */
1261         for (opc = iro_First; opc <= iro_Last; ++opc) {
1262                 ir_op *op = ir_get_opcode(opc);
1263                 assert(op->ops.be_ops == NULL);
1264                 op->ops.be_ops = &dummy_be_irn_ops;
1265         }
1266
1267         op_Phi->ops.be_ops = &phi_irn_ops;
1268 }
1269
1270 void be_finish_op(void)
1271 {
1272         free_ir_op(op_be_Spill);     op_be_Spill     = NULL;
1273         free_ir_op(op_be_Reload);    op_be_Reload    = NULL;
1274         free_ir_op(op_be_Perm);      op_be_Perm      = NULL;
1275         free_ir_op(op_be_MemPerm);   op_be_MemPerm   = NULL;
1276         free_ir_op(op_be_Copy);      op_be_Copy      = NULL;
1277         free_ir_op(op_be_Keep);      op_be_Keep      = NULL;
1278         free_ir_op(op_be_CopyKeep);  op_be_CopyKeep  = NULL;
1279         free_ir_op(op_be_Call);      op_be_Call      = NULL;
1280         free_ir_op(op_be_Return);    op_be_Return    = NULL;
1281         free_ir_op(op_be_IncSP);     op_be_IncSP     = NULL;
1282         free_ir_op(op_be_AddSP);     op_be_AddSP     = NULL;
1283         free_ir_op(op_be_SubSP);     op_be_SubSP     = NULL;
1284         free_ir_op(op_be_Start);     op_be_Start     = NULL;
1285         free_ir_op(op_be_FrameAddr); op_be_FrameAddr = NULL;
1286 }