From 998c6fe45b321549321e8bda048dc2d4ed6a33b2 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Fri, 12 Oct 2007 23:20:10 +0000 Subject: [PATCH] improve and generalize handling of calls shrinking the stack on return [r16186] --- ir/be/beabi.c | 28 ++++++++++++---------------- ir/be/beabi.h | 5 +++++ ir/be/ia32/bearch_ia32.c | 7 +++++++ ir/be/mips/bearch_mips.c | 1 + 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/ir/be/beabi.c b/ir/be/beabi.c index c1318e876..43b07cf8c 100644 --- a/ir/be/beabi.c +++ b/ir/be/beabi.c @@ -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. */ diff --git a/ir/be/beabi.h b/ir/be/beabi.h index 505b3df74..b72005904 100644 --- a/ir/be/beabi.h +++ b/ir/be/beabi.h @@ -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. diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index 99319ec41..9d0ccda1d 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -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; diff --git a/ir/be/mips/bearch_mips.c b/ir/be/mips/bearch_mips.c index 92fc947ed..19e529ba9 100644 --- a/ir/be/mips/bearch_mips.c +++ b/ir/be/mips/bearch_mips.c @@ -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]; } -- 2.20.1