curr_sp = alloc_res;
}
+ return curr_sp;
+} /* adjust_alloc */
+
+/**
+ * Adjust a Free.
+ * The Free is transformed into a back end free node and connected to the stack nodes.
+ */
+static ir_node *adjust_free(be_abi_irg_t *env, ir_node *free, ir_node *curr_sp)
+{
+ if (get_Free_where(free) == stack_alloc) {
+ ir_node *bl = get_nodes_block(free);
+ ir_graph *irg = get_irn_irg(bl);
+ ir_node *addsp, *mem, *res;
+ dbg_info *db = get_irn_dbg_info(free);
+
+ /* The stack pointer will be modified in an unknown manner.
+ We cannot omit it. */
+ env->call->flags.bits.try_omit_fp = 0;
+ addsp = be_new_SubSP(env->isa->sp, irg, bl, curr_sp, get_Free_size(free));
+ mem = new_r_Proj(irg, bl, addsp, mode_M, pn_be_SubSP_M);
+ res = new_r_Proj(irg, bl, addsp, mode_P_data, pn_be_SubSP_res);
+
+ exchange(free, mem);
+ curr_sp = res;
+ }
return curr_sp;
-}
+} /* adjust_free */
/* the following function is replaced by the usage of the heights module */
#if 0
}
/**
- * Walker: links all Call nodes to the Block they are contained.
+ * Walker: links all Call/alloc/Free nodes to the Block they are contained.
*/
static void link_calls_in_block_walker(ir_node *irn, void *data)
{
- if(is_Call(irn) || (get_irn_opcode(irn) == iro_Alloc && get_Alloc_where(irn) == stack_alloc)) {
+ opcode code = get_irn_opcode(irn);
+
+ if (code == iro_Call ||
+ (code == iro_Alloc && get_Alloc_where(irn) == stack_alloc) ||
+ (code == iro_Free && get_Free_where(irn) == stack_alloc)) {
be_abi_irg_t *env = data;
ir_node *bl = get_nodes_block(irn);
void *save = get_irn_link(bl);
- if (is_Call(irn))
+ if (code == iro_Call)
env->call->flags.bits.irg_is_leaf = 0;
set_irn_link(irn, save);
case iro_Alloc:
curr_sp = adjust_alloc(env, irn, curr_sp, ©);
break;
+ case iro_Free:
+ curr_sp = adjust_free(env, irn, curr_sp);
+ break;
default:
break;
}
}
set_irn_link(bl, curr_sp);
-}
+} /* process_calls_in_block */
/**
* Adjust all call nodes in the graph to the ABI conventions.