From 7167b92e568990ab347dc0b0a560c3bfd3040585 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Mon, 1 Oct 2007 11:11:30 +0000 Subject: [PATCH] mark methods with lowered struct params, correctly handle x86 abi for this case [r16018] --- include/libfirm/typerep.h | 2 ++ ir/be/beabi.c | 29 +++++++++++++++++++++++++---- ir/be/benode.c | 16 +++++++++++++--- ir/be/benode_t.h | 7 +++++-- ir/be/ia32/ia32_emitter.c | 6 ++++++ ir/lower/lower_calls.c | 2 ++ 6 files changed, 53 insertions(+), 9 deletions(-) diff --git a/include/libfirm/typerep.h b/include/libfirm/typerep.h index f4b66a854..3513cc556 100644 --- a/include/libfirm/typerep.h +++ b/include/libfirm/typerep.h @@ -1946,6 +1946,8 @@ typedef enum { function calls (stdcall). */ cc_this_call = 0x08000000, /**< The first parameter is a this pointer and is transmitted in a special way. */ + cc_compound_ret = 0x10000000, /**< the method returns a compound + type */ cc_bits = (0xFF << 24) /**< the calling convention bits */ } calling_convention; diff --git a/ir/be/beabi.c b/ir/be/beabi.c index dfd2305b0..83c6a3879 100644 --- a/ir/be/beabi.c +++ b/ir/be/beabi.c @@ -780,6 +780,11 @@ 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) { + stack_size -= get_mode_size_bytes(mode_P_data); + } + curr_sp = be_new_IncSP(sp, irg, bl, curr_sp, -stack_size); add_irn_dep(curr_sp, mem_proj); } @@ -1361,15 +1366,21 @@ static ir_node *create_barrier(be_abi_irg_t *env, ir_node *bl, ir_node **mem, pm * @param mem the current memory * @param n_res number of return results */ -static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl, ir_node *mem, int n_res) { - be_abi_call_t *call = env->call; +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; pmap *reg_map = pmap_create(); ir_node *keep = pmap_get(env->keep_map, bl); int in_max; ir_node *ret; int i, n; + unsigned pop; ir_node **in; ir_node *stack; const arch_register_t **regs; @@ -1446,7 +1457,17 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl, i } /* The in array for the new back end return is now ready. */ - ret = be_new_Return(irn ? get_irn_dbg_info(irn) : NULL, env->birg->irg, bl, n_res, n, in); + if(irn != NULL) { + dbgi = get_irn_dbg_info(irn); + } else { + 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); + } + ret = be_new_Return(dbgi, env->birg->irg, bl, n_res, pop, n, in); /* Set the register classes of the return's parameter accordingly. */ for(i = 0; i < n; ++i) diff --git a/ir/be/benode.c b/ir/be/benode.c index 7fc22c543..ecdfeb2eb 100644 --- a/ir/be/benode.c +++ b/ir/be/benode.c @@ -85,6 +85,7 @@ typedef struct { typedef struct { be_node_attr_t node_attr; int num_ret_vals; /**< number of return values */ + unsigned pop; /**< number of bytes that should be popped */ } be_return_attr_t; /** The be_Stack attribute type. */ @@ -196,6 +197,8 @@ static int Return_cmp_attr(ir_node *a, ir_node *b) { if (a_attr->num_ret_vals != b_attr->num_ret_vals) return 1; + if (a_attr->pop != b_attr->pop) + return 1; return _node_cmp_attr((be_node_attr_t*) a_attr, (be_node_attr_t*) b_attr); } @@ -640,7 +643,7 @@ void be_Call_set_type(ir_node *call, ir_type *call_tp) { /* Construct a new be_Return. */ ir_node *be_new_Return(dbg_info *dbg, ir_graph *irg, ir_node *block, int n_res, - int n, ir_node *in[]) + unsigned pop, int n, ir_node *in[]) { be_return_attr_t *a; ir_node *res; @@ -655,17 +658,24 @@ ir_node *be_new_Return(dbg_info *dbg, ir_graph *irg, ir_node *block, int n_res, a = get_irn_attr(res); a->num_ret_vals = n_res; + a->pop = pop; return res; } /* Returns the number of real returns values */ -int be_Return_get_n_rets(ir_node *ret) +int be_Return_get_n_rets(const ir_node *ret) { - be_return_attr_t *a = get_irn_attr(ret); + const be_return_attr_t *a = get_irn_generic_attr_const(ret); return a->num_ret_vals; } +unsigned be_Return_get_pop(const ir_node *ret) +{ + const be_return_attr_t *a = get_irn_generic_attr_const(ret); + return a->pop; +} + int be_Return_append_node(ir_node *ret, ir_node *node) { int pos; diff --git a/ir/be/benode_t.h b/ir/be/benode_t.h index a8b5a73ff..ddd3c059a 100644 --- a/ir/be/benode_t.h +++ b/ir/be/benode_t.h @@ -335,12 +335,15 @@ enum { * @param bl the block where the new node will be placed * @param n_res number of "real" results * @param n number of inputs + * @param pop pop number of bytes on return * @param in input array */ -ir_node *be_new_Return(dbg_info *dbg, ir_graph *irg, ir_node *bl, int n_res, int n, ir_node *in[]); +ir_node *be_new_Return(dbg_info *dbg, ir_graph *irg, ir_node *bl, int n_res, unsigned pop, int n, ir_node *in[]); /** Returns the number of real returns values */ -int be_Return_get_n_rets(ir_node *ret); +int be_Return_get_n_rets(const ir_node *ret); + +unsigned be_Return_get_pop(const ir_node *ret); /** appends a node to the return node, returns the position of the node */ int be_Return_append_node(ir_node *ret, ir_node *node); diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 1f3496969..2881ee772 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -1752,7 +1752,13 @@ zero_neg: static void emit_be_Return(const ir_node *node) { + unsigned pop; be_emit_cstring("\tret"); + + pop = be_Return_get_pop(node); + if(pop > 0) { + be_emit_irprintf(" $%d", pop); + } be_emit_finish_line_gas(node); } diff --git a/ir/lower/lower_calls.c b/ir/lower/lower_calls.c index 606d9f77b..97fd3e235 100644 --- a/ir/lower/lower_calls.c +++ b/ir/lower/lower_calls.c @@ -177,6 +177,8 @@ static ir_type *create_modified_mtd_type(const lower_params_t *lp, ir_type *mtp) set_method_first_variadic_param_index(lowered, first_variadic); /* associate the lowered type with the original one for easier access */ + set_method_calling_convention(lowered, + get_method_calling_convention(mtp) | cc_compound_ret); set_lowered_type(mtp, lowered); return lowered; -- 2.20.1