set *params;
};
-#define N_FRAME_TYPES 3
-
-/**
- * This type describes the stack layout.
- * The stack is divided into 3 parts:
- * - arg_type: A struct type describing the stack arguments and it's order.
- * - between_type: A struct type describing the stack layout between arguments
- * and frame type
- * - frame_type: A class type descibing the frame layout
- */
-typedef struct _be_stack_layout_t {
- ir_type *arg_type; /**< A type describing the stack argument layout. */
- ir_type *between_type; /**< A type describing the "between" layout. */
- ir_type *frame_type; /**< The frame type. */
-
- ir_type *order[N_FRAME_TYPES]; /**< arg, between and frame types ordered. */
-
- int initial_offset;
- int stack_dir; /**< -1 for decreasing, 1 for increasing. */
-} be_stack_layout_t;
-
struct _be_abi_irg_t {
struct obstack obst;
be_stack_layout_t *frame; /**< The stack frame model. */
* @param between the between layout type
* @param locals the method frame type
* @param stack_dir the stack direction
+ * @param param_map an array mapping method argument positions to the stack argument type
*
* @return the initialized stack layout
*/
static be_stack_layout_t *stack_frame_init(be_stack_layout_t *frame, ir_type *args,
- ir_type *between, ir_type *locals, int stack_dir)
+ ir_type *between, ir_type *locals, int stack_dir,
+ entity *param_map[])
{
frame->arg_type = args;
frame->between_type = between;
frame->initial_offset = 0;
frame->stack_dir = stack_dir;
frame->order[1] = between;
+ frame->param_map = param_map;
if(stack_dir > 0) {
frame->order[0] = args;
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;
+ /* 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.
* @param env the ABI environment
* @param call the current call ABI
* @param method_type the method type
+ * @param param_map an array mapping method arguments to the stack layout type
*
* @return the stack argument layout type
*/
-static ir_type *compute_arg_type(be_abi_irg_t *env, be_abi_call_t *call, ir_type *method_type)
+static ir_type *compute_arg_type(be_abi_irg_t *env, be_abi_call_t *call, ir_type *method_type, entity ***param_map)
{
int dir = env->call->flags.bits.left_to_right ? 1 : -1;
int inc = env->birg->main_env->arch_env->isa->stack_dir * dir;
int i;
ir_type *val_param_tp = get_method_value_param_type(method_type);
ident *id = get_entity_ident(get_irg_entity(env->birg->irg));
+ entity **map;
+ *param_map = map = obstack_alloc(&env->obst, n * sizeof(entity *));
res = new_type_struct(mangle_u(id, new_id_from_chars("arg_type", 8)));
for (i = 0; i < n; ++i, curr += inc) {
ir_type *param_type = get_method_param_type(method_type, curr);
be_abi_call_arg_t *arg = get_call_arg(call, 0, curr);
+ map[i] = NULL;
if (arg->on_stack) {
if (val_param_tp) {
/* the entity was already created, move it to the param type */
set_entity_offset_bytes(arg->stack_ent, ofs);
ofs += arg->space_after;
ofs += get_type_size_bytes(param_type);
+ map[i] = arg->stack_ent;
}
}
set_type_size_bytes(res, ofs);
typedef struct lower_frame_sels_env_t {
be_abi_irg_t *env;
- entity *value_param_list; /**< the list of all value param antities */
+ entity *value_param_list; /**< the list of all value param entities */
} lower_frame_sels_env_t;
/**
const ir_edge_t *edge;
ir_type *arg_type, *bet_type;
lower_frame_sels_env_t ctx;
+ entity **param_map;
bitset_t *used_proj_nr;
DEBUG_ONLY(firm_dbg_module_t *dbg = env->dbg;)
DBG((dbg, LEVEL_2, "\treading arg: %d -> %+F\n", nr, irn));
}
- arg_type = compute_arg_type(env, call, method_type);
+ arg_type = compute_arg_type(env, call, method_type, ¶m_map);
bet_type = call->cb->get_between_type(env->cb);
- stack_frame_init(env->frame, arg_type, bet_type, get_irg_frame_type(irg), isa->stack_dir);
+ stack_frame_init(env->frame, arg_type, bet_type, get_irg_frame_type(irg), isa->stack_dir, param_map);
/* Count the register params and add them to the number of Projs for the RegParams node */
for(i = 0; i < n_params; ++i) {
bitset_set(bs, reg->index);
}
+/* Returns the stack layout from a abi environment. */
+const be_stack_layout_t *be_abi_get_stack_layout(const be_abi_irg_t *abi) {
+ return abi->frame;
+}
/*