X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbeabi.c;h=5ec10b4f709d4a82c2aa63b325b8d87d065a0894;hb=c3bca446c415740a35b343ae9d23f0f431561cb8;hp=294e2f23884be46ce572038680a22b924bad8502;hpb=b4559ec03fdb815542c75600384afb295600baa9;p=libfirm diff --git a/ir/be/beabi.c b/ir/be/beabi.c index 294e2f238..5ec10b4f7 100644 --- a/ir/be/beabi.c +++ b/ir/be/beabi.c @@ -95,11 +95,8 @@ struct be_abi_irg_t { ir_node *start; /**< The be_Start params node. */ pmap *regs; /**< A map of all callee-save and ignore regs to their Projs to the RegParams node. */ - int start_block_bias; /**< The stack bias at the end of the start block. */ - void *cb; /**< ABI Callback self pointer. */ - pmap *keep_map; /**< mapping blocks to keep nodes. */ ir_node **calls; /**< flexible array containing all be_Call nodes */ @@ -110,6 +107,17 @@ static ir_heights_t *ir_heights; /** Flag: if set, try to omit the frame pointer in all routines. */ static int be_omit_fp = 1; +static ir_node *be_abi_reg_map_get(pmap *map, const arch_register_t *reg) +{ + return (ir_node*)pmap_get(map, reg); +} + +static void be_abi_reg_map_set(pmap *map, const arch_register_t* reg, + ir_node *node) +{ + pmap_insert(map, reg, node); +} + /* _ ____ ___ ____ _ _ _ _ / \ | __ )_ _| / ___|__ _| | | |__ __ _ ___| | _____ @@ -280,13 +288,12 @@ static void be_abi_call_free(be_abi_call_t *call) * @param args the stack argument layout type * @param between the between layout type * @param locals the method frame type - * @param stack_dir the stack direction: < 0 decreasing, > 0 increasing addresses * @param param_map an array mapping method argument positions to the stack argument type * * @return the initialized stack layout */ static be_stack_layout_t *stack_frame_init(be_stack_layout_t *frame, ir_type *args, - ir_type *between, ir_type *locals, int stack_dir, + ir_type *between, ir_type *locals, ir_entity *param_map[]) { frame->arg_type = args; @@ -294,19 +301,13 @@ static be_stack_layout_t *stack_frame_init(be_stack_layout_t *frame, ir_type *ar frame->frame_type = locals; frame->initial_offset = 0; frame->initial_bias = 0; - frame->stack_dir = stack_dir; frame->order[1] = between; frame->param_map = param_map; - if (stack_dir > 0) { - frame->order[0] = args; - frame->order[2] = locals; - } else { - /* typical decreasing stack: locals have the - * lowest addresses, arguments the highest */ - frame->order[0] = locals; - frame->order[2] = args; - } + /* typical decreasing stack: locals have the + * lowest addresses, arguments the highest */ + frame->order[0] = locals; + frame->order[2] = args; return frame; } @@ -339,7 +340,6 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) ir_node *curr_mem = get_Call_mem(irn); ir_node *bl = get_nodes_block(irn); int stack_size = 0; - int stack_dir = arch_env->stack_dir; const arch_register_t *sp = arch_env->sp; be_abi_call_t *call = be_abi_call_new(sp->reg_class); ir_mode *mach_mode = sp->reg_class->mode; @@ -362,6 +362,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) int *reg_param_idxs; int *stack_param_idx; int i, n, destroy_all_regs; + int throws_exception; size_t s; size_t p; dbg_info *dbgi; @@ -404,7 +405,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) * Note: we also have to do this for stack_size == 0, because we may have * to adjust stack alignment for the call. */ - if (stack_dir < 0 && !do_seq && !no_alloc) { + if (!do_seq && !no_alloc) { curr_sp = be_new_IncSP(sp, bl, curr_sp, stack_size, 1); } @@ -420,7 +421,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) * We must them reverse again if they are pushed (not stored) and the stack * direction is downwards. */ - if (call->flags.bits.left_to_right ^ (do_seq && stack_dir < 0)) { + if (call->flags.bits.left_to_right ^ do_seq) { for (i = 0; i < n_stack_params >> 1; ++i) { int other = n_stack_params - i - 1; int tmp = stack_param_idx[i]; @@ -470,7 +471,8 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) /* Insert a store for primitive arguments. */ if (is_atomic_type(param_type)) { - ir_node *mem_input = do_seq ? curr_mem : new_r_NoMem(irg); + ir_node *nomem = get_irg_no_mem(irg); + ir_node *mem_input = do_seq ? curr_mem : nomem; ir_node *store = new_rd_Store(dbgi, bl, mem_input, addr, param, cons_none); mem = new_r_Proj(store, mode_M, pn_Store_M); } else { @@ -584,16 +586,13 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) for (s = 0; s < ARR_LEN(states); ++s) { const arch_register_t *reg = states[s]; const arch_register_class_t *cls = arch_register_get_class(reg); -#if 0 - ir_node *regnode = be_abi_reg_map_get(env->regs, reg); - ir_fprintf(stderr, "Adding %+F\n", regnode); -#endif ir_node *regnode = new_r_Unknown(irg, arch_register_class_mode(cls)); in[n_ins++] = regnode; } assert(n_ins == (int) (n_reg_params + ARR_LEN(states))); /* ins collected, build the call */ + throws_exception = ir_throws_exception(irn); 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, @@ -606,6 +605,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) n_reg_results + pn_be_Call_first_res + ARR_LEN(destroyed_regs), n_ins, in, get_Call_type(irn)); } + ir_set_throws_exception(low_call, throws_exception); be_Call_set_pop(low_call, call->pop); /* put the call into the list of all calls for later processing */ @@ -619,9 +619,9 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) /* now handle results */ for (i = 0; i < n_res; ++i) { - int pn; ir_node *proj = res_projs[i]; be_abi_call_arg_t *arg = get_call_arg(call, 1, i, 0); + long pn = i + pn_be_Call_first_res; /* returns values on stack not supported yet */ assert(arg->in_reg); @@ -756,7 +756,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) } if (! mem_proj) { - mem_proj = new_r_Proj(low_call, mode_M, pn_be_Call_M_regular); + mem_proj = new_r_Proj(low_call, mode_M, pn_be_Call_M); keep_alive(mem_proj); } } @@ -1146,9 +1146,8 @@ static ir_type *compute_arg_type(be_abi_irg_t *env, ir_graph *irg, ir_type *method_type, ir_type *val_param_tp, ir_entity ***param_map) { - const arch_env_t *arch_env = be_get_irg_arch_env(irg); int dir = env->call->flags.bits.left_to_right ? 1 : -1; - int inc = arch_env->stack_dir * dir; + int inc = -dir; int n = get_method_n_params(method_type); int curr = inc > 0 ? 0 : n - 1; struct obstack *obst = be_get_be_obst(irg); @@ -1281,9 +1280,6 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl, be_abi_reg_map_set(reg_map, arch_env->sp, stack); - /* Make the Epilogue node and call the arch's epilogue maker. */ - 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 @@ -1328,7 +1324,6 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl, /* we have to pop the shadow parameter in in case of struct returns */ pop = call->pop; ret = be_new_Return(dbgi, irg, bl, n_res, pop, n, in); - arch_irn_add_flags(ret, arch_irn_flags_epilog); /* Set the register classes of the return's parameter accordingly. */ for (i = 0; i < n; ++i) { @@ -1518,6 +1513,7 @@ static void fix_address_of_parameter_access(be_abi_irg_t *env, ir_graph *irg, /* the new memory Proj gets the last Proj from store */ set_Proj_pred(nmem, store); set_Proj_proj(nmem, pn_Store_M); + set_nodes_block(nmem, get_nodes_block(store)); /* move all entities to the frame type */ frame_tp = get_irg_frame_type(irg); @@ -1564,7 +1560,22 @@ static void fix_start_block(ir_graph *irg) assert(is_Proj(initial_X)); exchange(initial_X, jmp); - set_irg_initial_exec(irg, new_r_Bad(irg)); + set_irg_initial_exec(irg, new_r_Bad(irg, mode_X)); + + /* merge start block with successor if possible */ + { + const ir_edge_t *edge; + foreach_out_edge(jmp, edge) { + ir_node *succ = get_edge_src_irn(edge); + if (!is_Block(succ)) + continue; + + if (get_irn_arity(succ) == 1) { + exchange(succ, start_block); + } + break; + } + } } /** @@ -1753,10 +1764,10 @@ static void modify_irg(ir_graph *irg) } } - bet_type = call->cb->get_between_type(env->cb); - stack_frame_init(stack_layout, arg_type, bet_type, - get_irg_frame_type(irg), arch_env->stack_dir, param_map); stack_layout->sp_relative = call->flags.bits.try_omit_fp; + bet_type = call->cb->get_between_type(irg); + stack_frame_init(stack_layout, arg_type, bet_type, + get_irg_frame_type(irg), param_map); /* Count the register params and add them to the number of Projs for the RegParams node */ for (i = 0; i < n_params; ++i) { @@ -1782,6 +1793,9 @@ static void modify_irg(ir_graph *irg) } } + fp_reg = call->flags.bits.try_omit_fp ? arch_env->sp : arch_env->bp; + rbitset_clear(birg->allocatable_regs, fp_reg->global_index); + /* handle start block here (place a jump in the block) */ fix_start_block(irg); @@ -1789,17 +1803,15 @@ static void modify_irg(ir_graph *irg) pmap_insert(env->regs, (void *) arch_env->bp, NULL); start_bl = get_irg_start_block(irg); env->start = be_new_Start(NULL, start_bl, pmap_count(env->regs) + 1); - arch_irn_add_flags(env->start, arch_irn_flags_prolog); set_irg_start(irg, env->start); /* * make proj nodes for the callee save registers. * memorize them, since Return nodes get those as inputs. * - * Note, that if a register corresponds to an argument, the regs map contains - * the old Proj from start for that argument. + * Note, that if a register corresponds to an argument, the regs map + * contains the old Proj from start for that argument. */ - rm = ALLOCAN(reg_node_map_t, pmap_count(env->regs)); reg_map_to_arr(rm, env->regs); for (i = 0, n = pmap_count(env->regs); i < n; ++i) { @@ -1810,7 +1822,10 @@ static void modify_irg(ir_graph *irg) ir_node *proj; if (reg == sp) - add_type |= arch_register_req_type_produces_sp | arch_register_req_type_ignore; + add_type |= arch_register_req_type_produces_sp; + if (!rbitset_is_set(birg->allocatable_regs, reg->global_index)) { + add_type |= arch_register_req_type_ignore; + } assert(nr >= 0); proj = new_r_Proj(env->start, mode, nr + 1); @@ -1828,20 +1843,11 @@ static void modify_irg(ir_graph *irg) mem = new_mem_proj; set_irg_initial_mem(irg, mem); - /* Generate the Prologue */ - fp_reg = call->cb->prologue(env->cb, &mem, env->regs, &stack_layout->initial_bias); - - env->init_sp = be_abi_reg_map_get(env->regs, sp); - env->init_sp = be_new_IncSP(sp, start_bl, env->init_sp, BE_STACK_FRAME_SIZE_EXPAND, 0); - arch_irn_add_flags(env->init_sp, arch_irn_flags_prolog); - be_abi_reg_map_set(env->regs, sp, env->init_sp); - env->init_sp = be_abi_reg_map_get(env->regs, sp); - arch_set_irn_register(env->init_sp, sp); + /* set new frame_pointer */ frame_pointer = be_abi_reg_map_get(env->regs, fp_reg); set_irg_frame(irg, frame_pointer); - rbitset_clear(birg->allocatable_regs, fp_reg->global_index); /* rewire old mem users to new mem */ exchange(old_mem, mem); @@ -1875,8 +1881,9 @@ static void modify_irg(ir_graph *irg) if (is_atomic_type(param_type) && get_irn_n_edges(args[i]) > 0) { ir_mode *mode = get_type_mode(param_type); ir_mode *load_mode = arg->load_mode; + ir_node *nomem = get_irg_no_mem(irg); - ir_node *load = new_r_Load(start_bl, new_r_NoMem(irg), addr, load_mode, cons_floats); + ir_node *load = new_r_Load(start_bl, nomem, addr, load_mode, cons_floats); repl = new_r_Proj(load, load_mode, pn_Load_res); if (mode != load_mode) { @@ -1905,7 +1912,7 @@ static void modify_irg(ir_graph *irg) /* the arg proj is not needed anymore now and should be only used by the anchor */ assert(get_irn_n_edges(arg_tuple) == 1); kill_node(arg_tuple); - set_irg_args(irg, new_r_Bad(irg)); + set_irg_args(irg, new_r_Bad(irg, mode_T)); /* All Return nodes hang on the End node, so look for them there. */ end = get_irg_end_block(irg); @@ -2110,14 +2117,14 @@ static void fix_pic_symconsts(ir_node *node, void *data) /* we need an extra indirection for global data outside our current module. The loads are always safe and can therefore float and need no memory input */ - load = new_r_Load(block, new_r_NoMem(irg), add, mode, cons_floats); + load = new_r_Load(block, get_irg_no_mem(irg), add, mode, cons_floats); load_res = new_r_Proj(load, mode, pn_Load_res); set_irn_n(node, i, load_res); } } -be_abi_irg_t *be_abi_introduce(ir_graph *irg) +void be_abi_introduce(ir_graph *irg) { be_abi_irg_t *env = XMALLOCZ(be_abi_irg_t); ir_node *old_frame = get_irg_frame(irg); @@ -2127,10 +2134,10 @@ be_abi_irg_t *be_abi_introduce(ir_graph *irg) ir_type *method_type = get_entity_type(entity); be_irg_t *birg = be_birg_from_irg(irg); struct obstack *obst = &birg->obst; + ir_node *dummy = new_r_Dummy(irg, + arch_env->sp->reg_class->mode); unsigned r; - ir_node *dummy; - /* determine allocatable registers */ assert(birg->allocatable_regs == NULL); birg->allocatable_regs = rbitset_obstack_alloc(obst, arch_env->n_registers); @@ -2153,9 +2160,11 @@ be_abi_irg_t *be_abi_introduce(ir_graph *irg) env->call = be_abi_call_new(arch_env->sp->reg_class); arch_env_get_call_abi(arch_env, method_type, env->call); - env->init_sp = dummy = new_r_Dummy(irg, arch_env->sp->reg_class->mode); + env->init_sp = dummy; env->calls = NEW_ARR_F(ir_node*, 0); + edges_assure(irg); + if (options->pic) { irg_walk_graph(irg, fix_pic_symconsts, NULL, env); } @@ -2163,12 +2172,6 @@ be_abi_irg_t *be_abi_introduce(ir_graph *irg) /* Lower all call nodes in the IRG. */ process_calls(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, irg); - /* Process the IRG */ modify_irg(irg); @@ -2187,9 +2190,8 @@ be_abi_irg_t *be_abi_introduce(ir_graph *irg) exchange(dummy, env->init_sp); exchange(old_frame, get_irg_frame(irg)); - env->call->cb->done(env->cb); - env->cb = NULL; - return env; + pmap_destroy(env->regs); + env->regs = NULL; } void be_abi_free(ir_graph *irg) @@ -2198,35 +2200,12 @@ void be_abi_free(ir_graph *irg) if (env->call != NULL) be_abi_call_free(env->call); - if (env->regs != NULL) - pmap_destroy(env->regs); + assert(env->regs == NULL); free(env); be_set_irg_abi(irg, NULL); } -/** - * called after nodes have been transformed so some node references can be - * replaced with new nodes - */ -void be_abi_transform_fixup(ir_graph *irg) -{ - be_abi_irg_t *abi = be_get_irg_abi(irg); - pmap *new_regs; - pmap_entry *entry; - if (abi == NULL || abi->regs == NULL) - return; - - new_regs = pmap_create(); - foreach_pmap(abi->regs, entry) { - ir_node *value = (ir_node*)entry->value; - ir_node *transformed = be_transform_node(value); - pmap_insert(new_regs, entry->key, transformed); - } - pmap_destroy(abi->regs); - abi->regs = new_regs; -} - void be_put_allocatable_regs(const ir_graph *irg, const arch_register_class_t *cls, bitset_t *bs) { @@ -2267,23 +2246,7 @@ void be_set_allocatable_regs(const ir_graph *irg, } } -ir_node *be_abi_get_callee_save_irn(ir_graph *irg, const arch_register_t *reg) -{ - const be_abi_irg_t *abi = be_get_irg_abi(irg); - assert(reg->type & arch_register_type_callee_save); - assert(pmap_contains(abi->regs, (void *) reg)); - return (ir_node*)pmap_get(abi->regs, (void *) reg); -} - -ir_node *be_abi_get_ignore_irn(ir_graph *irg, const arch_register_t *reg) -{ - const be_abi_irg_t *abi = be_get_irg_abi(irg); - assert(reg->type & arch_register_type_ignore); - assert(pmap_contains(abi->regs, (void *) reg)); - return (ir_node*)pmap_get(abi->regs, (void *) reg); -} - -BE_REGISTER_MODULE_CONSTRUCTOR(be_init_abi); +BE_REGISTER_MODULE_CONSTRUCTOR(be_init_abi) void be_init_abi(void) { FIRM_DBG_REGISTER(dbg, "firm.be.abi");