X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbeabi.c;h=2de57d9de455f706d46650b7560fe508056e61d8;hb=8694468860fe14808c20e9e246fe1368c097b322;hp=2fcb3033a55db2fc516c3e006b5a7ee3b06581f9;hpb=0d5be81726ac97d9c03854f92248f5f803e587cb;p=libfirm diff --git a/ir/be/beabi.c b/ir/be/beabi.c index 2fcb3033a..2de57d9de 100644 --- a/ir/be/beabi.c +++ b/ir/be/beabi.c @@ -500,17 +500,29 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) type *param_type = get_method_param_type(mt, p); int param_size = get_type_size_bytes(param_type) + arg->space_after; - curr_ofs += arg->space_before; - curr_ofs = round_up2(curr_ofs, arg->alignment); + /* + * If we wanted to build the arguments sequentially, + * the stack pointer for the next must be incremented, + * and the memory value propagated. + */ + if (do_seq) { + curr_ofs = 0; + addr = curr_sp = be_new_IncSP(sp, irg, bl, curr_sp, curr_mem, + param_size + arg->space_before, be_stack_dir_expand); + } + else { + curr_ofs += arg->space_before; + curr_ofs = round_up2(curr_ofs, arg->alignment); - /* Make the expression to compute the argument's offset. */ - if(curr_ofs > 0) { - addr = new_r_Const_long(irg, bl, mode_Is, curr_ofs); - addr = new_r_Add(irg, bl, curr_sp, addr, mach_mode); + /* Make the expression to compute the argument's offset. */ + if(curr_ofs > 0) { + addr = new_r_Const_long(irg, bl, mode_Is, curr_ofs); + addr = new_r_Add(irg, bl, curr_sp, addr, mach_mode); + } } /* Insert a store for primitive arguments. */ - if(is_atomic_type(param_type)) { + if (is_atomic_type(param_type)) { mem = new_r_Store(irg, bl, curr_mem, addr, param); mem = new_r_Proj(irg, bl, mem, mode_M, pn_Store_M); } @@ -522,20 +534,12 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) mem = new_r_Proj(irg, bl, mem, mode_M, pn_CopyB_M_regular); } - obstack_ptr_grow(obst, mem); - curr_ofs += param_size; - /* - * If we wanted to build the arguments sequentially, - * the stack pointer for the next must be incremented, - * and the memory value propagated. - */ - if(do_seq) { - curr_ofs = 0; - curr_sp = be_new_IncSP(sp, irg, bl, curr_sp, curr_mem, param_size, be_stack_dir_expand); + if (do_seq) curr_mem = mem; - } + else + obstack_ptr_grow(obst, mem); } in = (ir_node **) obstack_finish(obst); @@ -1109,8 +1113,8 @@ static reg_node_map_t *reg_map_to_arr(struct obstack *obst, pmap *reg_map) static ir_node *create_barrier(be_abi_irg_t *env, ir_node *bl, ir_node **mem, pmap *regs, int in_req) { ir_graph *irg = env->birg->irg; + int n_regs = pmap_count(regs); int n; - int n_regs = pmap_count(regs); ir_node *irn; ir_node **in; reg_node_map_t *rm; @@ -1130,9 +1134,10 @@ static ir_node *create_barrier(be_abi_irg_t *env, ir_node *bl, ir_node **mem, pm obstack_free(&env->obst, in); for(n = 0; n < n_regs; ++n) { - int pos = BE_OUT_POS(n); - ir_node *proj; const arch_register_t *reg = rm[n].reg; + int flags = 0; + int pos = BE_OUT_POS(n); + ir_node *proj; proj = new_r_Proj(irg, bl, irn, get_irn_mode(rm[n].irn), n); be_node_set_reg_class(irn, n, reg->reg_class); @@ -1144,7 +1149,12 @@ static ir_node *create_barrier(be_abi_irg_t *env, ir_node *bl, ir_node **mem, pm /* if the proj projects a ignore register or a node which is set to ignore, propagate this property. */ if(arch_register_type_is(reg, ignore) || arch_irn_is(env->birg->main_env->arch_env, in[n], ignore)) - be_node_set_flags(irn, pos, arch_irn_flags_ignore); + flags |= arch_irn_flags_ignore; + + if(arch_irn_is(env->birg->main_env->arch_env, in[n], modify_sp)) + flags |= arch_irn_flags_modify_sp; + + be_node_set_flags(irn, pos, flags); pmap_insert(regs, (void *) reg, proj); } @@ -1157,6 +1167,15 @@ static ir_node *create_barrier(be_abi_irg_t *env, ir_node *bl, ir_node **mem, pm return irn; } +/** + * Creates a be_Return for a Return node. + * + * @param @env the abi environment + * @param irn the Return node or NULL if there was none + * @param bl the block where the be_Retun should be placed + * @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; const arch_isa_t *isa = env->birg->main_env->arch_env->isa; @@ -1180,10 +1199,12 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl, i */ stack = be_abi_reg_map_get(env->regs, isa->sp); if (keep) { + ir_node *bad = new_r_Bad(env->birg->irg); stack = get_irn_n(keep, 0); - exchange(keep, new_r_Bad(env->birg->irg)); + set_nodes_block(keep, bad); + set_irn_n(keep, 0, bad); + // exchange(keep, new_r_Bad(env->birg->irg)); } - be_abi_reg_map_set(reg_map, isa->sp, stack); /* Insert results for Return into the register map. */ for(i = 0; i < n_res; ++i) { @@ -1200,6 +1221,8 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl, i pmap_insert(reg_map, ent->key, ent->value); } + be_abi_reg_map_set(reg_map, isa->sp, stack); + /* Make the Epilogue node and call the arch's epilogue maker. */ create_barrier(env, bl, &mem, reg_map, 1); call->cb->epilogue(env->cb, bl, &mem, reg_map); @@ -1361,10 +1384,12 @@ static void modify_irg(be_abi_irg_t *env) for(i = 0, n = pmap_count(env->regs); i < n; ++i) { arch_register_t *reg = (void *) rm[i].reg; ir_node *arg_proj = rm[i].irn; - ir_node *proj; ir_mode *mode = arg_proj ? get_irn_mode(arg_proj) : reg->reg_class->mode; long nr = i; int pos = BE_OUT_POS((int) nr); + int flags = 0; + + ir_node *proj; assert(nr >= 0); bitset_set(used_proj_nr, nr); @@ -1378,7 +1403,12 @@ static void modify_irg(be_abi_irg_t *env) * The Proj for that register shall also be ignored during register allocation. */ if(arch_register_type_is(reg, ignore)) - be_node_set_flags(env->reg_params, pos, arch_irn_flags_ignore); + flags |= arch_irn_flags_ignore; + + if(reg == sp) + flags |= arch_irn_flags_modify_sp; + + be_node_set_flags(env->reg_params, pos, flags); DBG((dbg, LEVEL_2, "\tregister save proj #%d -> reg %s\n", nr, reg->name)); } @@ -1445,17 +1475,13 @@ static void modify_irg(be_abi_irg_t *env) for (i = 0, n = get_Block_n_cfgpreds(end); i < n; ++i) { ir_node *irn = get_Block_cfgpred(end, i); - if (get_irn_opcode(irn) == iro_Return) { + if (is_Return(irn)) { ir_node *ret = create_be_return(env, irn, get_nodes_block(irn), get_Return_mem(irn), get_Return_n_ress(irn)); exchange(irn, ret); } } - - if (n <= 0) { - /* we have endless loops, add a dummy return without return vals */ - ir_node *ret = create_be_return(env, NULL, end, get_irg_no_mem(irg), n); - add_End_keepalive(get_irg_end(irg), ret); - } + /* if we have endless loops here, n might be <= 0. Do NOT create a be_Return than, + the code is dead and will never be executed. */ del_pset(dont_save); obstack_free(&env->obst, args); @@ -1556,27 +1582,35 @@ void be_abi_put_ignore_regs(be_abi_irg_t *abi, const arch_register_class_t *cls, */ +struct fix_stack_walker_info { + nodeset *nodes; + const arch_env_t *aenv; +}; + /** * Walker. Collect all stack modifying nodes. */ static void collect_stack_nodes_walker(ir_node *irn, void *data) { - pset *s = data; + struct fix_stack_walker_info *info = data; - if(be_is_AddSP(irn) || be_is_IncSP(irn) || be_is_SetSP(irn)) - pset_insert_ptr(s, irn); + if(arch_irn_is(info->aenv, irn, modify_sp)) + pset_insert_ptr(info->nodes, irn); } void be_abi_fix_stack_nodes(be_abi_irg_t *env) { dom_front_info_t *df; - pset *stack_nodes; + pset *stack_nodes = pset_new_ptr(16); + struct fix_stack_walker_info info; + + info.nodes = stack_nodes; + info.aenv = env->birg->main_env->arch_env; /* We need dominance frontiers for fix up */ df = be_compute_dominance_frontiers(env->birg->irg); - stack_nodes = pset_new_ptr(16); + irg_walk_graph(env->birg->irg, collect_stack_nodes_walker, NULL, &info); pset_insert_ptr(stack_nodes, env->init_sp); - irg_walk_graph(env->birg->irg, collect_stack_nodes_walker, NULL, stack_nodes); be_ssa_constr_set_phis(df, stack_nodes, env->stack_phis); del_pset(stack_nodes); @@ -1755,7 +1789,7 @@ static arch_irn_class_t abi_classify(const void *_self, const ir_node *irn) static arch_irn_flags_t abi_get_flags(const void *_self, const ir_node *irn) { - return arch_irn_flags_ignore; + return arch_irn_flags_ignore | arch_irn_flags_modify_sp; } static entity *abi_get_frame_entity(const void *_self, const ir_node *irn)