unsigned in_reg : 1; /**< 1: this argument is transmitted in registers. */
unsigned on_stack : 1; /**< 1: this argument is transmitted on the stack. */
- int pos;
+ int pos;
const arch_register_t *reg;
- ir_entity *stack_ent;
- unsigned alignment; /**< stack alignment */
- unsigned space_before; /**< allocate space before */
- unsigned space_after; /**< allocate space after */
+ ir_entity *stack_ent;
+ ir_mode *load_mode;
+ unsigned alignment; /**< stack alignment */
+ unsigned space_before; /**< allocate space before */
+ unsigned space_after; /**< allocate space after */
} 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;
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)
}
-void be_abi_call_param_stack(be_abi_call_t *call, int arg_pos, unsigned alignment, unsigned space_before, unsigned space_after)
+void be_abi_call_param_stack(be_abi_call_t *call, int arg_pos, ir_mode *load_mode, unsigned alignment, unsigned space_before, unsigned space_after)
{
be_abi_call_arg_t *arg = get_or_set_call_arg(call, 0, arg_pos, 1);
arg->on_stack = 1;
+ arg->load_mode = load_mode;
arg->alignment = alignment;
arg->space_before = space_before;
arg->space_after = space_after;
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);
n_reg_results + pn_be_Call_first_res + pset_count(caller_save),
n_ins, in, get_Call_type(irn));
}
+ be_Call_set_pop(low_call, call->pop);
ARR_APP1(ir_node *, env->calls, low_call);
+ /* create new stack pointer */
+ curr_sp = new_r_Proj(irg, bl, low_call, get_irn_mode(curr_sp),
+ pn_be_Call_sp);
+ be_set_constr_single_reg(low_call, BE_OUT_POS(pn_be_Call_sp), sp);
+ arch_set_irn_register(arch_env, curr_sp, sp);
+ be_node_set_flags(low_call, BE_OUT_POS(pn_be_Call_sp),
+ arch_irn_flags_ignore | arch_irn_flags_modify_sp);
+
for(i = 0; i < n_res; ++i) {
int pn;
ir_node *proj = res_projs[i];
/* Make additional projs for the caller save registers
and the Keep node which keeps them alive. */
- if (pset_count(caller_save) + n_reg_results > 0) {
+ if (1 || pset_count(caller_save) + n_reg_results > 0) {
const arch_register_t *reg;
ir_node **in, *keep;
- int i, n;
+ int i;
+ int n = 0;
int curr_res_proj
= pn_be_Call_first_res + n_reg_results;
- for (reg = pset_first(caller_save), n = 0; reg; reg = pset_next(caller_save), ++n) {
+ /* also keep the stack pointer */
+ ++n;
+ set_irn_link(curr_sp, (void*) sp);
+ obstack_ptr_grow(obst, curr_sp);
+
+ for (reg = pset_first(caller_save); reg; reg = pset_next(caller_save), ++n) {
ir_node *proj = new_r_Proj(irg, bl, low_call, reg->reg_class->mode,
curr_res_proj);
/* memorize the register in the link field. we need afterwards to set the register class of the keep correctly. */
be_set_constr_single_reg(low_call, BE_OUT_POS(curr_res_proj), reg);
- arch_set_irn_register(env->birg->main_env->arch_env, proj, reg);
+ arch_set_irn_register(arch_env, proj, reg);
/* a call can produce ignore registers, in this case set the flag and register for the Proj */
if (arch_register_type_is(reg, ignore)) {
}
/* Clean up the stack. */
+ assert(stack_size >= call->pop);
+ stack_size -= call->pop;
+
if (stack_size > 0) {
ir_node *mem_proj = NULL;
}
if (! mem_proj) {
- mem_proj = new_r_Proj(irg, bl, low_call, mode_M, pn_Call_M);
+ mem_proj = new_r_Proj(irg, bl, low_call, mode_M, pn_be_Call_M_regular);
keep_alive(mem_proj);
}
/* 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);
}
}
obstack_free(&env->obst, nodes);
- /* Keep the last stack state in the block by tying it to Keep node */
- if(curr_sp != env->init_sp) {
+ /* Keep the last stack state in the block by tying it to Keep node,
+ * the proj from calls is already kept */
+ if(curr_sp != env->init_sp
+ && !(is_Proj(curr_sp) && be_is_Call(get_Proj_pred(curr_sp)))) {
nodes[0] = curr_sp;
keep = be_new_Keep(env->isa->sp->reg_class, get_irn_irg(bl),
bl, 1, nodes);
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;
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. */
if (arg->in_reg) {
repl = pmap_get(env->regs, (void *) arg->reg);
- }
-
- else if(arg->on_stack) {
+ } else if(arg->on_stack) {
ir_node *addr = be_new_FrameAddr(sp->reg_class, irg, reg_params_bl, frame_pointer, arg->stack_ent);
/* For atomic parameters which are actually used, we create a Load node. */
if(is_atomic_type(param_type) && get_irn_n_edges(args[i]) > 0) {
- ir_mode *mode = get_type_mode(param_type);
- ir_node *load = new_rd_Load(NULL, irg, reg_params_bl,
- new_NoMem(), addr, mode);
- repl = new_rd_Proj(NULL, irg, reg_params_bl, load,
- mode, pn_Load_res);
- }
+ ir_mode *mode = get_type_mode(param_type);
+ ir_mode *load_mode = arg->load_mode;
+
+ ir_node *load = new_r_Load(irg, reg_params_bl, new_NoMem(), addr, load_mode);
+ set_irn_pinned(load, op_pin_state_floats);
+ repl = new_r_Proj(irg, reg_params_bl, load, load_mode, pn_Load_res);
- /* The stack parameter is not primitive (it is a struct or array),
- we thus will create a node representing the parameter's address
- on the stack. */
- else {
+ if (mode != load_mode) {
+ repl = new_r_Conv(irg, reg_params_bl, repl, mode);
+ }
+ } else {
+ /* The stack parameter is not primitive (it is a struct or array),
+ * we thus will create a node representing the parameter's address
+ * on the stack. */
repl = addr;
}
}