+ return 1;
+}
+
+/**
+ * Compare two be node attributes.
+ *
+ * @return zero if both attributes are identically
+ */
+static int _node_cmp_attr(const be_node_attr_t *a, const be_node_attr_t *b) {
+ int i, len;
+
+ if (ARR_LEN(a->reg_data) != ARR_LEN(b->reg_data))
+ return 1;
+
+ len = ARR_LEN(a->reg_data);
+ for (i = 0; i < len; ++i) {
+ if (a->reg_data[i].reg != b->reg_data[i].reg ||
+ !be_reqs_equal(&a->reg_data[i].in_req, &b->reg_data[i].in_req) ||
+ !be_reqs_equal(&a->reg_data[i].req, &b->reg_data[i].req))
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Compare the node attributes of two be_node's.
+ *
+ * @return zero if both nodes have identically attributes
+ */
+static int node_cmp_attr(ir_node *a, ir_node *b) {
+ const be_node_attr_t *a_attr = get_irn_attr_const(a);
+ const be_node_attr_t *b_attr = get_irn_attr_const(b);
+
+ return _node_cmp_attr(a_attr, b_attr);
+}
+
+/**
+ * Compare the attributes of two be_FrameAddr nodes.
+ *
+ * @return zero if both nodes have identically attributes
+ */
+static int FrameAddr_cmp_attr(ir_node *a, ir_node *b) {
+ const be_frame_attr_t *a_attr = get_irn_attr_const(a);
+ const be_frame_attr_t *b_attr = get_irn_attr_const(b);
+
+ if (a_attr->ent != b_attr->ent || a_attr->offset != b_attr->offset)
+ return 1;
+
+ return _node_cmp_attr(&a_attr->node_attr, &b_attr->node_attr);
+}
+
+/**
+ * Compare the attributes of two be_Return nodes.
+ *
+ * @return zero if both nodes have identically attributes
+ */
+static int Return_cmp_attr(ir_node *a, ir_node *b) {
+ const be_return_attr_t *a_attr = get_irn_attr_const(a);
+ const be_return_attr_t *b_attr = get_irn_attr_const(b);
+
+ if (a_attr->num_ret_vals != b_attr->num_ret_vals)
+ return 1;
+ if (a_attr->pop != b_attr->pop)
+ return 1;
+ if (a_attr->emit_pop != b_attr->emit_pop)
+ return 1;
+
+ return _node_cmp_attr(&a_attr->node_attr, &b_attr->node_attr);
+}
+
+/**
+ * Compare the attributes of two be_IncSP nodes.
+ *
+ * @return zero if both nodes have identically attributes
+ */
+static int IncSP_cmp_attr(ir_node *a, ir_node *b) {
+ const be_incsp_attr_t *a_attr = get_irn_attr_const(a);
+ const be_incsp_attr_t *b_attr = get_irn_attr_const(b);
+
+ if (a_attr->offset != b_attr->offset)
+ return 1;
+
+ return _node_cmp_attr(&a_attr->node_attr, &b_attr->node_attr);
+}
+
+/**
+ * Compare the attributes of two be_Call nodes.
+ *
+ * @return zero if both nodes have identically attributes
+ */
+static int Call_cmp_attr(ir_node *a, ir_node *b) {
+ const be_call_attr_t *a_attr = get_irn_attr_const(a);
+ const be_call_attr_t *b_attr = get_irn_attr_const(b);
+
+ if (a_attr->ent != b_attr->ent ||
+ a_attr->call_tp != b_attr->call_tp)
+ return 1;
+
+ return _node_cmp_attr(&a_attr->node_attr, &b_attr->node_attr);
+}
+
+static INLINE be_req_t *get_be_req(const ir_node *node, int pos)
+{
+ int idx;
+ const be_node_attr_t *attr;
+ be_reg_data_t *rd;
+
+ assert(is_be_node(node));
+ attr = get_irn_attr_const(node);
+
+ if(pos < 0) {
+ idx = -(pos + 1);
+ } else {
+ idx = pos;
+ assert(idx < get_irn_arity(node));
+ }
+ assert(idx < ARR_LEN(attr->reg_data));
+ rd = &attr->reg_data[idx];
+
+ return pos < 0 ? &rd->req : &rd->in_req;
+}
+
+static INLINE arch_register_req_t *get_req(const ir_node *node, int pos)
+{
+ be_req_t *bereq = get_be_req(node, pos);
+ return &bereq->req;
+}
+
+void be_node_init(void) {
+ static int inited = 0;
+
+ if(inited)
+ return;
+
+ inited = 1;
+
+ /* Acquire all needed opcodes. */
+ beo_base = get_next_ir_opcodes(beo_Last);
+
+ op_be_Spill = new_ir_op(beo_base + beo_Spill, "be_Spill", op_pin_state_pinned, N, oparity_unary, 0, sizeof(be_frame_attr_t), &be_node_op_ops);
+ op_be_Reload = new_ir_op(beo_base + beo_Reload, "be_Reload", op_pin_state_pinned, N, oparity_zero, 0, sizeof(be_frame_attr_t), &be_node_op_ops);
+ op_be_Perm = new_ir_op(beo_base + beo_Perm, "be_Perm", op_pin_state_pinned, N, oparity_variable, 0, sizeof(be_node_attr_t), &be_node_op_ops);
+ op_be_MemPerm = new_ir_op(beo_base + beo_MemPerm, "be_MemPerm", op_pin_state_pinned, N, oparity_variable, 0, sizeof(be_memperm_attr_t), &be_node_op_ops);
+ op_be_Copy = new_ir_op(beo_base + beo_Copy, "be_Copy", op_pin_state_floats, N, oparity_unary, 0, sizeof(be_node_attr_t), &be_node_op_ops);
+ op_be_Keep = new_ir_op(beo_base + beo_Keep, "be_Keep", op_pin_state_pinned, K, oparity_dynamic, 0, sizeof(be_node_attr_t), &be_node_op_ops);
+ op_be_CopyKeep = new_ir_op(beo_base + beo_CopyKeep, "be_CopyKeep", op_pin_state_pinned, K, oparity_variable, 0, sizeof(be_node_attr_t), &be_node_op_ops);
+ op_be_Call = new_ir_op(beo_base + beo_Call, "be_Call", op_pin_state_pinned, F|M, oparity_variable, 0, sizeof(be_call_attr_t), &be_node_op_ops);
+ op_be_Return = new_ir_op(beo_base + beo_Return, "be_Return", op_pin_state_pinned, X, oparity_dynamic, 0, sizeof(be_return_attr_t), &be_node_op_ops);
+ op_be_AddSP = new_ir_op(beo_base + beo_AddSP, "be_AddSP", op_pin_state_pinned, N, oparity_unary, 0, sizeof(be_node_attr_t), &be_node_op_ops);
+ op_be_SubSP = new_ir_op(beo_base + beo_SubSP, "be_SubSP", op_pin_state_pinned, N, oparity_unary, 0, sizeof(be_node_attr_t), &be_node_op_ops);
+ op_be_IncSP = new_ir_op(beo_base + beo_IncSP, "be_IncSP", op_pin_state_pinned, N, oparity_unary, 0, sizeof(be_incsp_attr_t), &be_node_op_ops);
+ op_be_RegParams = new_ir_op(beo_base + beo_RegParams, "be_RegParams", op_pin_state_pinned, N, oparity_zero, 0, sizeof(be_node_attr_t), &be_node_op_ops);
+ op_be_FrameAddr = new_ir_op(beo_base + beo_FrameAddr, "be_FrameAddr", op_pin_state_floats, N, oparity_unary, 0, sizeof(be_frame_attr_t), &be_node_op_ops);
+ op_be_Barrier = new_ir_op(beo_base + beo_Barrier, "be_Barrier", op_pin_state_pinned, N, oparity_dynamic, 0, sizeof(be_node_attr_t), &be_node_op_ops);
+ op_be_Unwind = new_ir_op(beo_base + beo_Unwind, "be_Unwind", op_pin_state_pinned, X, oparity_zero, 0, sizeof(be_node_attr_t), &be_node_op_ops);
+
+ set_op_tag(op_be_Spill, &be_node_tag);
+ op_be_Spill->ops.node_cmp_attr = FrameAddr_cmp_attr;
+ set_op_tag(op_be_Reload, &be_node_tag);
+ op_be_Reload->ops.node_cmp_attr = FrameAddr_cmp_attr;
+ set_op_tag(op_be_Perm, &be_node_tag);
+ op_be_Perm->ops.node_cmp_attr = node_cmp_attr;
+ set_op_tag(op_be_MemPerm, &be_node_tag);
+ op_be_MemPerm->ops.node_cmp_attr = node_cmp_attr;
+ set_op_tag(op_be_Copy, &be_node_tag);
+ op_be_Copy->ops.node_cmp_attr = node_cmp_attr;
+ set_op_tag(op_be_Keep, &be_node_tag);
+ op_be_Keep->ops.node_cmp_attr = node_cmp_attr;
+ set_op_tag(op_be_CopyKeep, &be_node_tag);
+ op_be_CopyKeep->ops.node_cmp_attr = node_cmp_attr;
+ set_op_tag(op_be_Call, &be_node_tag);
+ op_be_Call->ops.node_cmp_attr = Call_cmp_attr;
+ set_op_tag(op_be_Return, &be_node_tag);
+ op_be_Return->ops.node_cmp_attr = Return_cmp_attr;
+ set_op_tag(op_be_AddSP, &be_node_tag);
+ op_be_AddSP->ops.node_cmp_attr = node_cmp_attr;
+ set_op_tag(op_be_SubSP, &be_node_tag);
+ op_be_SubSP->ops.node_cmp_attr = node_cmp_attr;
+ set_op_tag(op_be_IncSP, &be_node_tag);
+ op_be_IncSP->ops.node_cmp_attr = IncSP_cmp_attr;
+ set_op_tag(op_be_RegParams, &be_node_tag);
+ op_be_RegParams->ops.node_cmp_attr = node_cmp_attr;
+ set_op_tag(op_be_FrameAddr, &be_node_tag);
+ op_be_FrameAddr->ops.node_cmp_attr = FrameAddr_cmp_attr;
+ set_op_tag(op_be_Barrier, &be_node_tag);
+ op_be_Barrier->ops.node_cmp_attr = node_cmp_attr;
+ set_op_tag(op_be_Unwind, &be_node_tag);
+ op_be_Unwind->ops.node_cmp_attr = node_cmp_attr;
+}
+
+/**
+ * Initializes the generic attribute of all be nodes and return ir.
+ */
+static void *init_node_attr(ir_node *node, int max_reg_data)
+{
+ ir_graph *irg = get_irn_irg(node);
+ struct obstack *obst = get_irg_obstack(irg);
+ be_node_attr_t *a = get_irn_attr(node);
+
+ memset(a, 0, sizeof(get_op_attr_size(get_irn_op(node))));
+
+ if(max_reg_data >= 0) {
+ a->reg_data = NEW_ARR_D(be_reg_data_t, obst, max_reg_data);
+ memset(a->reg_data, 0, max_reg_data * sizeof(a->reg_data[0]));
+ } else {
+ a->reg_data = NEW_ARR_F(be_reg_data_t, 0);
+ }
+
+ return a;
+}
+
+static void add_register_req(ir_node *node)
+{
+ be_node_attr_t *a = get_irn_attr(node);
+ be_reg_data_t regreq;
+ memset(®req, 0, sizeof(regreq));
+ ARR_APP1(be_reg_data_t, a->reg_data, regreq);
+}
+
+int is_be_node(const ir_node *irn)
+{
+ return get_op_tag(get_irn_op(irn)) == &be_node_tag;
+}
+
+be_opcode_t be_get_irn_opcode(const ir_node *irn)
+{
+ return is_be_node(irn) ? (be_opcode_t) get_irn_opcode(irn) - beo_base : beo_NoBeOp;
+}
+
+/**
+ * Skip Proj nodes and return their Proj numbers.
+ *
+ * If *node is a Proj or Proj(Proj) node, skip it.
+ *
+ * @param node points to the node to be skipped
+ *
+ * @return 0 if *node was no Proj node, its Proj number else.
+ */
+static int redir_proj(const ir_node **node)
+{
+ const ir_node *n = *node;
+
+ if(is_Proj(n)) {
+ ir_node *irn;
+
+ *node = irn = get_Proj_pred(n);
+ if(is_Proj(irn)) {
+ assert(get_irn_mode(irn) == mode_T);
+ *node = get_Proj_pred(irn);
+ }
+ return get_Proj_proj(n);
+ }
+
+ return 0;
+}
+
+static be_reg_data_t *retrieve_reg_data(const ir_node *node)
+{
+ const be_node_attr_t *attr;
+ int pos = 0;
+
+ if(is_Proj(node)) {
+ pos = get_Proj_proj(node);
+ node = get_Proj_pred(node);
+ }
+
+ assert(is_be_node(node));
+ attr = get_irn_attr_const(node);
+ assert(pos >= 0 && pos < ARR_LEN(attr->reg_data) && "illegal proj number");
+
+ return &attr->reg_data[pos];
+}
+
+static void
+be_node_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg)
+{
+ be_reg_data_t *r = retrieve_reg_data(irn);
+ (void) self;
+ r->reg = reg;
+}