Use simple assignment instead of memcpy() when possible.
[libfirm] / ir / be / beabi.c
index b35e96e..050b11d 100644 (file)
@@ -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);
+}
+
 /*
      _    ____ ___    ____      _ _ _                _
     / \  | __ )_ _|  / ___|__ _| | | |__   __ _  ___| | _____
@@ -462,7 +470,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 {
@@ -576,10 +585,6 @@ 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;
        }
@@ -1272,9 +1277,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
@@ -1319,7 +1321,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) {
@@ -1555,7 +1556,7 @@ 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));
 }
 
 /**
@@ -1744,10 +1745,10 @@ static void modify_irg(ir_graph *irg)
                }
        }
 
-       bet_type = call->cb->get_between_type(env->cb);
+       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);
-       stack_layout->sp_relative = call->flags.bits.try_omit_fp;
 
        /* Count the register params and add them to the number of Projs for the RegParams node */
        for (i = 0; i < n_params; ++i) {
@@ -1773,6 +1774,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);
 
@@ -1780,17 +1784,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) {
@@ -1801,7 +1803,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);
@@ -1819,20 +1824,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);
@@ -1866,8 +1862,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) {
@@ -1896,7 +1893,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);
@@ -2101,14 +2098,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);
@@ -2118,10 +2115,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);
@@ -2144,9 +2141,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);
        }
@@ -2154,12 +2153,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);
 
@@ -2178,9 +2171,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)
@@ -2189,35 +2181,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)
 {
@@ -2258,23 +2227,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");