X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbeabi.c;h=2de57d9de455f706d46650b7560fe508056e61d8;hb=8694468860fe14808c20e9e246fe1368c097b322;hp=d5d29b3c95915a4c2d689bc0cea00c6742a6e366;hpb=ea64ddabccc512b21b425e4d89fda5e4ffe124a6;p=libfirm diff --git a/ir/be/beabi.c b/ir/be/beabi.c index d5d29b3c9..2de57d9de 100644 --- a/ir/be/beabi.c +++ b/ir/be/beabi.c @@ -96,6 +96,9 @@ struct _be_abi_irg_t { void *cb; /**< ABI Callback self pointer. */ + pmap *keep_map; /**< mapping blocks to keep nodes. */ + pset *ignore_regs; /**< Additional registers which shall be ignored. */ + arch_irn_handler_t irn_handler; arch_irn_ops_t irn_ops; DEBUG_ONLY(firm_dbg_module_t *dbg;) /**< The debugging module. */ @@ -108,6 +111,9 @@ struct _be_abi_irg_t { static const arch_irn_ops_if_t abi_irn_ops; static const arch_irn_handler_t abi_irn_handler; +/* Flag: if set, try to omit the frame pointer if called by the backend */ +int be_omit_fp = 1; + /* _ ____ ___ ____ _ _ _ _ / \ | __ )_ _| / ___|__ _| | | |__ __ _ ___| | _____ @@ -206,12 +212,14 @@ be_abi_call_flags_t be_abi_call_get_flags(const be_abi_call_t *call) * * @return the new ABI call object */ -static be_abi_call_t *be_abi_call_new(void) +static be_abi_call_t *be_abi_call_new() { be_abi_call_t *call = xmalloc(sizeof(call[0])); call->flags.val = 0; call->params = new_set(cmp_call_arg, 16); call->cb = NULL; + + call->flags.bits.try_omit_fp = be_omit_fp; return call; } @@ -458,9 +466,13 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) int curr_ofs = 0; int do_seq = call->flags.bits.store_args_sequential && !no_alloc; - /* Reverse list of stack parameters if call arguments are from left to right */ - if(call->flags.bits.left_to_right) { - for(i = 0; i < n_pos / 2; ++i) { + /* + * Reverse list of stack parameters if call arguments are from left to right. + * We must them reverse again in they are pushed (not stored) and the stack + * direction is downwards. + */ + if (call->flags.bits.left_to_right ^ (do_seq && stack_dir < 0)) { + for(i = 0; i < n_pos >> 1; ++i) { int other = n_pos - i - 1; int tmp = pos[i]; pos[i] = pos[other]; @@ -488,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); } @@ -510,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, no_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); @@ -607,7 +623,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) be_Call_set_entity(low_call, get_SymConst_entity(call_ptr)); } - else + else low_call = be_new_Call(get_irn_dbg_info(irn), irg, bl, curr_mem, curr_sp, call_ptr, curr_res_proj + pset_count(caller_save), n_low_args, in, get_Call_type(irn)); @@ -715,10 +731,6 @@ static ir_node *adjust_alloc(be_abi_irg_t *env, ir_node *alloc, ir_node *curr_sp const ir_edge_t *edge; ir_node *new_alloc; - env->call->flags.bits.try_omit_fp = 0; - - new_alloc = be_new_AddSP(env->isa->sp, irg, bl, curr_sp, get_Alloc_size(alloc)); - foreach_out_edge(alloc, edge) { ir_node *irn = get_edge_src_irn(edge); @@ -735,10 +747,19 @@ static ir_node *adjust_alloc(be_abi_irg_t *env, ir_node *alloc, ir_node *curr_sp } } - /* TODO: Beware: currently Alloc nodes without a result might happen, - only escape analysis kills them and this phase runs only for object - oriented source. So this must be fixed. */ - assert(alloc_res != NULL); + /* Beware: currently Alloc nodes without a result might happen, + only escape analysis kills them and this phase runs only for object + oriented source. We kill the Alloc here. */ + if (alloc_res == NULL) { + exchange(alloc_mem, get_Alloc_mem(alloc)); + return curr_sp; + } + + /* The stack pointer will be modified in an unknown manner. + We cannot omit it. */ + env->call->flags.bits.try_omit_fp = 0; + new_alloc = be_new_AddSP(env->isa->sp, irg, bl, curr_sp, get_Alloc_size(alloc)); + exchange(alloc_res, env->isa->stack_dir < 0 ? new_alloc : curr_sp); if(alloc_mem != NULL) @@ -842,6 +863,7 @@ static void process_calls_in_block(ir_node *bl, void *data) /* If there were call nodes in the block. */ if(n > 0) { + ir_node *keep; ir_node **nodes; int i; @@ -869,7 +891,8 @@ static void process_calls_in_block(ir_node *bl, void *data) /* Keep the last stack state in the block by tying it to Keep node */ nodes[0] = curr_sp; - be_new_Keep(env->isa->sp->reg_class, get_irn_irg(bl), bl, 1, nodes); + keep = be_new_Keep(env->isa->sp->reg_class, get_irn_irg(bl), bl, 1, nodes); + pmap_insert(env->keep_map, bl, keep); } set_irn_link(bl, curr_sp); @@ -895,6 +918,7 @@ static void collect_return_walker(ir_node *irn, void *data) } } +#if 0 /* static ir_node *setup_frame(be_abi_irg_t *env) { const arch_isa_t *isa = env->birg->main_env->arch_env->isa; @@ -971,6 +995,8 @@ static void clearup_frame(be_abi_irg_t *env, ir_node *ret, pmap *reg_map, struct obstack_ptr_grow(obst, irn); } } +*/ +#endif static ir_type *compute_arg_type(be_abi_irg_t *env, be_abi_call_t *call, ir_type *method_type) { @@ -1081,11 +1107,14 @@ static reg_node_map_t *reg_map_to_arr(struct obstack *obst, pmap *reg_map) return res; } -static void create_barrier(be_abi_irg_t *env, ir_node *bl, ir_node **mem, pmap *regs, int in_req) +/** + * Creates a barrier. + */ +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; @@ -1105,9 +1134,10 @@ static void create_barrier(be_abi_irg_t *env, ir_node *bl, ir_node **mem, pmap * 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); @@ -1116,8 +1146,15 @@ static void create_barrier(be_abi_irg_t *env, ir_node *bl, ir_node **mem, pmap * be_set_constr_single_reg(irn, pos, reg); be_node_set_reg_class(irn, pos, reg->reg_class); arch_set_irn_register(env->birg->main_env->arch_env, proj, reg); - if(arch_register_type_is(reg, ignore)) - be_node_set_flags(irn, pos, arch_irn_flags_ignore); + + /* 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)) + 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); } @@ -1127,6 +1164,118 @@ static void create_barrier(be_abi_irg_t *env, ir_node *bl, ir_node **mem, pmap * } obstack_free(&env->obst, rm); + 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; + + pmap *reg_map = pmap_create(); + ir_node *keep = pmap_get(env->keep_map, bl); + int in_max; + ir_node *ret; + int i, n; + ir_node **in; + ir_node *stack; + const arch_register_t **regs; + pmap_entry *ent ; + + /* + get the valid stack node in this block. + If we had a call in that block there is a Keep constructed by process_calls() + which points to the last stack modification in that block. we'll use + it then. Else we use the stack from the start block and let + the ssa construction fix the usage. + */ + 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); + set_nodes_block(keep, bad); + set_irn_n(keep, 0, bad); + // exchange(keep, new_r_Bad(env->birg->irg)); + } + + /* Insert results for Return into the register map. */ + for(i = 0; i < n_res; ++i) { + ir_node *res = get_Return_res(irn, i); + be_abi_call_arg_t *arg = get_call_arg(call, 1, i); + assert(arg->in_reg && "return value must be passed in register"); + pmap_insert(reg_map, (void *) arg->reg, res); + } + + /* Add uses of the callee save registers. */ + pmap_foreach(env->regs, ent) { + const arch_register_t *reg = ent->key; + if(arch_register_type_is(reg, callee_save) || arch_register_type_is(reg, ignore)) + 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); + + /* + Maximum size of the in array for Return nodes is + return args + callee save/ignore registers + memory + stack pointer + */ + in_max = pmap_count(reg_map) + n_res + 2; + + in = obstack_alloc(&env->obst, in_max * sizeof(in[0])); + regs = obstack_alloc(&env->obst, in_max * sizeof(regs[0])); + + in[0] = mem; + in[1] = be_abi_reg_map_get(reg_map, isa->sp); + regs[0] = NULL; + regs[1] = isa->sp; + n = 2; + + /* clear SP entry, since it has already been grown. */ + pmap_insert(reg_map, (void *) isa->sp, NULL); + for(i = 0; i < n_res; ++i) { + ir_node *res = get_Return_res(irn, i); + be_abi_call_arg_t *arg = get_call_arg(call, 1, i); + + in[n] = be_abi_reg_map_get(reg_map, arg->reg); + regs[n++] = arg->reg; + + /* Clear the map entry to mark the register as processed. */ + be_abi_reg_map_set(reg_map, arg->reg, NULL); + } + + /* grow the rest of the stuff. */ + pmap_foreach(reg_map, ent) { + if(ent->value) { + in[n] = ent->value; + regs[n++] = ent->key; + } + } + + /* 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); + + /* Set the register classes of the return's parameter accordingly. */ + for(i = 0; i < n; ++i) + if(regs[i]) + be_node_set_reg_class(ret, i, regs[i]->reg_class); + + /* Free the space of the Epilog's in array and the register <-> proj map. */ + obstack_free(&env->obst, in); + pmap_destroy(reg_map); + + return ret; } /** @@ -1147,20 +1296,20 @@ static void modify_irg(be_abi_irg_t *env) pset *dont_save = pset_new_ptr(8); int n_params = get_method_n_params(method_type); int max_arg = 0; - DEBUG_ONLY(firm_dbg_module_t *dbg = env->dbg;) int i, j, n; reg_node_map_t *rm; const arch_register_t *fp_reg; ir_node *frame_pointer; + ir_node *barrier; ir_node *reg_params_bl; ir_node **args; const ir_edge_t *edge; ir_type *arg_type, *bet_type; - pmap_entry *ent; bitset_t *used_proj_nr; + DEBUG_ONLY(firm_dbg_module_t *dbg = env->dbg;) DBG((dbg, LEVEL_1, "introducing abi on %+F\n", irg)); @@ -1235,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); @@ -1252,22 +1403,34 @@ 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)); } obstack_free(&env->obst, rm); /* Generate the Prologue */ - fp_reg = call->cb->prologue(env->cb, &mem, env->regs); - create_barrier(env, bl, &mem, env->regs, 0); + fp_reg = call->cb->prologue(env->cb, &mem, env->regs); + /* do the stack allocation BEFORE the barrier, or spill code + might be added before it */ env->init_sp = be_abi_reg_map_get(env->regs, sp); - env->init_sp = be_new_IncSP(sp, irg, bl, env->init_sp, no_mem, BE_STACK_FRAME_SIZE, be_stack_dir_expand); - arch_set_irn_register(env->birg->main_env->arch_env, env->init_sp, sp); + env->init_sp = be_new_IncSP(sp, irg, bl, env->init_sp, no_mem, BE_STACK_FRAME_SIZE, be_stack_dir_expand); be_abi_reg_map_set(env->regs, sp, env->init_sp); + + barrier = create_barrier(env, bl, &mem, env->regs, 0); + + env->init_sp = be_abi_reg_map_get(env->regs, sp); + arch_set_irn_register(env->birg->main_env->arch_env, env->init_sp, sp); + frame_pointer = be_abi_reg_map_get(env->regs, fp_reg); set_irg_frame(irg, frame_pointer); + pset_insert_ptr(env->ignore_regs, fp_reg); /* Now, introduce stack param nodes for all parameters passed on the stack */ for(i = 0; i < max_arg; ++i) { @@ -1309,91 +1472,16 @@ static void modify_irg(be_abi_irg_t *env) } /* All Return nodes hang on the End node, so look for them there. */ - for(i = 0, n = get_irn_arity(end); i < n; ++i) { - ir_node *irn = get_irn_n(end, i); - - if(get_irn_opcode(irn) == iro_Return) { - ir_node *bl = get_nodes_block(irn); - int n_res = get_Return_n_ress(irn); - pmap *reg_map = pmap_create(); - ir_node *mem = get_Return_mem(irn); - int in_max; - ir_node *ret; - int i, n; - ir_node **in; - const arch_register_t **regs; - - pmap_insert(reg_map, (void *) sp, pmap_get(env->regs, (void *) sp)); - - /* Insert results for Return into the register map. */ - for(i = 0; i < n_res; ++i) { - ir_node *res = get_Return_res(irn, i); - be_abi_call_arg_t *arg = get_call_arg(call, 1, i); - assert(arg->in_reg && "return value must be passed in register"); - pmap_insert(reg_map, (void *) arg->reg, res); - } - - /* Add uses of the callee save registers. */ - pmap_foreach(env->regs, ent) { - const arch_register_t *reg = ent->key; - if(arch_register_type_is(reg, callee_save) || arch_register_type_is(reg, ignore)) - pmap_insert(reg_map, ent->key, ent->value); - } - - /* 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); + for (i = 0, n = get_Block_n_cfgpreds(end); i < n; ++i) { + ir_node *irn = get_Block_cfgpred(end, i); - /* - Maximum size of the in array for Return nodes is - return args + callee save/ignore registers + memory + stack pointer - */ - in_max = pmap_count(reg_map) + get_Return_n_ress(irn) + 2; - - in = obstack_alloc(&env->obst, in_max * sizeof(in[0])); - regs = obstack_alloc(&env->obst, in_max * sizeof(regs[0])); - - in[0] = mem; - in[1] = be_abi_reg_map_get(reg_map, sp); - regs[0] = NULL; - regs[1] = sp; - n = 2; - - /* clear SP entry, since it has already been grown. */ - pmap_insert(reg_map, (void *) sp, NULL); - for(i = 0; i < n_res; ++i) { - ir_node *res = get_Return_res(irn, i); - be_abi_call_arg_t *arg = get_call_arg(call, 1, i); - - in[n] = be_abi_reg_map_get(reg_map, arg->reg); - regs[n++] = arg->reg; - - /* Clear the map entry to mark the register as processed. */ - be_abi_reg_map_set(reg_map, arg->reg, NULL); - } - - /* grow the rest of the stuff. */ - pmap_foreach(reg_map, ent) { - if(ent->value) { - in[n] = ent->value; - regs[n++] = ent->key; - } - } - - /* The in array for the new back end return is now ready. */ - ret = be_new_Return(get_irn_dbg_info(irn), irg, bl, n, in); - - /* Set the register classes of the return's parameter accordingly. */ - for(i = 0; i < n; ++i) - if(regs[i]) - be_node_set_reg_class(ret, i, regs[i]->reg_class); - - /* Free the space of the Epilog's in array and the register <-> proj map. */ - obstack_free(&env->obst, in); + 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); - pmap_destroy(reg_map); } } + /* 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); @@ -1418,11 +1506,15 @@ be_abi_irg_t *be_abi_introduce(be_irg_t *birg) pmap_entry *ent; ir_node *dummy; + obstack_init(&env->obst); + env->isa = birg->main_env->arch_env->isa; env->method_type = get_entity_type(get_irg_entity(irg)); env->call = be_abi_call_new(); arch_isa_get_call_abi(env->isa, env->method_type, env->call); + env->ignore_regs = pset_new_ptr_default(); + env->keep_map = pmap_create(); env->dce_survivor = new_survive_dce(); env->birg = birg; env->stack_phis = pset_new_ptr(16); @@ -1431,8 +1523,6 @@ be_abi_irg_t *be_abi_introduce(be_irg_t *birg) env->cb = env->call->cb->init(env->call, birg->main_env->arch_env, irg); - obstack_init(&env->obst); - memcpy(&env->irn_handler, &abi_irn_handler, sizeof(abi_irn_handler)); env->irn_ops.impl = &abi_irn_ops; @@ -1442,6 +1532,9 @@ be_abi_irg_t *be_abi_introduce(be_irg_t *birg) /* Process the IRG */ modify_irg(env); + /* We don't need the keep map anymore. */ + pmap_destroy(env->keep_map); + /* reroute the stack origin of the calls to the true stack origin. */ edges_reroute(dummy, env->init_sp, irg); edges_reroute(old_frame, get_irg_frame(irg), irg); @@ -1462,12 +1555,22 @@ void be_abi_free(be_abi_irg_t *env) { free_survive_dce(env->dce_survivor); del_pset(env->stack_phis); + del_pset(env->ignore_regs); pmap_destroy(env->regs); obstack_free(&env->obst, NULL); arch_env_pop_irn_handler(env->birg->main_env->arch_env); free(env); } +void be_abi_put_ignore_regs(be_abi_irg_t *abi, const arch_register_class_t *cls, bitset_t *bs) +{ + arch_register_t *reg; + + for(reg = pset_first(abi->ignore_regs); reg; reg = pset_next(abi->ignore_regs)) + if(reg->reg_class == cls) + bitset_set(bs, reg->index); +} + /* @@ -1479,24 +1582,35 @@ void be_abi_free(be_abi_irg_t *env) */ +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); @@ -1569,6 +1683,9 @@ struct bias_walk { int start_block_bias; /**< The bias at the end of the start block. */ }; +/** + * Block-Walker: fix all stack offsets + */ static void stack_bias_walker(ir_node *bl, void *data) { if(bl != get_irg_start_block(get_irn_irg(bl))) { @@ -1585,7 +1702,7 @@ void be_abi_fix_stack_bias(be_abi_irg_t *env) stack_frame_compute_initial_offset(env->frame); // stack_frame_dump(stdout, env->frame); - /* Determine the stack bias at the and of the start block. */ + /* Determine the stack bias at the end of the start block. */ bw.start_block_bias = process_stack_bias(env, get_irg_start_block(irg), 0); /* fix the bias is all other blocks */ @@ -1672,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)