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;
/* 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);
}
* @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;
}
/* 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)
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. */
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);
}
/* 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;
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;
* @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);
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);
}
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;