/**
* @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.
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);
}
* 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;
/**
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;
* 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);
/* 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);
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;
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)) {
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);
+ }
+ }
+ }
}