make code a bit more readble
[libfirm] / ir / be / beabi.c
index fd8cc69..8c75e0d 100644 (file)
@@ -209,14 +209,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(const arch_register_class_t *cls_addr)
 {
        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->cls_addr   = NULL;
+       call->cls_addr   = cls_addr;
 
        call->flags.bits.try_omit_fp = be_omit_fp;
 
@@ -387,7 +387,6 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp, i
 {
        ir_graph *irg             = env->birg->irg;
        const arch_isa_t *isa     = env->birg->main_env->arch_env->isa;
-       be_abi_call_t *call       = be_abi_call_new();
        ir_type *mt               = get_Call_type(irn);
        ir_node *call_ptr         = get_Call_ptr(irn);
        int n_params              = get_method_n_params(mt);
@@ -398,6 +397,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp, i
        int stack_size            = 0;
        int stack_dir             = arch_isa_stack_dir(isa);
        const arch_register_t *sp = arch_isa_sp(isa);
+       be_abi_call_t *call       = be_abi_call_new(sp->reg_class);
        ir_mode *mach_mode        = sp->reg_class->mode;
        struct obstack *obst      = &env->obst;
        int no_alloc              = call->flags.bits.frame_is_setup_on_call;
@@ -636,10 +636,10 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp, i
                                       get_Call_type(irn));
 
        /*
-               Set the register class of the call address to the same as the stack pointer's
-               if it's not set by the backend in the abi callback.
+               Set the register class of the call address to
+               the backend provided class (default: stack pointer class)
        */
-       be_node_set_reg_class(low_call, be_pos_Call_ptr, call->cls_addr ? call->cls_addr : sp->reg_class);
+       be_node_set_reg_class(low_call, be_pos_Call_ptr, call->cls_addr);
 
        /* Set input requirement for stack pointer. */
        be_node_set_reg_class(low_call, be_pos_Call_sp, arch_get_irn_reg_class(isa->main_env->arch_env, curr_sp, -1));
@@ -663,6 +663,11 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp, i
                /* Correct Proj number since it has been adjusted! (see above) */
                const be_abi_call_arg_t *arg = get_call_arg(call, 1, proj - pn_Call_max);
 
+               /* correct mode */
+               const arch_register_class_t *cls = arch_register_get_class(arg->reg);
+               ir_mode *mode = arch_register_class_mode(cls);
+               set_irn_mode(irn, mode);
+
                assert(arg->in_reg);
                be_set_constr_single_reg(low_call, BE_OUT_POS(proj), arg->reg);
        }
@@ -924,7 +929,7 @@ static int cmp_call_dependecy(const void *c1, const void *c2)
  */
 static void link_calls_in_block_walker(ir_node *irn, void *data)
 {
-       opcode code = get_irn_opcode(irn);
+       ir_opcode code = get_irn_opcode(irn);
 
        if (code == iro_Call ||
                (code == iro_Alloc && get_Alloc_where(irn) == stack_alloc) ||
@@ -1547,6 +1552,37 @@ static void fix_address_of_parameter_access(be_abi_irg_t *env, ir_entity *value_
        }
 }
 
+/**
+ * The start block has no jump, instead it has an initial exec Proj.
+ * The backend wants to handle all blocks the same way, so we replace
+ * the out cfg edge with a real jump.
+ */
+static void fix_start_block(ir_node *block, void *env) {
+       int      *done = env;
+       int      i;
+       ir_node  *start_block;
+       ir_graph *irg;
+
+       /* we processed the start block, return */
+       if (*done)
+               return;
+
+       irg         = get_irn_irg(block);
+       start_block = get_irg_start_block(irg);
+
+       for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
+               ir_node *pred       = get_Block_cfgpred(block, i);
+               ir_node *pred_block = get_nodes_block(pred);
+
+               /* ok, we are in the block, having start as cfg predecessor */
+               if (pred_block == start_block) {
+                       ir_node *jump = new_r_Jmp(irg, pred_block);
+                       set_Block_cfgpred(block, i, jump);
+                       *done = 1;
+               }
+       }
+}
+
 /**
  * Modify the irg itself and the frame type.
  */
@@ -1563,7 +1599,7 @@ static void modify_irg(be_abi_irg_t *env)
        pset *dont_save           = pset_new_ptr(8);
 
        int n_params;
-       int i, j, n;
+       int i, j, n, temp;
 
        reg_node_map_t *rm;
        const arch_register_t *fp_reg;
@@ -1572,6 +1608,7 @@ static void modify_irg(be_abi_irg_t *env)
        ir_node *reg_params_bl;
        ir_node **args;
        ir_node *arg_tuple;
+       ir_node *value_param_base;
        const ir_edge_t *edge;
        ir_type *arg_type, *bet_type;
        lower_frame_sels_env_t ctx;
@@ -1587,6 +1624,11 @@ static void modify_irg(be_abi_irg_t *env)
        ctx.value_param_list = NULL;
        irg_walk_graph(irg, lower_frame_sels_walker, NULL, &ctx);
 
+       /* value_param_base anchor is not needed anymore now */
+       value_param_base = get_irg_value_param_base(irg);
+       set_Proj_pred(value_param_base, new_r_Bad(irg));
+       set_irg_value_param_base(irg, new_r_Bad(irg));
+
        env->frame = obstack_alloc(&env->obst, sizeof(env->frame[0]));
        env->regs  = pmap_create();
 
@@ -1661,8 +1703,7 @@ static void modify_irg(be_abi_irg_t *env)
        rm = reg_map_to_arr(&env->obst, env->regs);
        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_mode *mode        = arg_proj ? get_irn_mode(arg_proj) : reg->reg_class->mode;
+               ir_mode *mode        = reg->reg_class->mode;
                long nr              = i;
                int pos              = BE_OUT_POS((int) nr);
                int flags            = 0;
@@ -1745,10 +1786,15 @@ static void modify_irg(be_abi_irg_t *env)
                        }
 
                        assert(repl != NULL);
-                       edges_reroute(args[i], repl, irg);
+                       exchange(args[i], repl);
                }
        }
 
+       /* the arg proj is not needed anymore now */
+       assert(get_irn_n_edges(arg_tuple) == 0);
+       set_irn_n(arg_tuple, 0, new_rd_Bad(irg));
+       set_irg_args(irg, new_rd_Bad(irg));
+
        /* All Return nodes hang on the End node, so look for them there. */
        for (i = 0, n = get_Block_n_cfgpreds(end); i < n; ++i) {
                ir_node *irn = get_Block_cfgpred(end, i);
@@ -1763,6 +1809,10 @@ static void modify_irg(be_abi_irg_t *env)
 
        del_pset(dont_save);
        obstack_free(&env->obst, args);
+
+       /* handle start block here (place a jump in the block) */
+       temp = 0;
+       irg_block_walk_graph(irg, fix_start_block, NULL, &temp);
 }
 
 be_abi_irg_t *be_abi_introduce(be_irg_t *birg)
@@ -1781,7 +1831,7 @@ be_abi_irg_t *be_abi_introduce(be_irg_t *birg)
 
        env->isa           = birg->main_env->arch_env->isa;
        env->method_type   = get_entity_type(get_irg_entity(irg));
-       env->call          = be_abi_call_new();
+       env->call          = be_abi_call_new(env->isa->sp->reg_class);
        arch_isa_get_call_abi(env->isa, env->method_type, env->call);
 
        env->ignore_regs      = pset_new_ptr_default();
@@ -1816,8 +1866,8 @@ be_abi_irg_t *be_abi_introduce(be_irg_t *birg)
        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);
+       exchange(dummy, env->init_sp);
+       exchange(old_frame, get_irg_frame(irg));
 
        /* Make some important node pointers survive the dead node elimination. */
        survive_dce_register_irn(env->dce_survivor, &env->init_sp);
@@ -1891,15 +1941,20 @@ void be_abi_fix_stack_nodes(be_abi_irg_t *env, be_lv_t *lv)
 {
        pset *stack_nodes = pset_new_ptr(16);
        struct fix_stack_walker_info info;
+       int collect_phis;
 
        info.nodes = stack_nodes;
        info.aenv  = env->birg->main_env->arch_env;
 
        be_assure_dom_front(env->birg);
 
+
        irg_walk_graph(env->birg->irg, collect_stack_nodes_walker, NULL, &info);
        pset_insert_ptr(stack_nodes, env->init_sp);
-       be_ssa_constr_set_phis(env->birg->dom_front, lv, stack_nodes, env->stack_phis);
+       collect_phis = 1;
+       if (env->call->cb->collect_stack_phis)
+               collect_phis = env->call->cb->collect_stack_phis(env->cb);
+       be_ssa_constr_set_phis(env->birg->dom_front, lv, stack_nodes, collect_phis ? env->stack_phis : NULL);
        del_pset(stack_nodes);
 }