X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=ir%2Fbe%2Fbeabi.c;h=d463723f412559a3c186ee17f40c0c941a92bb84;hb=4169e2e8894af2573c3724afee3c4c582b8a6130;hp=2fcb3033a55db2fc516c3e006b5a7ee3b06581f9;hpb=0d5be81726ac97d9c03854f92248f5f803e587cb;p=libfirm diff --git a/ir/be/beabi.c b/ir/be/beabi.c index 2fcb3033a..d463723f4 100644 --- a/ir/be/beabi.c +++ b/ir/be/beabi.c @@ -2,7 +2,8 @@ * ABI lowering. * * @author Sebastian Hack - * @date 7.3.2005 + * @date 7.3.2005 + * @cvsid $Id$ */ #ifdef HAVE_CONFIG_H @@ -353,18 +354,18 @@ static INLINE entity *get_sel_ent(ir_node *irn) /** * Walker: Replaces Loads, Stores and Sels of frame type entities - * by FrameLoad, FrameStore and FrameAdress. + * by FrameLoad, FrameStore and FrameAddress. */ static void lower_frame_sels_walker(ir_node *irn, void *data) { ir_node *nw = NULL; - entity *ent = get_sel_ent(irn); + entity *ent = get_sel_ent(irn); - if(ent != NULL) { - be_abi_irg_t *env = data; - ir_node *bl = get_nodes_block(irn); - ir_graph *irg = get_irn_irg(bl); - ir_node *frame = get_irg_frame(irg); + if (ent != NULL) { + be_abi_irg_t *env = data; + ir_node *bl = get_nodes_block(irn); + ir_graph *irg = get_irn_irg(bl); + ir_node *frame = get_irg_frame(irg); nw = be_new_FrameAddr(env->isa->sp->reg_class, irg, bl, frame, ent); exchange(irn, nw); @@ -500,17 +501,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 +535,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); @@ -827,6 +832,9 @@ static int cmp_call_dependecy(const void *c1, const void *c2) return n1 == n2 ? 0 : (dependent_on(n1, n2) ? -1 : 1); } +/** + * Walker: links all Call nodes to the Block they are contained. + */ static void link_calls_in_block_walker(ir_node *irn, void *data) { if(is_Call(irn)) { @@ -842,9 +850,10 @@ static void link_calls_in_block_walker(ir_node *irn, void *data) } /** - * Process all call nodes inside a basic block. + * Block-walker: + * Process all Call nodes inside a basic block. * Note that the link field of the block must contain a linked list of all - * Call nodes inside the block. We first order this list according to data dependency + * Call nodes inside the Block. We first order this list according to data dependency * and that connect the calls together. */ static void process_calls_in_block(ir_node *bl, void *data) @@ -1109,8 +1118,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 +1139,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 +1154,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 +1172,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 +1204,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 +1226,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 +1389,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 +1408,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 +1480,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); @@ -1479,6 +1510,7 @@ be_abi_irg_t *be_abi_introduce(be_irg_t *birg) pmap_entry *ent; ir_node *dummy; + optimization_state_t state; obstack_init(&env->obst); @@ -1492,7 +1524,12 @@ be_abi_irg_t *be_abi_introduce(be_irg_t *birg) env->dce_survivor = new_survive_dce(); env->birg = birg; env->stack_phis = pset_new_ptr(16); + /* Beware: later we replace this node by the real one, ensure it is not CSE'd + to another Unknown or the stack pointer gets used */ + save_optimization_state(&state); + set_optimize(0); env->init_sp = dummy = new_r_Unknown(irg, env->isa->sp->reg_class->mode); + restore_optimization_state(&state); FIRM_DBG_REGISTER(env->dbg, "firm.be.abi"); env->cb = env->call->cb->init(env->call, birg->main_env->arch_env, irg); @@ -1556,27 +1593,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 +1800,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)