X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbeabi.c;h=a41be6dcdac47274d694d30e498792a6c9366281;hb=c8e1cf6a41fa2077058cce740783ab78990ac0ab;hp=fc8fdabd5eaa29faf32ed894a562dc3f0e62d487;hpb=4b33054acaa27b6fca74713bb0e1e79e6af3d9c4;p=libfirm diff --git a/ir/be/beabi.c b/ir/be/beabi.c index fc8fdabd5..a41be6dcd 100644 --- a/ir/be/beabi.c +++ b/ir/be/beabi.c @@ -58,7 +58,7 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg;) -typedef struct _be_abi_call_arg_t { +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. */ unsigned in_reg : 1; /**< 1: this argument is transmitted in registers. */ unsigned on_stack : 1; /**< 1: this argument is transmitted on the stack. */ @@ -73,7 +73,7 @@ typedef struct _be_abi_call_arg_t { unsigned space_after; /**< allocate space after */ } be_abi_call_arg_t; -struct _be_abi_call_t { +struct be_abi_call_t { be_abi_call_flags_t flags; /**< Flags describing the ABI behavior on calls */ int pop; /**< number of bytes the stack frame is shrinked by the callee on return. */ const be_abi_callbacks_t *cb; @@ -85,7 +85,7 @@ struct _be_abi_call_t { /** * The ABI information for the current graph. */ -struct _be_abi_irg_t { +struct be_abi_irg_t { survive_dce_t *dce_survivor; be_abi_call_t *call; /**< The ABI call information. */ @@ -296,8 +296,8 @@ static void be_abi_call_free(be_abi_call_t *call) and the spills. */ -static int get_stack_entity_offset(be_stack_layout_t *frame, ir_entity *ent, - int bias) +int be_get_stack_entity_offset(be_stack_layout_t *frame, ir_entity *ent, + int bias) { ir_type *t = get_entity_owner(ent); int ofs = get_entity_offset(ent); @@ -346,7 +346,7 @@ static int stack_frame_compute_initial_offset(be_stack_layout_t *frame) frame->initial_offset = frame->stack_dir < 0 ? get_type_size_bytes(frame->frame_type) : get_type_size_bytes(frame->between_type); } else { - frame->initial_offset = get_stack_entity_offset(frame, ent, 0); + frame->initial_offset = be_get_stack_entity_offset(frame, ent, 0); } return frame->initial_offset; @@ -431,22 +431,18 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) int n_stack_params = 0; int n_ins; - pset_new_t destroyed_regs, states; - pset_new_iterator_t iter; + const arch_register_t **states = NEW_ARR_F(const arch_register_t*, 0); + const arch_register_t **destroyed_regs = NEW_ARR_F(const arch_register_t*, 0); ir_node *low_call; ir_node **in; ir_node **res_projs; int n_reg_results = 0; - const arch_register_t *reg; const ir_edge_t *edge; int *reg_param_idxs; int *stack_param_idx; int i, n, destroy_all_regs; dbg_info *dbgi; - pset_new_init(&destroyed_regs); - pset_new_init(&states); - /* Let the isa fill out the abi description for that call node. */ arch_env_get_call_abi(arch_env, call_tp, call); @@ -561,7 +557,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) assert(mode_is_reference(get_irn_mode(param))); copy = new_rd_CopyB(dbgi, bl, curr_mem, addr, param, param_type); - mem = new_r_Proj(copy, mode_M, pn_CopyB_M_regular); + mem = new_r_Proj(copy, mode_M, pn_CopyB_M); } curr_ofs += param_size; @@ -596,30 +592,34 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) destroy_all_regs = 1; } - /* Put caller save into the destroyed set and state registers in the states set */ + /* Put caller save into the destroyed set and state registers in the states + * set */ for (i = 0, n = arch_env_get_n_reg_class(arch_env); i < n; ++i) { unsigned j; const arch_register_class_t *cls = arch_env_get_reg_class(arch_env, i); for (j = 0; j < cls->n_regs; ++j) { const arch_register_t *reg = arch_register_for_index(cls, j); - if (destroy_all_regs || arch_register_type_is(reg, caller_save)) { - if (! arch_register_type_is(reg, ignore)) - pset_new_insert(&destroyed_regs, (void *) reg); - } + /* even if destroyed all is specified, neither SP nor FP are + * destroyed (else bad things will happen) */ + if (reg == arch_env->sp || reg == arch_env->bp) + continue; + if (arch_register_type_is(reg, state)) { - pset_new_insert(&destroyed_regs, (void*) reg); - pset_new_insert(&states, (void*) reg); + ARR_APP1(const arch_register_t*, destroyed_regs, reg); + ARR_APP1(const arch_register_t*, states, reg); + /* we're already in the destroyed set so no need for further + * checking */ + continue; + } + if (destroy_all_regs || arch_register_type_is(reg, caller_save)) { + if (! arch_register_type_is(reg, ignore)) { + ARR_APP1(const arch_register_t*, destroyed_regs, reg); + } } } } - if (destroy_all_regs) { - /* even if destroyed all is specified, neither SP nor FP are destroyed (else bad things will happen) */ - pset_new_remove(&destroyed_regs, arch_env->sp); - pset_new_remove(&destroyed_regs, arch_env->bp); - } - /* search the largest result proj number */ res_projs = ALLOCANZ(ir_node*, n_res); @@ -651,7 +651,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) n_reg_results = n_res; n_ins = 0; - in = ALLOCAN(ir_node*, n_reg_params + pset_new_size(&states)); + in = ALLOCAN(ir_node*, n_reg_params + ARR_LEN(states)); /* make the back end call node and set its register requirements. */ for (i = 0; i < n_reg_params; ++i) { @@ -659,7 +659,8 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) } /* add state registers ins */ - foreach_pset_new(&states, reg, iter) { + for (i = 0; i < ARR_LEN(states); ++i) { + const arch_register_t *reg = states[i]; const arch_register_class_t *cls = arch_register_get_class(reg); #if 0 ir_node *regnode = be_abi_reg_map_get(env->regs, reg); @@ -668,19 +669,19 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) ir_node *regnode = new_r_Unknown(irg, arch_register_class_mode(cls)); in[n_ins++] = regnode; } - assert(n_ins == (int) (n_reg_params + pset_new_size(&states))); + assert(n_ins == (int) (n_reg_params + ARR_LEN(states))); /* ins collected, build the call */ if (env->call->flags.bits.call_has_imm && is_SymConst(call_ptr)) { /* direct call */ low_call = be_new_Call(dbgi, irg, bl, curr_mem, curr_sp, curr_sp, - n_reg_results + pn_be_Call_first_res + pset_new_size(&destroyed_regs), + n_reg_results + pn_be_Call_first_res + ARR_LEN(destroyed_regs), n_ins, in, get_Call_type(irn)); be_Call_set_entity(low_call, get_SymConst_entity(call_ptr)); } else { /* indirect call */ low_call = be_new_Call(dbgi, irg, bl, curr_mem, curr_sp, call_ptr, - n_reg_results + pn_be_Call_first_res + pset_new_size(&destroyed_regs), + n_reg_results + pn_be_Call_first_res + ARR_LEN(destroyed_regs), n_ins, in, get_Call_type(irn)); } be_Call_set_pop(low_call, call->pop); @@ -721,7 +722,16 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) } if (arg->in_reg) { - pset_new_remove(&destroyed_regs, arg->reg); + /* remove register from destroyed regs */ + int j; + int n = ARR_LEN(destroyed_regs); + for (j = 0; j < n; ++j) { + if (destroyed_regs[j] == arg->reg) { + destroyed_regs[j] = destroyed_regs[n-1]; + ARR_SHRINKLEN(destroyed_regs,n-1); + break; + } + } } } @@ -763,22 +773,21 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) /* Make additional projs for the caller save registers and the Keep node which keeps them alive. */ { - const arch_register_t *reg; ir_node **in, *keep; int i; int n = 0; int curr_res_proj = pn_be_Call_first_res + n_reg_results; - pset_new_iterator_t iter; int n_ins; - n_ins = (int)pset_new_size(&destroyed_regs) + n_reg_results + 1; + n_ins = ARR_LEN(destroyed_regs) + n_reg_results + 1; in = ALLOCAN(ir_node *, n_ins); /* also keep the stack pointer */ set_irn_link(curr_sp, (void*) sp); in[n++] = curr_sp; - foreach_pset_new(&destroyed_regs, reg, iter) { + for (i = 0; i < ARR_LEN(destroyed_regs); ++i) { + const arch_register_t *reg = destroyed_regs[i]; ir_node *proj = new_r_Proj(low_call, reg->reg_class->mode, curr_res_proj); /* memorize the register in the link field. we need afterwards to set the register class of the keep correctly. */ @@ -833,8 +842,8 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) be_abi_call_free(call); - pset_new_destroy(&states); - pset_new_destroy(&destroyed_regs); + DEL_ARR_F(states); + DEL_ARR_F(destroyed_regs); return curr_sp; } @@ -2265,9 +2274,10 @@ be_abi_irg_t *be_abi_introduce(ir_graph *irg) sp_req = OALLOCZ(obst, arch_register_req_t); env->sp_req = sp_req; - sp_req->type = arch_register_req_type_limited - | arch_register_req_type_produces_sp; - sp_req->cls = arch_register_get_class(arch_env->sp); + sp_req->type = arch_register_req_type_limited + | arch_register_req_type_produces_sp; + sp_req->cls = arch_register_get_class(arch_env->sp); + sp_req->width = 1; limited_bitset = rbitset_obstack_alloc(obst, sp_req->cls->n_regs); rbitset_set(limited_bitset, arch_register_get_index(arch_env->sp)); @@ -2301,7 +2311,7 @@ be_abi_irg_t *be_abi_introduce(ir_graph *irg) Beware: init backend abi call object after processing calls, otherwise some information might be not yet available. */ - env->cb = env->call->cb->init(env->call, arch_env, irg); + env->cb = env->call->cb->init(env->call, irg); /* Process the IRG */ modify_irg(irg); @@ -2498,7 +2508,7 @@ static int process_stack_bias(ir_node *bl, int real_bias) ir_entity *ent = arch_get_frame_entity(irn); if (ent != NULL) { int bias = sp_relative ? real_bias : 0; - int offset = get_stack_entity_offset(layout, ent, bias); + int offset = be_get_stack_entity_offset(layout, ent, bias); arch_set_frame_offset(irn, offset); DBG((dbg, LEVEL_2, "%F has offset %d (including bias %d)\n", ent, offset, bias)); @@ -2597,7 +2607,7 @@ static void lower_outer_frame_sels(ir_node *sel, void *ctx) if (owner == layout->frame_type || owner == layout->arg_type) { /* found access to outer frame or arguments */ - int offset = get_stack_entity_offset(layout, ent, 0); + int offset = be_get_stack_entity_offset(layout, ent, 0); if (offset != 0) { ir_node *bl = get_nodes_block(sel);