- /*
- Check, if the node relates to an entity on the stack frame.
- If so, set the true offset (including the bias) for that
- node.
- */
- ir_entity *ent = arch_get_frame_entity(irn);
- if (ent != NULL) {
- int bias = omit_fp ? real_bias : 0;
- int offset = get_stack_entity_offset(layout, ent, bias);
- arch_set_frame_offset(irn, offset);
- DBG((dbg, LEVEL_2, "%F has offset %d (including bias %d)\n",
- ent, offset, 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)) {
- /* 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);
- } 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;
- }
- }
- }
- }
-
- real_bias += ofs;
- wanted_bias += ofs;
- }
-
- assert(real_bias == wanted_bias);
- return real_bias;
-}
-
-/**
- * A helper struct for the bias walker.
- */
-struct bias_walk {
- be_abi_irg_t *env; /**< The ABI irg environment. */
- 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. */
-};
-
-/**
- * Block-Walker: fix all stack offsets for all blocks
- * except the start block
- */
-static void stack_bias_walker(ir_node *bl, void *data)
-{
- struct bias_walk *bw = data;
- if (bl != bw->start_block) {
- process_stack_bias(bw->env, bl, bw->start_block_bias);
- }
-}
-
-/**
- * Walker: finally lower all Sels of outer frame or parameter
- * entities.
- */
-static void lower_outer_frame_sels(ir_node *sel, void *ctx)
-{
- ir_node *ptr;
- ir_entity *ent;
- ir_type *owner;
- be_stack_layout_t *layout;
- ir_graph *irg;
- (void) ctx;
-
- if (! is_Sel(sel))
- return;
-
- ent = get_Sel_entity(sel);
- owner = get_entity_owner(ent);
- ptr = get_Sel_ptr(sel);
- irg = get_irn_irg(sel);
- layout = be_get_irg_stack_layout(irg);
-
- if (owner == layout->frame_type || owner == layout->arg_type) {
- /* found access to outer frame or arguments */
- int offset = get_stack_entity_offset(layout, ent, 0);
-
- if (offset != 0) {
- ir_node *bl = get_nodes_block(sel);
- dbg_info *dbgi = get_irn_dbg_info(sel);
- ir_mode *mode = get_irn_mode(sel);
- ir_mode *mode_UInt = get_reference_mode_unsigned_eq(mode);
- ir_node *cnst = new_r_Const_long(current_ir_graph, mode_UInt, offset);
-
- ptr = new_rd_Add(dbgi, bl, ptr, cnst, mode);
- }
- exchange(sel, ptr);
- }
-}
-
-void be_abi_fix_stack_bias(ir_graph *irg)
-{
- be_abi_irg_t *env = be_get_irg_abi(irg);
- be_stack_layout_t *stack_layout = be_get_irg_stack_layout(irg);
- ir_type *frame_tp;
- int i;
- struct bias_walk bw;
-
- stack_frame_compute_initial_offset(stack_layout);
- // stack_layout_dump(stdout, stack_layout);
-
- /* Determine the stack bias at the end of the start block. */
- bw.start_block_bias = process_stack_bias(env, 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.env = env;
- bw.start_block = get_irg_start_block(irg);
- irg_block_walk_graph(irg, stack_bias_walker, NULL, &bw);
-
- /* fix now inner functions: these still have Sel node to outer
- frame and parameter entities */
- frame_tp = get_irg_frame_type(irg);
- for (i = get_class_n_members(frame_tp) - 1; i >= 0; --i) {
- ir_entity *ent = get_class_member(frame_tp, i);
- ir_graph *irg = get_entity_irg(ent);
-
- if (irg != NULL) {
- irg_walk_graph(irg, NULL, lower_outer_frame_sels, env);
- }