+ /*
+ Classical qsort() comparison function behavior:
+ 0 if both elements are equal
+ 1 if second is "smaller" that first
+ -1 if first is "smaller" that second
+ */
+ return n1 == n2 ? 0 : (dependent_on(n1, n2) ? -1 : 1);
+}
+
+static void link_calls_in_block_walker(ir_node *irn, void *data)
+{
+ if(is_Call(irn)) {
+ be_abi_irg_t *env = data;
+ ir_node *bl = get_nodes_block(irn);
+ void *save = get_irn_link(bl);
+
+ env->call->flags.bits.irg_is_leaf = 0;
+
+ set_irn_link(irn, save);
+ set_irn_link(bl, irn);
+ }
+}
+
+/**
+ * Process all call nodes inside a basic block.
+ * Note that the link field of the block must contain a linked list of all
+ * Call nodes inside the block. We first order this list according to data dependency
+ * and that connect the calls together.
+ */
+static void process_calls_in_block(ir_node *bl, void *data)
+{
+ be_abi_irg_t *env = data;
+ ir_node *curr_sp = env->init_sp;
+ ir_node *irn;
+ int n;
+
+ for(irn = get_irn_link(bl), n = 0; irn; irn = get_irn_link(irn), ++n)
+ obstack_ptr_grow(&env->obst, irn);
+
+ /* If there were call nodes in the block. */
+ if(n > 0) {
+ ir_node **nodes;
+ int i;
+
+ nodes = obstack_finish(&env->obst);
+
+ /* order the call nodes according to data dependency */
+ qsort(nodes, n, sizeof(nodes[0]), cmp_call_dependecy);
+
+ for(i = n - 1; i >= 0; --i) {
+ ir_node *irn = nodes[i];
+
+ switch(get_irn_opcode(irn)) {
+ case iro_Call:
+ curr_sp = adjust_call(env, irn, curr_sp);
+ break;
+ case iro_Alloc:
+ curr_sp = adjust_alloc(env, irn, curr_sp);
+ break;
+ default:
+ break;
+ }
+ }
+
+ obstack_free(&env->obst, nodes);
+
+ /* Keep the last stack state in the block by tying it to Keep node */
+ nodes[0] = curr_sp;
+ be_new_Keep(env->isa->sp->reg_class, get_irn_irg(bl), bl, 1, nodes);
+ }
+
+ set_irn_link(bl, curr_sp);
+}
+
+/**
+ * Adjust all call nodes in the graph to the ABI conventions.
+ */
+static void process_calls(be_abi_irg_t *env)
+{
+ ir_graph *irg = env->birg->irg;
+
+ env->call->flags.bits.irg_is_leaf = 1;
+ irg_walk_graph(irg, firm_clear_link, link_calls_in_block_walker, env);
+ irg_block_walk_graph(irg, NULL, process_calls_in_block, env);