X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbeabi.c;h=d463723f412559a3c186ee17f40c0c941a92bb84;hb=4169e2e8894af2573c3724afee3c4c582b8a6130;hp=a763407a9dfd15c1347298bd402b673cd0bbf93c;hpb=523002f1fb52f2f3af8f817f4bb06289df98c55f;p=libfirm diff --git a/ir/be/beabi.c b/ir/be/beabi.c index a763407a9..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); @@ -831,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)) { @@ -846,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) @@ -1113,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; @@ -1134,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); @@ -1148,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); } @@ -1193,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) { @@ -1213,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); @@ -1374,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); @@ -1391,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)); } @@ -1488,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); @@ -1501,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); @@ -1565,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); @@ -1764,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)