Commit 998c6fe4 authored by Matthias Braun's avatar Matthias Braun
Browse files

improve and generalize handling of calls shrinking the stack on return

[r16186]
parent 5ffc7772
......@@ -70,7 +70,8 @@ typedef struct _be_abi_call_arg_t {
} be_abi_call_arg_t;
struct _be_abi_call_t {
be_abi_call_flags_t flags;
be_abi_call_flags_t flags;
int pop;
const be_abi_callbacks_t *cb;
ir_type *between_type;
set *params;
......@@ -178,6 +179,11 @@ void be_abi_call_set_flags(be_abi_call_t *call, be_abi_call_flags_t flags, const
call->cb = cb;
}
void be_abi_call_set_pop(be_abi_call_t *call, int pop)
{
assert(pop >= 0);
call->pop = pop;
}
/* Set register class for call address */
void be_abi_call_set_call_address_reg_class(be_abi_call_t *call, const arch_register_class_t *cls)
......@@ -224,6 +230,7 @@ be_abi_call_flags_t be_abi_call_get_flags(const be_abi_call_t *call)
static be_abi_call_t *be_abi_call_new(const arch_register_class_t *cls_addr)
{
be_abi_call_t *call = xmalloc(sizeof(call[0]));
memset(call, 0, sizeof(call[0]));
call->flags.val = 0;
call->params = new_set(cmp_call_arg, 16);
......@@ -776,6 +783,9 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
}
/* Clean up the stack. */
assert(stack_size >= call->pop);
stack_size -= call->pop;
if (stack_size > 0) {
ir_node *mem_proj = NULL;
......@@ -794,15 +804,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
/* Clean up the stack frame if we allocated it */
if (! no_alloc) {
/* the callee pops the shadow parameter */
if(get_method_calling_convention(mt) & cc_compound_ret) {
unsigned size = get_mode_size_bytes(mode_P_data);
stack_size -= size;
be_Call_set_pop(low_call, size);
}
curr_sp = be_new_IncSP(sp, irg, bl, curr_sp, -stack_size);
//add_irn_dep(curr_sp, mem_proj);
}
}
......@@ -1387,9 +1389,6 @@ static ir_node *create_barrier(be_abi_irg_t *env, ir_node *bl, ir_node **mem, pm
static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl,
ir_node *mem, int n_res)
{
ir_graph *irg = env->birg->irg;
ir_entity *entity = get_irg_entity(irg);
ir_type *method_type = get_entity_type(entity);
be_abi_call_t *call = env->call;
const arch_isa_t *isa = env->birg->main_env->arch_env->isa;
dbg_info *dbgi;
......@@ -1481,10 +1480,7 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl,
dbgi = NULL;
}
/* we have to pop the shadow parameter in in case of struct returns */
pop = 0;
if(get_method_calling_convention(method_type) & cc_compound_ret) {
pop = get_mode_size_bytes(mode_P_data);
}
pop = call->pop;
ret = be_new_Return(dbgi, env->birg->irg, bl, n_res, pop, n, in);
/* Set the register classes of the return's parameter accordingly. */
......
......@@ -114,6 +114,11 @@ struct _be_abi_callbacks_t {
*/
void be_abi_call_set_flags(be_abi_call_t *call, be_abi_call_flags_t flags, const be_abi_callbacks_t *cb);
/**
* Sets the number of bytes the stackframe is shrinked by the callee on return
*/
void be_abi_call_set_pop(be_abi_call_t *call, int pop);
/**
* Set register class for call address.
* @param call The call.
......
......@@ -1799,6 +1799,13 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type, be_abi_cal
cc = (cc & ~cc_bits) | cc_reg_param;
}
}
/* we have to pop the shadow parameter ourself for compound calls */
if( (get_method_calling_convention(method_type) & cc_compound_ret)
&& !(cc & cc_reg_param)) {
be_abi_call_set_pop(abi, get_mode_size_bytes(mode_P_data));
}
n = get_method_n_params(method_type);
for (i = regnum = 0; i < n; i++) {
const ir_mode *mode;
......
......@@ -680,6 +680,7 @@ const arch_register_class_t *mips_get_reg_class_for_mode(const void *self,
const ir_mode *mode)
{
(void) self;
(void) mode;
ASSERT_NO_FLOAT(mode);
return &mips_reg_classes[CLASS_mips_gp];
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment