X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbeabi.c;h=0f62ac708fc2e493b6cf82171c83d48040422ee9;hb=205396c4f4f5abe7abd6dc2350c8c398a7623afc;hp=4ff9cbd00da29aabb72da31985a94f0b2ce3bd04;hpb=87965f5c94d561cb15233b80711123f6edc80b30;p=libfirm diff --git a/ir/be/beabi.c b/ir/be/beabi.c index 4ff9cbd00..0f62ac708 100644 --- a/ir/be/beabi.c +++ b/ir/be/beabi.c @@ -6,7 +6,7 @@ * @cvsid $Id$ */ #ifdef HAVE_CONFIG_H -# include +# include "config.h" #endif #include "obst.h" @@ -31,12 +31,12 @@ #include "be.h" #include "beabi.h" -#include "bearch.h" +#include "bearch_t.h" #include "benode_t.h" #include "belive_t.h" #include "besched_t.h" -#include "beirg.h" -#include "beirgmod.h" +#include "beirg_t.h" +#include "bessaconstr.h" typedef struct _be_abi_call_arg_t { unsigned is_res : 1; /**< 1: the call argument is a return value. 0: it's a call parameter. */ @@ -93,14 +93,6 @@ struct _be_abi_irg_t { DEBUG_ONLY(firm_dbg_module_t *dbg;) /**< The debugging module. */ }; -#if 0 -#define get_abi_from_handler(ptr) firm_container_of(ptr, be_abi_irg_t, irn_handler) -#define get_abi_from_ops(ptr) firm_container_of(ptr, be_abi_irg_t, irn_ops) - -/* Forward, since be need it in be_abi_introduce(). */ -static const arch_irn_ops_if_t abi_irn_ops; -static const arch_irn_handler_t abi_irn_handler; -#endif static heights_t *ir_heights; /* Flag: if set, try to omit the frame pointer if called by the backend */ @@ -389,7 +381,8 @@ static INLINE int is_on_stack(be_abi_call_t *call, int pos) static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp, ir_node *alloca_copy) { ir_graph *irg = env->birg->irg; - const arch_isa_t *isa = env->birg->main_env->arch_env->isa; + const arch_env_t *arch_env = env->birg->main_env->arch_env; + const arch_isa_t *isa = arch_env->isa; ir_type *mt = get_Call_type(irn); ir_node *call_ptr = get_Call_ptr(irn); int n_params = get_method_n_params(mt); @@ -698,6 +691,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp, i assert(arg->in_reg); be_set_constr_single_reg(low_call, BE_OUT_POS(pn), arg->reg); + arch_set_irn_register(arch_env, res_projs[i], arg->reg); } obstack_free(obst, in); exchange(irn, low_call); @@ -900,6 +894,7 @@ static ir_node *adjust_free(be_abi_irg_t *env, ir_node *free, ir_node *curr_sp) ir_node *subsp, *mem, *res, *size, *sync; ir_type *type; ir_node *in[2]; + ir_mode *sp_mode; if (get_Free_where(free) != stack_alloc) { assert(0); @@ -909,6 +904,7 @@ static ir_node *adjust_free(be_abi_irg_t *env, ir_node *free, ir_node *curr_sp) block = get_nodes_block(free); irg = get_irn_irg(block); type = get_Free_type(free); + sp_mode = env->isa->sp->reg_class->mode; /* we might need to multiply the size with the element size */ if(type != get_unknown_type() && get_type_size_bytes(type) != 1) { @@ -927,7 +923,7 @@ static ir_node *adjust_free(be_abi_irg_t *env, ir_node *free, ir_node *curr_sp) subsp = be_new_SubSP(env->isa->sp, irg, block, curr_sp, size); mem = new_r_Proj(irg, block, subsp, mode_M, pn_be_SubSP_M); - res = new_r_Proj(irg, block, subsp, mode_P_data, pn_be_SubSP_res); + res = new_r_Proj(irg, block, subsp, sp_mode, pn_be_SubSP_res); /* we need to sync the memory */ in[0] = get_Free_mem(free); @@ -1678,7 +1674,9 @@ static void modify_irg(be_abi_irg_t *env) ir_graph *irg = env->birg->irg; ir_node *bl = get_irg_start_block(irg); ir_node *end = get_irg_end_block(irg); - ir_node *mem = get_irg_initial_mem(irg); + ir_node *old_mem = get_irg_initial_mem(irg); + ir_node *new_mem_proj; + ir_node *mem; ir_type *method_type = get_entity_type(get_irg_entity(irg)); pset *dont_save = pset_new_ptr(8); @@ -1819,6 +1817,13 @@ static void modify_irg(be_abi_irg_t *env) } obstack_free(&env->obst, rm); + /* create a new initial memory proj */ + assert(is_Proj(old_mem)); + new_mem_proj = new_r_Proj(irg, get_nodes_block(old_mem), + new_r_Unknown(irg, mode_T), mode_M, + get_Proj_proj(old_mem)); + mem = new_mem_proj; + /* Generate the Prologue */ fp_reg = call->cb->prologue(env->cb, &mem, env->regs); @@ -1837,6 +1842,10 @@ static void modify_irg(be_abi_irg_t *env) set_irg_frame(irg, frame_pointer); pset_insert_ptr(env->ignore_regs, fp_reg); + /* rewire old mem users to new mem */ + set_Proj_pred(new_mem_proj, get_Proj_pred(old_mem)); + exchange(old_mem, mem); + set_irg_initial_mem(irg, mem); /* Now, introduce stack param nodes for all parameters passed on the stack */ @@ -1909,7 +1918,7 @@ void fix_call_state_inputs(be_abi_irg_t *env) { const arch_isa_t *isa = env->isa; int i, n, n_states; - const arch_register_t **stateregs = NEW_ARR_F(const arch_register_t*, 0); + arch_register_t **stateregs = NEW_ARR_F(arch_register_t*, 0); /* Collect caller save registers */ n = arch_isa_get_n_reg_class(isa); @@ -1919,7 +1928,7 @@ void fix_call_state_inputs(be_abi_irg_t *env) for(j = 0; j < cls->n_regs; ++j) { const arch_register_t *reg = arch_register_for_index(cls, j); if(arch_register_type_is(reg, state)) { - ARR_APP1(arch_register_t*, stateregs, reg); + ARR_APP1(arch_register_t*, stateregs, (arch_register_t *)reg); } } } @@ -1985,11 +1994,6 @@ be_abi_irg_t *be_abi_introduce(be_irg_t *birg) restore_optimization_state(&state); FIRM_DBG_REGISTER(env->dbg, "firm.be.abi"); -#if 0 - memcpy(&env->irn_handler, &abi_irn_handler, sizeof(abi_irn_handler)); - env->irn_ops.impl = &abi_irn_ops; -#endif - env->calls = NEW_ARR_F(ir_node*, 0); /* Lower all call nodes in the IRG. */ @@ -2023,10 +2027,6 @@ be_abi_irg_t *be_abi_introduce(be_irg_t *birg) survive_dce_register_irn(env->dce_survivor, (ir_node **) &ent->value); } -#if 0 - arch_env_push_irn_handler(env->birg->main_env->arch_env, &env->irn_handler); -#endif - env->call->cb->done(env->cb); env->cb = NULL; return env; @@ -2038,9 +2038,6 @@ void be_abi_free(be_abi_irg_t *env) del_pset(env->ignore_regs); pmap_destroy(env->regs); obstack_free(&env->obst, NULL); -#if 0 - arch_env_pop_irn_handler(env->birg->main_env->arch_env); -#endif free(env); } @@ -2068,8 +2065,10 @@ const be_stack_layout_t *be_abi_get_stack_layout(const be_abi_irg_t *abi) { */ +typedef ir_node **node_array; + typedef struct fix_stack_walker_env_t { - ir_node **nodes; + node_array sp_nodes; const arch_env_t *arch_env; } fix_stack_walker_env_t; @@ -2080,46 +2079,65 @@ static void collect_stack_nodes_walker(ir_node *node, void *data) { fix_stack_walker_env_t *env = data; - if (is_Block(node)) - return; - if (arch_irn_is(env->arch_env, node, modify_sp)) { assert(get_irn_mode(node) != mode_M && get_irn_mode(node) != mode_T); - ARR_APP1(ir_node*, env->nodes, node); + ARR_APP1(ir_node*, env->sp_nodes, node); } } -void be_abi_fix_stack_nodes(be_abi_irg_t *env, be_lv_t *lv) +void be_abi_fix_stack_nodes(be_abi_irg_t *env) { - int i; + be_ssa_construction_env_t senv; + int i, len; ir_node **phis; be_irg_t *birg = env->birg; + be_lv_t *lv = be_get_birg_liveness(birg); fix_stack_walker_env_t walker_env; + arch_isa_t *isa; - walker_env.nodes = NEW_ARR_F(ir_node*, 0); + walker_env.sp_nodes = NEW_ARR_F(ir_node*, 0); walker_env.arch_env = birg->main_env->arch_env; - - be_assure_dom_front(birg); + isa = walker_env.arch_env->isa; irg_walk_graph(birg->irg, collect_stack_nodes_walker, NULL, &walker_env); - phis = be_ssa_construction( - be_get_birg_dom_front(birg), - be_get_birg_liveness(birg), - env->init_sp, - ARR_LEN(walker_env.nodes), walker_env.nodes, - NULL, 1); + /* nothing to be done if we didn't find any node, in fact we mustn't + * continue, as for endless loops incsp might have had no users and is bad + * now. + */ + len = ARR_LEN(walker_env.sp_nodes); + if(len == 0) { + DEL_ARR_F(walker_env.sp_nodes); + return; + } + + be_ssa_construction_init(&senv, birg); + be_ssa_construction_add_copies(&senv, walker_env.sp_nodes, + ARR_LEN(walker_env.sp_nodes)); + be_ssa_construction_fix_users_array(&senv, walker_env.sp_nodes, + ARR_LEN(walker_env.sp_nodes)); + + if(lv != NULL) { + len = ARR_LEN(walker_env.sp_nodes); + for(i = 0; i < len; ++i) { + be_liveness_update(lv, walker_env.sp_nodes[i]); + } + be_ssa_construction_update_liveness_phis(&senv, lv); + } + + phis = be_ssa_construction_get_new_phis(&senv); /* set register requirements for stack phis */ - for(i = 0; i < ARR_LEN(phis); ++i) { + len = ARR_LEN(phis); + for(i = 0; i < len; ++i) { ir_node *phi = phis[i]; be_set_phi_reg_req(walker_env.arch_env, phi, &env->sp_req); be_set_phi_flags(walker_env.arch_env, phi, arch_irn_flags_ignore | arch_irn_flags_modify_sp); arch_set_irn_register(walker_env.arch_env, phi, env->isa->sp); } + be_ssa_construction_destroy(&senv); - DEL_ARR_F(phis); - DEL_ARR_F(walker_env.nodes); + DEL_ARR_F(walker_env.sp_nodes); } static int process_stack_bias(be_abi_irg_t *env, ir_node *bl, int bias) @@ -2223,107 +2241,6 @@ ir_node *be_abi_get_start_barrier(be_abi_irg_t *abi) return abi->start_barrier; } -#if 0 -/* - _____ _____ _ _ _ _ _ _ - |_ _| __ \| \ | | | | | | | | | - | | | |__) | \| | | |__| | __ _ _ __ __| | | ___ _ __ - | | | _ /| . ` | | __ |/ _` | '_ \ / _` | |/ _ \ '__| - _| |_| | \ \| |\ | | | | | (_| | | | | (_| | | __/ | - |_____|_| \_\_| \_| |_| |_|\__,_|_| |_|\__,_|_|\___|_| - - for Phi nodes which are created due to stack modifying nodes - such as IncSP, AddSP and SetSP. - - These Phis are always to be ignored by the reg alloc and are - fixed on the SP register of the ISA. -*/ - -static const void *abi_get_irn_ops(const arch_irn_handler_t *handler, const ir_node *irn) -{ - const be_abi_irg_t *abi = get_abi_from_handler(handler); - const void *res = NULL; - - if(is_Phi(irn) && pset_find_ptr(abi->stack_phis, (void *) irn)) - res = &abi->irn_ops; - - return res; -} - -static -const arch_register_req_t *abi_get_irn_reg_req(const void *self, - const ir_node *irn, int pos) -{ - be_abi_irg_t *abi = get_abi_from_ops(self); - - if(pos == BE_OUT_POS(0)) { - return &abi->sp_req; - } else if(pos >= 0 && pos < get_irn_arity(irn)) { - return &abi->sp_cls_req; - } - - return arch_no_register_req; -} - -static void abi_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) -{ -} - -static const arch_register_t *abi_get_irn_reg(const void *self, const ir_node *irn) -{ - const be_abi_irg_t *abi = get_abi_from_ops(self); - return abi->isa->sp; -} - -static arch_irn_class_t abi_classify(const void *_self, const ir_node *irn) -{ - return arch_irn_class_normal; -} - -static arch_irn_flags_t abi_get_flags(const void *_self, const ir_node *irn) -{ - return arch_irn_flags_ignore | arch_irn_flags_modify_sp; -} - -static ir_entity *abi_get_frame_entity(const void *_self, const ir_node *irn) -{ - return NULL; -} - -static void abi_set_frame_entity(const void *_self, ir_node *irn, ir_entity *ent) -{ -} - -static void abi_set_frame_offset(const void *_self, ir_node *irn, int bias) -{ -} - -static int abi_get_sp_bias(const void *self, const ir_node *irn) -{ - return 0; -} - -static const arch_irn_ops_if_t abi_irn_ops = { - abi_get_irn_reg_req, - abi_set_irn_reg, - abi_get_irn_reg, - abi_classify, - abi_get_flags, - abi_get_frame_entity, - abi_set_frame_entity, - abi_set_frame_offset, - abi_get_sp_bias, - NULL, /* get_inverse */ - NULL, /* get_op_estimated_cost */ - NULL, /* possible_memory_operand */ - NULL, /* perform_memory_operand */ -}; - -static const arch_irn_handler_t abi_irn_handler = { - abi_get_irn_ops -}; -#endif - /** * Returns non-zero if the ABI has omitted the frame pointer in * the current graph.