+/**
+* A function that allows for setting an edge.
+* This abstraction is necessary since different edge kind have
+* different methods of setting edges.
+*/
+typedef void (set_edge_func_t)(ir_node *src, int pos, ir_node *tgt);
+
+typedef int (get_edge_src_arity_func_t)(const ir_node *src);
+
+typedef int (get_edge_src_first_func_t)(const ir_node *src);
+
+typedef ir_node *(get_edge_src_n_func_t)(const ir_node *src, int pos);
+
+/**
+* Additional data for an edge kind.
+*/
+typedef struct {
+ const char *name;
+ set_edge_func_t *set_edge;
+ get_edge_src_first_func_t *get_first;
+ get_edge_src_arity_func_t *get_arity;
+ get_edge_src_n_func_t *get_n;
+} ir_edge_kind_info_t;
+
+static int get_zero(const ir_node *irn)
+{
+ return 0;
+}
+
+static int get_irn_first(const ir_node *irn)
+{
+ return 0 - !is_Block(irn);
+}
+
+static ir_node *get_block_n(const ir_node *irn, int pos)
+{
+ return is_Block(irn) ? get_Block_cfgpred_block((ir_node *) irn, pos) : 0;
+}
+
+static const ir_edge_kind_info_t edge_kind_info[EDGE_KIND_LAST] = {
+ { "normal" , set_irn_n, get_irn_first, get_irn_arity, get_irn_n },
+ { "block succs", NULL, get_zero, get_irn_arity, get_block_n },
+ { "dependency", set_irn_dep, get_zero, get_irn_deps, get_irn_dep }
+};
+
+#define foreach_tgt(irn, i, n, kind) for(i = edge_kind_info[kind].get_first(irn), n = edge_kind_info[kind].get_arity(irn); i < n; ++i)
+#define get_n(irn, pos, kind) (edge_kind_info[kind].get_n(irn, pos))
+#define get_kind_str(kind) (edge_kind_info[kind].name)