+ irn = new_ir_node(NULL, irg, bl, op_be_Call, mode_T, real_n, real_in);
+ init_node_attr(irn, (n_outs > real_n ? n_outs : real_n));
+ return irn;
+}
+
+entity *be_Call_get_entity(const ir_node *call)
+{
+ be_call_attr_t *a = get_irn_attr(call);
+ assert(be_is_Call(call));
+ return a->ent;
+}
+
+void be_Call_set_entity(ir_node *call, entity *ent)
+{
+ be_call_attr_t *a = get_irn_attr(call);
+ assert(be_is_Call(call));
+ a->ent = ent;
+}
+
+ir_node *be_new_Return(dbg_info *dbg, ir_graph *irg, ir_node *bl, int n, ir_node *in[])
+{
+ ir_node *irn = new_ir_node(dbg, irg, bl, op_be_Return, mode_X, n, in);
+ init_node_attr(irn, n);
+
+ return irn;
+}
+
+ir_node *be_new_IncSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *mem, unsigned offset, be_stack_dir_t dir)
+{
+ be_stack_attr_t *a;
+ ir_node *irn;
+ ir_node *in[1];
+
+ in[0] = old_sp;
+ in[1] = mem;
+ irn = new_ir_node(NULL, irg, bl, op_be_IncSP, sp->reg_class->mode, 2, in);
+ a = init_node_attr(irn, 1);
+ a->dir = dir;
+ a->offset = offset;
+
+ be_node_set_flags(irn, -1, arch_irn_flags_ignore);
+
+ /* Set output constraint to stack register. */
+ be_node_set_reg_class(irn, 0, sp->reg_class);
+ be_set_constr_single_reg(irn, -1, sp);
+ be_node_set_irn_reg(NULL, irn, sp);
+
+ return irn;
+}
+
+ir_node *be_new_AddSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *sz)
+{
+ be_node_attr_t *a;
+ ir_node *irn;
+ ir_node *in[be_pos_AddSP_last];
+
+ in[be_pos_AddSP_old_sp] = old_sp;
+ in[be_pos_AddSP_size] = sz;
+
+ irn = new_ir_node(NULL, irg, bl, op_be_AddSP, mode_T, be_pos_AddSP_last, in);
+ a = init_node_attr(irn, be_pos_AddSP_last);
+
+ be_node_set_flags(irn, OUT_POS(0), arch_irn_flags_ignore);
+
+ /* Set output constraint to stack register. */
+ be_set_constr_single_reg(irn, OUT_POS(0), sp);
+
+ return irn;
+}
+
+ir_node *be_new_SetSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *op, ir_node *mem)
+{
+ be_node_attr_t *a;
+ ir_node *irn;
+ ir_node *in[3];
+
+ in[0] = mem;
+ in[1] = old_sp;
+ in[2] = op;
+ irn = new_ir_node(NULL, irg, bl, op_be_SetSP, get_irn_mode(old_sp), 3, in);
+ a = init_node_attr(irn, 3);
+
+ be_node_set_flags(irn, OUT_POS(0), arch_irn_flags_ignore);
+
+ /* Set output constraint to stack register. */
+ be_set_constr_single_reg(irn, OUT_POS(0), sp);
+ be_node_set_reg_class(irn, 1, sp->reg_class);
+ be_node_set_reg_class(irn, 2, sp->reg_class);
+ be_node_set_irn_reg(NULL, irn, sp);
+
+ return irn;
+}
+
+ir_node *be_new_StackParam(const arch_register_class_t *cls, const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_mode *mode, ir_node *frame_pointer, entity *ent)
+{
+ be_frame_attr_t *a;
+ ir_node *irn;
+ ir_node *in[1];
+
+ in[0] = frame_pointer;
+ irn = new_ir_node(NULL, irg, bl, op_be_StackParam, mode, 1, in);
+ a = init_node_attr(irn, 1);
+ a->ent = ent;
+
+ be_node_set_reg_class(irn, 0, cls_frame);
+ be_node_set_reg_class(irn, OUT_POS(0), cls);
+ return irn;
+}
+
+ir_node *be_new_RegParams(ir_graph *irg, ir_node *bl, int n_outs)
+{
+ ir_node *irn;
+ ir_node *in[1];
+
+ irn = new_ir_node(NULL, irg, bl, op_be_RegParams, mode_T, 0, in);
+ init_node_attr(irn, n_outs);
+ return irn;
+}
+
+ir_node *be_new_FrameLoad(const arch_register_class_t *cls_frame, const arch_register_class_t *cls_data,
+ ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *frame, entity *ent)
+{
+ be_frame_attr_t *a;
+ ir_node *irn;
+ ir_node *in[2];
+
+ in[0] = mem;
+ in[1] = frame;
+ irn = new_ir_node(NULL, irg, bl, op_be_FrameLoad, mode_T, 2, in);
+ a = init_node_attr(irn, 3);
+ a->ent = ent;
+ a->offset = 0;
+ be_node_set_reg_class(irn, 1, cls_frame);
+ be_node_set_reg_class(irn, OUT_POS(pn_Load_res), cls_data);
+ return irn;
+}
+
+ir_node *be_new_FrameStore(const arch_register_class_t *cls_frame, const arch_register_class_t *cls_data,
+ ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *frame, ir_node *data, entity *ent)
+{
+ be_frame_attr_t *a;
+ ir_node *irn;
+ ir_node *in[3];
+
+ in[0] = mem;
+ in[1] = frame;
+ in[2] = data;
+ irn = new_ir_node(NULL, irg, bl, op_be_FrameStore, mode_T, 3, in);
+ a = init_node_attr(irn, 3);
+ a->ent = ent;
+ a->offset = 0;
+ be_node_set_reg_class(irn, 1, cls_frame);
+ be_node_set_reg_class(irn, 2, cls_data);
+ return irn;
+}
+
+ir_node *be_new_FrameAddr(const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_node *frame, entity *ent)
+{
+ be_frame_attr_t *a;
+ ir_node *irn;
+ ir_node *in[1];
+
+ in[0] = frame;
+ irn = new_ir_node(NULL, irg, bl, op_be_FrameAddr, get_irn_mode(frame), 1, in);
+ a = init_node_attr(irn, 1);
+ a->ent = ent;
+ a->offset = 0;
+ be_node_set_reg_class(irn, 0, cls_frame);
+ be_node_set_reg_class(irn, OUT_POS(0), cls_frame);
+ return irn;
+}
+
+ir_node *be_new_CopyKeep(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *src, int n, ir_node *in_keep[], ir_mode *mode)
+{
+ ir_node *irn;
+ ir_node **in = (ir_node **) alloca((n + 1) * sizeof(in[0]));
+
+ in[0] = src;
+ memcpy(&in[1], in_keep, n * sizeof(in[0]));
+ irn = new_ir_node(NULL, irg, bl, op_be_CopyKeep, mode, n + 1, in);
+ init_node_attr(irn, n + 1);
+ be_node_set_reg_class(irn, OUT_POS(0), cls);
+ be_node_set_reg_class(irn, 0, cls);
+
+ return irn;
+}
+
+ir_node *be_new_CopyKeep_single(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *src, ir_node *keep, ir_mode *mode)
+{
+ ir_node *in[1];
+
+ in[0] = keep;
+ return be_new_CopyKeep(cls, irg, bl, src, 1, in, mode);
+}
+
+ir_node *be_new_Barrier(ir_graph *irg, ir_node *bl, int n, ir_node *in[])
+{
+ ir_node *irn;
+
+ irn = new_ir_node(NULL, irg, bl, op_be_Barrier, mode_T, n, in);
+ init_node_attr(irn, n);
+ return irn;
+}
+
+int be_is_Spill (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Spill ; }
+int be_is_Reload (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Reload ; }
+int be_is_Copy (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Copy ; }
+int be_is_Perm (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Perm ; }
+int be_is_Keep (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Keep ; }
+int be_is_Call (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Call ; }
+int be_is_Return (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Return ; }
+int be_is_IncSP (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_IncSP ; }
+int be_is_SetSP (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_SetSP ; }
+int be_is_AddSP (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_AddSP ; }
+int be_is_RegParams (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_RegParams ; }
+int be_is_StackParam (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_StackParam ; }
+int be_is_FrameAddr (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameAddr ; }
+int be_is_FrameLoad (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameLoad ; }
+int be_is_FrameStore (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameStore ; }
+int be_is_Barrier (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Barrier ; }
+
+int be_has_frame_entity(const ir_node *irn)
+{
+ switch(be_get_irn_opcode(irn)) {
+ case beo_StackParam:
+ case beo_Spill:
+ case beo_Reload:
+ case beo_FrameStore:
+ case beo_FrameLoad:
+ case beo_FrameAddr:
+ return 1;
+ }
+
+ return 0;
+}
+
+entity *be_get_frame_entity(const ir_node *irn)
+{
+ if(be_has_frame_entity(irn)) {
+ be_frame_attr_t *a = get_irn_attr(irn);
+ return a->ent;
+ }
+ return NULL;
+}
+
+static void be_limited(void *data, bitset_t *bs)
+{
+ be_req_t *req = data;
+
+ switch(req->kind) {
+ case be_req_kind_negate_old_limited:
+ case be_req_kind_old_limited:
+ req->x.old_limited.old_limited(req->x.old_limited.old_limited_env, bs);
+ if(req->kind == be_req_kind_negate_old_limited)
+ bitset_flip_all(bs);
+ break;
+ case be_req_kind_single_reg:
+ bitset_clear_all(bs);
+ bitset_set(bs, req->x.single_reg->index);
+ break;
+ }
+}
+
+static INLINE be_req_t *get_req(ir_node *irn, int pos)
+{
+ int idx = pos < 0 ? -(pos + 1) : pos;
+ be_node_attr_t *a = get_irn_attr(irn);
+ be_reg_data_t *rd = &a->reg_data[idx];
+ be_req_t *r = pos < 0 ? &rd->req : &rd->in_req;
+
+ assert(is_be_node(irn));
+ assert(!(pos >= 0) || pos < get_irn_arity(irn));
+ assert(!(pos < 0) || -(pos + 1) <= a->max_reg_data);
+
+ return r;
+}
+
+void be_set_constr_single_reg(ir_node *irn, int pos, const arch_register_t *reg)
+{
+ be_req_t *r = get_req(irn, pos);
+
+ r->kind = be_req_kind_single_reg;
+ r->x.single_reg = reg;
+ r->req.limited = be_limited;
+ r->req.limited_env = r;
+ r->req.type = arch_register_req_type_limited;
+ r->req.cls = reg->reg_class;
+}
+
+void be_set_constr_limited(ir_node *irn, int pos, const arch_register_req_t *req)
+{
+ be_req_t *r = get_req(irn, pos);
+
+ assert(arch_register_req_is(req, limited));
+
+ r->kind = be_req_kind_old_limited;
+ r->req.limited = be_limited;
+ r->req.limited_env = r;
+ r->req.type = arch_register_req_type_limited;
+ r->req.cls = req->cls;
+
+ r->x.old_limited.old_limited = req->limited;
+ r->x.old_limited.old_limited_env = req->limited_env;
+}
+
+void be_node_set_flags(ir_node *irn, int pos, arch_irn_flags_t flags)
+{
+ be_req_t *r = get_req(irn, pos);
+ r->flags = flags;
+}
+
+void be_node_set_reg_class(ir_node *irn, int pos, const arch_register_class_t *cls)
+{
+ be_req_t *r = get_req(irn, pos);
+ r->req.cls = cls;
+ if(r->req.type == arch_register_req_type_none)
+ r->req.type = arch_register_req_type_normal;
+}
+
+void be_node_set_req_type(ir_node *irn, int pos, arch_register_req_type_t type)
+{
+ be_req_t *r = get_req(irn, pos);
+ r->req.type = type;
+}
+
+void be_set_IncSP_offset(ir_node *irn, unsigned offset)
+{
+ be_stack_attr_t *a = get_irn_attr(irn);
+ assert(be_is_IncSP(irn));
+ a->offset = offset;
+}
+
+unsigned be_get_IncSP_offset(const ir_node *irn)
+{
+ be_stack_attr_t *a = get_irn_attr(irn);
+ assert(be_is_IncSP(irn));
+ return a->offset;
+}
+
+void be_set_IncSP_direction(ir_node *irn, be_stack_dir_t dir)
+{
+ be_stack_attr_t *a = get_irn_attr(irn);
+ assert(be_is_IncSP(irn));
+ a->dir = dir;
+}
+
+be_stack_dir_t be_get_IncSP_direction(const ir_node *irn)
+{
+ be_stack_attr_t *a = get_irn_attr(irn);
+ assert(be_is_IncSP(irn));
+ return a->dir;
+}
+
+void be_set_Spill_entity(ir_node *irn, entity *ent)
+{
+ be_spill_attr_t *a = get_irn_attr(irn);
+ assert(be_is_Spill(irn));
+ a->frame_attr.ent = ent;
+}
+
+static ir_node *find_a_spill_walker(ir_node *irn, unsigned visited_nr)
+{
+ unsigned nr = get_irn_visited(irn);
+
+ set_irn_visited(irn, visited_nr);
+
+ if(is_Phi(irn)) {
+ int i, n;
+ if(nr < visited_nr) {
+ for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
+ ir_node *n = find_a_spill_walker(get_irn_n(irn, i), visited_nr);
+ if(n != NULL)
+ return n;
+ }
+ }
+ }
+
+ else if(be_get_irn_opcode(irn) == beo_Spill)
+ return irn;
+
+ return NULL;
+}
+
+ir_node *be_get_Spill_context(const ir_node *irn) {
+ const be_spill_attr_t *a = get_irn_attr(irn);
+ assert(be_is_Spill(irn));
+ return a->spill_ctx;