+ be_node_get_irn_ops
+};
+
+/*
+ ____ _ _ ___ ____ _ _ _ _ _ _
+ | _ \| |__ (_) |_ _| _ \| \ | | | | | | __ _ _ __ __| | | ___ _ __
+ | |_) | '_ \| | | || |_) | \| | | |_| |/ _` | '_ \ / _` | |/ _ \ '__|
+ | __/| | | | | | || _ <| |\ | | _ | (_| | | | | (_| | | __/ |
+ |_| |_| |_|_| |___|_| \_\_| \_| |_| |_|\__,_|_| |_|\__,_|_|\___|_|
+
+*/
+
+typedef struct {
+ const arch_register_t *reg;
+ arch_register_req_t req;
+ arch_irn_flags_t flags;
+} phi_attr_t;
+
+typedef struct {
+ arch_irn_handler_t irn_handler;
+ arch_irn_ops_t irn_ops;
+ const arch_env_t *arch_env;
+ pmap *phi_attrs;
+} phi_handler_t;
+
+#define get_phi_handler_from_handler(h) container_of(h, phi_handler_t, irn_handler)
+#define get_phi_handler_from_ops(h) container_of(h, phi_handler_t, irn_ops)
+
+static
+const void *phi_get_irn_ops(const arch_irn_handler_t *handler,
+ const ir_node *irn)
+{
+ const phi_handler_t *h;
+ if(!is_Phi(irn) || !mode_is_datab(get_irn_mode(irn)))
+ return NULL;
+
+ h = get_phi_handler_from_handler(handler);
+ return &h->irn_ops;
+}
+
+static INLINE
+phi_attr_t *get_Phi_attr(const phi_handler_t *handler, const ir_node *phi)
+{
+ phi_attr_t *attr = pmap_get(handler->phi_attrs, (void*) phi);
+ if(attr == NULL) {
+ ir_graph *irg = get_irn_irg(phi);
+ struct obstack *obst = get_irg_obstack(irg);
+ attr = obstack_alloc(obst, sizeof(attr[0]));
+ memset(attr, 0, sizeof(attr[0]));
+ pmap_insert(handler->phi_attrs, phi, attr);
+ }
+
+ return attr;
+}
+
+/**
+ * Get register class of a Phi.
+ */
+static
+const arch_register_req_t *get_Phi_reg_req_recursive(const phi_handler_t *h,
+ const ir_node *phi,
+ pset **visited)
+{
+ int n = get_irn_arity(phi);
+ ir_node *op;
+ int i;
+
+ if(*visited && pset_find_ptr(*visited, phi))
+ return NULL;
+
+ for(i = 0; i < n; ++i) {
+ op = get_irn_n(phi, i);
+ /* Matze: don't we unnecessary constraint our phis with this?
+ * we only need to take the regclass IMO*/
+ if(!is_Phi(op))
+ return arch_get_register_req(h->arch_env, op, BE_OUT_POS(0));
+ }
+
+ /*
+ * The operands of that Phi were all Phis themselves.
+ * We have to start a DFS for a non-Phi argument now.
+ */
+ if(!*visited)
+ *visited = pset_new_ptr(16);
+
+ pset_insert_ptr(*visited, phi);
+
+ for(i = 0; i < n; ++i) {
+ const arch_register_req_t *req;
+ op = get_irn_n(phi, i);
+ req = get_Phi_reg_req_recursive(h, op, visited);
+ if(req != NULL)
+ return req;
+ }
+
+ return NULL;
+}
+
+static
+const arch_register_req_t *phi_get_irn_reg_req(const void *self,
+ const ir_node *irn, int pos)
+{
+ phi_handler_t *phi_handler = get_phi_handler_from_ops(self);
+ phi_attr_t *attr;
+ (void) self;
+ (void) pos;
+
+ if(!mode_is_datab(get_irn_mode(irn)))
+ return arch_no_register_req;
+
+ attr = get_Phi_attr(phi_handler, irn);
+
+ if(attr->req.type == arch_register_req_type_none) {
+ pset *visited = NULL;
+ const arch_register_req_t *req;
+ req = get_Phi_reg_req_recursive(phi_handler, irn, &visited);
+
+ memcpy(&attr->req, req, sizeof(req[0]));
+ assert(attr->req.cls != NULL);
+ attr->req.type = arch_register_req_type_normal;
+
+ if(visited != NULL)
+ del_pset(visited);
+ }
+
+ return &attr->req;
+}
+
+void be_set_phi_reg_req(const arch_env_t *arch_env, ir_node *node,
+ const arch_register_req_t *req)
+{
+ const arch_irn_ops_t *ops = arch_get_irn_ops(arch_env, node);
+ const phi_handler_t *handler = get_phi_handler_from_ops(ops);
+ phi_attr_t *attr;
+
+ assert(mode_is_datab(get_irn_mode(node)));
+
+ attr = get_Phi_attr(handler, node);
+ memcpy(&attr->req, req, sizeof(req[0]));
+}
+
+void be_set_phi_flags(const arch_env_t *arch_env, ir_node *node,
+ arch_irn_flags_t flags)
+{
+ const arch_irn_ops_t *ops = arch_get_irn_ops(arch_env, node);
+ const phi_handler_t *handler = get_phi_handler_from_ops(ops);
+ phi_attr_t *attr;
+
+ assert(mode_is_datab(get_irn_mode(node)));
+
+ attr = get_Phi_attr(handler, node);
+ attr->flags = flags;
+}
+
+static
+void phi_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg)
+{
+ phi_handler_t *h = get_phi_handler_from_ops(self);
+ phi_attr_t *attr = get_Phi_attr(h, irn);
+ attr->reg = reg;
+}
+
+static
+const arch_register_t *phi_get_irn_reg(const void *self, const ir_node *irn)
+{
+ phi_handler_t *h = get_phi_handler_from_ops(self);
+ phi_attr_t *attr = get_Phi_attr(h, irn);
+ return attr->reg;
+}
+
+static
+arch_irn_class_t phi_classify(const void *self, const ir_node *irn)
+{
+ (void) self;
+ (void) irn;
+ return arch_irn_class_normal;
+}
+
+static
+arch_irn_flags_t phi_get_flags(const void *self, const ir_node *irn)
+{
+ phi_handler_t *h = get_phi_handler_from_ops(self);
+ phi_attr_t *attr = get_Phi_attr(h, irn);
+ (void) self;
+ return attr->flags;
+}
+
+static
+ir_entity *phi_get_frame_entity(const void *self, const ir_node *irn)
+{
+ (void) self;
+ (void) irn;
+ return NULL;
+}
+
+static
+void phi_set_frame_entity(const void *self, ir_node *irn, ir_entity *ent)
+{
+ (void) self;
+ (void) irn;
+ (void) ent;
+ assert(0);
+}
+
+static
+void phi_set_frame_offset(const void *self, ir_node *irn, int bias)
+{
+ (void) self;
+ (void) irn;
+ (void) bias;
+ assert(0);
+}
+
+static
+int phi_get_sp_bias(const void* self, const ir_node *irn)
+{
+ (void) self;
+ (void) irn;
+ return 0;
+}
+
+static
+const arch_irn_ops_if_t phi_irn_ops = {
+ phi_get_irn_reg_req,
+ phi_set_irn_reg,
+ phi_get_irn_reg,
+ phi_classify,
+ phi_get_flags,
+ phi_get_frame_entity,
+ phi_set_frame_entity,
+ phi_set_frame_offset,
+ phi_get_sp_bias,
+ NULL, /* get_inverse */
+ NULL, /* get_op_estimated_cost */
+ NULL, /* possible_memory_operand */
+ NULL, /* perform_memory_operand */