From 22eb6c0a72ad11e96469143d4764375f6d2c3ef9 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Fri, 12 Aug 2011 13:30:22 +0200 Subject: [PATCH] implement aggregate returns according to sparc ABI --- ir/be/sparc/bearch_sparc_t.h | 3 ++- ir/be/sparc/sparc_cconv.c | 9 +++++++++ ir/be/sparc/sparc_emitter.c | 19 ++++++++++++++++++- ir/be/sparc/sparc_nodes_attr.h | 1 + ir/be/sparc/sparc_spec.pl | 11 +++++++---- ir/be/sparc/sparc_stackframe.c | 24 +++++++++++++----------- ir/be/sparc/sparc_transform.c | 7 +++++-- ir/lower/lower_calls.c | 1 + ir/tr/type_t.h | 4 +++- 9 files changed, 59 insertions(+), 20 deletions(-) diff --git a/ir/be/sparc/bearch_sparc_t.h b/ir/be/sparc/bearch_sparc_t.h index 8c4ca2f62..da5e07e0b 100644 --- a/ir/be/sparc/bearch_sparc_t.h +++ b/ir/be/sparc/bearch_sparc_t.h @@ -66,9 +66,10 @@ extern const arch_irn_ops_t sparc_irn_ops; * param 0-5 in this spaces and then handle va_next by simply * incrementing the stack pointer */ -#define SPARC_MIN_STACKSIZE 92 #define SPARC_IMMEDIATE_MIN -4096 #define SPARC_IMMEDIATE_MAX 4095 +#define SPARC_MIN_STACKSIZE 92 +#define SPARC_AGGREGATE_RETURN_OFFSET 64 static inline bool sparc_is_value_imm_encodeable(int32_t value) { diff --git a/ir/be/sparc/sparc_cconv.c b/ir/be/sparc/sparc_cconv.c index af2c09c0d..211699e8e 100644 --- a/ir/be/sparc/sparc_cconv.c +++ b/ir/be/sparc/sparc_cconv.c @@ -202,6 +202,15 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type, int bits = get_mode_size_bits(mode); reg_or_stackslot_t *param = ¶ms[i]; + if (i == 0 && function_type->attr.ma.has_compound_ret_parameter) { + assert(mode_is_reference(mode) && bits == 32); + /* special case, we have reserved space for this on the between + * type */ + param->type = param_type; + param->offset = -SPARC_MIN_STACKSIZE+SPARC_AGGREGATE_RETURN_OFFSET; + continue; + } + if (regnum < n_param_regs) { const arch_register_t *reg = param_regs[regnum]; if (irg == NULL || omit_fp) diff --git a/ir/be/sparc/sparc_emitter.c b/ir/be/sparc/sparc_emitter.c index d0a850701..045a385b8 100644 --- a/ir/be/sparc/sparc_emitter.c +++ b/ir/be/sparc/sparc_emitter.c @@ -337,6 +337,10 @@ static bool emits_multiple_instructions(const ir_node *node) if (has_delay_slot(node)) return true; + if (is_sparc_Call(node)) { + return arch_irn_get_flags(node) & sparc_arch_irn_flag_aggregate_return; + } + return is_sparc_Mulh(node) || is_sparc_SDiv(node) || is_sparc_UDiv(node) || be_is_MemPerm(node) || be_is_Perm(node); } @@ -531,6 +535,11 @@ static void emit_sparc_Call(const ir_node *node) be_emit_finish_line_gas(node); fill_delay_slot(); + + if (arch_irn_get_flags(node) & sparc_arch_irn_flag_aggregate_return) { + be_emit_cstring("\tunimp 8\n"); + be_emit_write_line(); + } } /** @@ -621,6 +630,10 @@ static void emit_be_MemPerm(const ir_node *node) static void emit_sparc_Return(const ir_node *node) { + ir_graph *irg = get_irn_irg(node); + ir_entity *entity = get_irg_entity(irg); + ir_type *type = get_entity_type(entity); + const char *destreg = "%o7"; /* hack: we don't explicitely model register changes because of the @@ -632,7 +645,11 @@ static void emit_sparc_Return(const ir_node *node) } be_emit_cstring("\tjmp "); be_emit_string(destreg); - be_emit_cstring("+8"); + if (type->attr.ma.has_compound_ret_parameter) { + be_emit_cstring("+12"); + } else { + be_emit_cstring("+8"); + } be_emit_finish_line_gas(node); fill_delay_slot(); } diff --git a/ir/be/sparc/sparc_nodes_attr.h b/ir/be/sparc/sparc_nodes_attr.h index 4a44251d2..b1c0011b7 100644 --- a/ir/be/sparc/sparc_nodes_attr.h +++ b/ir/be/sparc/sparc_nodes_attr.h @@ -46,6 +46,7 @@ enum sparc_arch_irn_flags_t { sparc_arch_irn_flag_modifies_fp_flags = arch_irn_flags_backend << 1, sparc_arch_irn_flag_needs_64bit_spillslot = arch_irn_flags_backend << 2, sparc_arch_irn_flag_immediate_form = arch_irn_flags_backend << 3, + sparc_arch_irn_flag_aggregate_return = arch_irn_flags_backend << 4, }; /** diff --git a/ir/be/sparc/sparc_spec.pl b/ir/be/sparc/sparc_spec.pl index 502067ae8..4de1ed028 100644 --- a/ir/be/sparc/sparc_spec.pl +++ b/ir/be/sparc/sparc_spec.pl @@ -518,14 +518,17 @@ Call => { out_arity => "variable", constructors => { imm => { - attr => "ir_entity *entity, int32_t offset", - custominit => "\tsparc_set_attr_imm(res, entity, offset);", + attr => "ir_entity *entity, int32_t offset, bool aggregate_return", + custominit => "\tsparc_set_attr_imm(res, entity, offset);". + "\tif (aggregate_return) arch_irn_add_flags(res, sparc_arch_irn_flag_aggregate_return);", arity => "variable", out_arity => "variable", }, reg => { - arity => "variable", - out_arity => "variable", + attr => "bool aggregate_return", + arity => "variable", + out_arity => "variable", + custominit => "\tif (aggregate_return) arch_irn_add_flags(res, sparc_arch_irn_flag_aggregate_return);", } }, }, diff --git a/ir/be/sparc/sparc_stackframe.c b/ir/be/sparc/sparc_stackframe.c index 22cd5fa84..e08043fa1 100644 --- a/ir/be/sparc/sparc_stackframe.c +++ b/ir/be/sparc/sparc_stackframe.c @@ -199,17 +199,19 @@ static void process_frame_types(ir_graph *irg) /* initially the stackpointer points to the begin of our stackframe. * Situation at the begin of our function: * - * high address |----------------------------| - * | ... | - * arg-type | stackarg 1 | - * | stackarg 0 | - * |----------------------------| - * between type | 92-bytes utility+save area | - * stack pointer -> |----------------------------| - * | high end of stackframe | - * | ... | - * | low end of stackframe | - * |----------------------------| + * high address |-----------------------------| + * | ... | + * arg-type | stackarg 1 | + * | stackarg 0 | + * |-----------------------------| + * | space for storing regarg0-5 | + * between type | pointer to aggregate return | + * | 16 words save are | + * stack pointer -> |-----------------------------| + * | high end of stackframe | + * | ... | + * | low end of stackframe | + * low address |-----------------------------| */ ir_type *between_type = layout->between_type; unsigned between_size = get_type_size_bytes(between_type); diff --git a/ir/be/sparc/sparc_transform.c b/ir/be/sparc/sparc_transform.c index 98084211b..4a6c6ffa6 100644 --- a/ir/be/sparc/sparc_transform.c +++ b/ir/be/sparc/sparc_transform.c @@ -1649,6 +1649,8 @@ static ir_node *gen_Call(ir_node *node) = rbitset_popcount(cconv->caller_saves, N_SPARC_REGISTERS); ir_entity *entity = NULL; ir_node *new_frame = get_stack_pointer_for(node); + bool aggregate_return + = type->attr.ma.has_compound_ret_parameter; ir_node *incsp; int mem_pos; ir_node *res; @@ -1761,9 +1763,10 @@ static ir_node *gen_Call(ir_node *node) /* create call node */ if (entity != NULL) { res = new_bd_sparc_Call_imm(dbgi, new_block, in_arity, in, out_arity, - entity, 0); + entity, 0, aggregate_return); } else { - res = new_bd_sparc_Call_reg(dbgi, new_block, in_arity, in, out_arity); + res = new_bd_sparc_Call_reg(dbgi, new_block, in_arity, in, out_arity, + aggregate_return); } arch_set_in_register_reqs(res, in_req); diff --git a/ir/lower/lower_calls.c b/ir/lower/lower_calls.c index 2560b3f09..fbb1e6407 100644 --- a/ir/lower/lower_calls.c +++ b/ir/lower/lower_calls.c @@ -147,6 +147,7 @@ static ir_type *lower_mtp(compound_call_lowering_flags flags, ir_type *mtp) /* create the new type */ lowered = new_d_type_method(nn_params, nn_ress, get_type_dbg_info(mtp)); + lowered->attr.ma.has_compound_ret_parameter = true; /* fill it */ for (i = 0; i < nn_params; ++i) diff --git a/ir/tr/type_t.h b/ir/tr/type_t.h index 3b7c3bdc3..660fb24f2 100644 --- a/ir/tr/type_t.h +++ b/ir/tr/type_t.h @@ -27,6 +27,7 @@ #ifndef FIRM_TR_TYPE_T_H #define FIRM_TR_TYPE_T_H +#include #include "typerep.h" #include "tpop_t.h" #include "irgraph.h" @@ -72,8 +73,9 @@ typedef struct { size_t n_res; /**< Number of results. */ tp_ent_pair *res_type; /**< Array of result type/value ir_entity pairs. */ ir_variadicity variadicity; /**< The variadicity of the method. */ -mtp_additional_properties additional_properties; /**< Set of additional method properties. */ + mtp_additional_properties additional_properties; /**< Set of additional method properties. */ unsigned irg_calling_conv; /**< A set of calling convention flags. */ + bool has_compound_ret_parameter : 1; /**< first parameter compound return address */ } mtd_attr; /** Union type attributes. */ -- 2.20.1