beinfo: Remove declaration of the non-existent function be_info_duplicate().
[libfirm] / ir / be / bestack.c
index 320c5c8..5695517 100644 (file)
@@ -20,7 +20,6 @@
 /**
  * @file
  * @author      Sebastian Hack, Matthias Braun
- * @version     $Id$
  *
  * Handling of the stack frame. It is composed of three types:
  * 1) The type of the arguments which are pushed on the stack.
@@ -86,12 +85,11 @@ static ir_entity *search_ent_with_offset(ir_type *t, int offset)
 
 static int stack_frame_compute_initial_offset(be_stack_layout_t *frame)
 {
-       ir_type  *base = frame->stack_dir < 0 ? frame->between_type : frame->frame_type;
+       ir_type  *base = frame->between_type;
        ir_entity *ent = search_ent_with_offset(base, 0);
 
        if (ent == NULL) {
-               frame->initial_offset
-                       = frame->stack_dir < 0 ? get_type_size_bytes(frame->frame_type) : get_type_size_bytes(frame->between_type);
+               frame->initial_offset = get_type_size_bytes(frame->frame_type);
        } else {
                frame->initial_offset = be_get_stack_entity_offset(frame, ent, 0);
        }
@@ -142,9 +140,8 @@ static void lower_outer_frame_sels(ir_node *sel, void *ctx)
  * A helper struct for the bias walker.
  */
 typedef struct bias_walk {
-       int           start_block_bias;  /**< The bias at the end of the start block. */
-       int           between_size;
-       ir_node      *start_block;  /**< The start block of the current graph. */
+       int      start_block_bias; /**< The bias at the end of the start block. */
+       ir_node *start_block;      /**< The start block of the current graph. */
 } bias_walk;
 
 /**
@@ -162,7 +159,6 @@ static int process_stack_bias(ir_node *bl, int real_bias)
        be_stack_layout_t *layout      = be_get_irg_stack_layout(irg);
        bool               sp_relative = layout->sp_relative;
        const arch_env_t  *arch_env    = be_get_irg_arch_env(irg);
-       ir_node           *irn;
 
        sched_foreach(bl, irn) {
                int ofs;
@@ -183,44 +179,40 @@ static int process_stack_bias(ir_node *bl, int real_bias)
                 * If the node modifies the stack pointer by a constant offset,
                 * record that in the bias.
                 */
-               ofs = arch_get_sp_bias(irn);
-
                if (be_is_IncSP(irn)) {
+                       ofs = be_get_IncSP_offset(irn);
                        /* fill in real stack frame size */
-                       if (ofs == BE_STACK_FRAME_SIZE_EXPAND) {
-                               ir_type *frame_type = get_irg_frame_type(irg);
-                               ofs = (int) get_type_size_bytes(frame_type);
-                               be_set_IncSP_offset(irn, ofs);
-                       } else if (ofs == BE_STACK_FRAME_SIZE_SHRINK) {
-                               ir_type *frame_type = get_irg_frame_type(irg);
-                               ofs = - (int)get_type_size_bytes(frame_type);
-                               be_set_IncSP_offset(irn, ofs);
+                       if (be_get_IncSP_align(irn)) {
+                               /* patch IncSP to produce an aligned stack pointer */
+                               int const between_size = get_type_size_bytes(layout->between_type);
+                               int const alignment    = 1 << arch_env->stack_alignment;
+                               int const delta        = (real_bias + ofs + between_size) & (alignment - 1);
+                               assert(ofs >= 0);
+                               if (delta > 0) {
+                                       be_set_IncSP_offset(irn, ofs + alignment - delta);
+                                       real_bias += alignment - delta;
+                               }
                        } else {
-                               if (be_get_IncSP_align(irn)) {
-                                       /* patch IncSP to produce an aligned stack pointer */
-                                       ir_type *between_type = layout->between_type;
-                                       int      between_size = get_type_size_bytes(between_type);
-                                       int      alignment    = 1 << arch_env->stack_alignment;
-                                       int      delta        = (real_bias + ofs + between_size) & (alignment - 1);
-                                       assert(ofs >= 0);
-                                       if (delta > 0) {
-                                               be_set_IncSP_offset(irn, ofs + alignment - delta);
-                                               real_bias += alignment - delta;
-                                       }
-                               } else {
-                                       /* adjust so real_bias corresponds with wanted_bias */
-                                       int delta = wanted_bias - real_bias;
-                                       assert(delta <= 0);
-                                       if (delta != 0) {
-                                               be_set_IncSP_offset(irn, ofs + delta);
-                                               real_bias += delta;
-                                       }
+                               /* adjust so real_bias corresponds with wanted_bias */
+                               int delta = wanted_bias - real_bias;
+                               assert(delta <= 0);
+                               if (delta != 0) {
+                                       be_set_IncSP_offset(irn, ofs + delta);
+                                       real_bias += delta;
                                }
                        }
+                       real_bias   += ofs;
+                       wanted_bias += ofs;
+               } else {
+                       ofs = arch_get_sp_bias(irn);
+                       if (ofs == SP_BIAS_RESET) {
+                               real_bias   = 0;
+                               wanted_bias = 0;
+                       } else {
+                               real_bias   += ofs;
+                               wanted_bias += ofs;
+                       }
                }
-
-               real_bias   += ofs;
-               wanted_bias += ofs;
        }
 
        assert(real_bias == wanted_bias);
@@ -251,7 +243,6 @@ void be_abi_fix_stack_bias(ir_graph *irg)
        /* Determine the stack bias at the end of the start block. */
        bw.start_block_bias = process_stack_bias(get_irg_start_block(irg),
                                                 stack_layout->initial_bias);
-       bw.between_size     = get_type_size_bytes(stack_layout->between_type);
 
        /* fix the bias is all other blocks */
        bw.start_block = get_irg_start_block(irg);
@@ -287,12 +278,12 @@ static void collect_stack_nodes_walker(ir_node *node, void *data)
                insn = get_Proj_pred(node);
        }
 
-       if (arch_irn_get_n_outs(insn) == 0)
+       if (arch_get_irn_n_outs(insn) == 0)
                return;
        if (get_irn_mode(node) == mode_T)
                return;
 
-       req = arch_get_register_req_out(node);
+       req = arch_get_irn_register_req(node);
        if (! (req->type & arch_register_req_type_produces_sp))
                return;
 
@@ -319,11 +310,11 @@ void be_abi_fix_stack_nodes(ir_graph *irg)
                new_sp_req        = OALLOCZ(obst, arch_register_req_t);
                new_sp_req->type  = arch_register_req_type_limited
                                  | arch_register_req_type_produces_sp;
-               new_sp_req->cls   = arch_register_get_class(arch_env->sp);
+               new_sp_req->cls   = arch_env->sp->reg_class;
                new_sp_req->width = 1;
 
                limited_bitset = rbitset_obstack_alloc(obst, new_sp_req->cls->n_regs);
-               rbitset_set(limited_bitset, arch_register_get_index(sp));
+               rbitset_set(limited_bitset, sp->index);
                new_sp_req->limited = limited_bitset;
 
                if (!rbitset_is_set(birg->allocatable_regs, sp->global_index)) {
@@ -372,6 +363,28 @@ void be_abi_fix_stack_nodes(ir_graph *irg)
                arch_set_irn_register(phi, arch_env->sp);
        }
        be_ssa_construction_destroy(&senv);
-
        DEL_ARR_F(walker_env.sp_nodes);
+
+       /* when doing code with frame-pointers then often the last incsp-nodes are
+        * not used anymore because we copy the framepointer to the stack pointer
+        * when leaving the function. Though the last incsp is often kept (because
+        * you often don't know which incsp is the last one and fixstack should find
+        * them all). Remove unnecessary keeps and IncSP nodes */
+       {
+               ir_node  *end    = get_irg_end(irg);
+               int       arity  = get_irn_arity(end);
+               int       i;
+               for (i = arity-1; i >= 0; --i) {
+                       ir_node *in = get_irn_n(end, i);
+                       if (!be_is_IncSP(in)) {
+                               continue;
+                       }
+
+                       remove_End_keepalive(end, in);
+                       if (get_irn_n_edges(in) == 0) {
+                               sched_remove(in);
+                               kill_node(in);
+                       }
+               }
+       }
 }