From 49650674902ee8d35388f8cff11568ec98b109ff Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Mon, 19 Jan 2009 23:14:27 +0000 Subject: [PATCH] - mostly implemented access to outer frame variables, however offset, is wrong yet [r25274] --- ir/be/TEMPLATE/bearch_TEMPLATE.c | 1 + ir/be/arm/bearch_arm.c | 1 + ir/be/beabi.c | 156 +++++++++++++++++++++++-------- ir/be/bearch_t.h | 19 ++-- ir/be/ia32/bearch_ia32.c | 1 + ir/be/mips/bearch_mips.c | 1 + ir/be/ppc32/bearch_ppc32.c | 1 + 7 files changed, 132 insertions(+), 48 deletions(-) diff --git a/ir/be/TEMPLATE/bearch_TEMPLATE.c b/ir/be/TEMPLATE/bearch_TEMPLATE.c index def07d557..1ab3ca677 100644 --- a/ir/be/TEMPLATE/bearch_TEMPLATE.c +++ b/ir/be/TEMPLATE/bearch_TEMPLATE.c @@ -283,6 +283,7 @@ static TEMPLATE_isa_t TEMPLATE_isa_template = { &TEMPLATE_isa_if, /* isa interface implementation */ &TEMPLATE_general_purpose_regs[REG_SP], /* stack pointer register */ &TEMPLATE_general_purpose_regs[REG_BP], /* base pointer register */ + &TEMPLATE_reg_classes[CLASS_TEMPLATE_general_purpose], /* link pointer register class */ -1, /* stack direction */ 2, /* power of two stack alignment for calls, 2^2 == 4 */ NULL, /* main environment */ diff --git a/ir/be/arm/bearch_arm.c b/ir/be/arm/bearch_arm.c index ae527b12f..3f12b5f85 100644 --- a/ir/be/arm/bearch_arm.c +++ b/ir/be/arm/bearch_arm.c @@ -652,6 +652,7 @@ static arm_isa_t arm_isa_template = { &arm_isa_if, /* isa interface */ &arm_gp_regs[REG_SP], /* stack pointer */ &arm_gp_regs[REG_R11], /* base pointer */ + &arm_reg_classes[CLASS_arm_gp], /* static link pointer class */ -1, /* stack direction */ 2, /* power of two stack alignment for calls, 2^2 == 4 */ NULL, /* main environment */ diff --git a/ir/be/beabi.c b/ir/be/beabi.c index 723147784..e9ee9d66d 100644 --- a/ir/be/beabi.c +++ b/ir/be/beabi.c @@ -342,7 +342,7 @@ static int stack_frame_compute_initial_offset(be_stack_layout_t *frame) * @param args the stack argument layout type * @param between the between layout type * @param locals the method frame type - * @param stack_dir the stack direction + * @param stack_dir the stack direction: < 0 decreasing, > 0 increasing addresses * @param param_map an array mapping method argument positions to the stack argument type * * @return the initialized stack layout @@ -365,6 +365,8 @@ static be_stack_layout_t *stack_frame_init(be_stack_layout_t *frame, ir_type *ar frame->order[2] = locals; } else { + /* typical decreasing stack: locals have the + * lowest addresses, arguments the highest */ frame->order[0] = locals; frame->order[2] = args; } @@ -429,8 +431,8 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp) ir_node *curr_mem = get_Call_mem(irn); ir_node *bl = get_nodes_block(irn); int stack_size = 0; - int stack_dir = arch_env_stack_dir(arch_env); - const arch_register_t *sp = arch_env_sp(arch_env); + int stack_dir = arch_env->stack_dir; + const arch_register_t *sp = arch_env->sp; 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; @@ -1504,13 +1506,50 @@ struct ent_pos_pair { }; typedef struct lower_frame_sels_env_t { - ent_pos_pair *value_param_list; /**< the list of all value param entities */ - ir_node *frame; /**< the current frame */ - const arch_register_class_t *sp_class; /**< register class of the stack pointer */ - ir_type *value_tp; /**< the value type if any */ - ir_type *frame_tp; /**< the frame type */ + ent_pos_pair *value_param_list; /**< the list of all value param entities */ + ir_node *frame; /**< the current frame */ + const arch_register_class_t *sp_class; /**< register class of the stack pointer */ + const arch_register_class_t *link_class; /**< register class of the link pointer */ + ir_type *value_tp; /**< the value type if any */ + ir_type *frame_tp; /**< the frame type */ + int static_link_pos; /**< argument number of the hidden static link */ } lower_frame_sels_env_t; +/** + * Return an entity from the backend for an value param entity. + * + * @param ent an value param type entity + * @param ctx context + */ +static ir_entity *get_argument_entity(ir_entity *ent, lower_frame_sels_env_t *ctx) +{ + ir_entity *argument_ent = get_entity_link(ent); + + if (argument_ent == NULL) { + /* we have NO argument entity yet: This is bad, as we will + * need one for backing store. + * Create one here. + */ + ir_type *frame_tp = ctx->frame_tp; + unsigned offset = get_type_size_bytes(frame_tp); + ir_type *tp = get_entity_type(ent); + unsigned align = get_type_alignment_bytes(tp); + + offset += align - 1; + offset &= ~(align - 1); + + argument_ent = copy_entity_own(ent, frame_tp); + + /* must be automatic to set a fixed layout */ + set_entity_allocation(argument_ent, allocation_automatic); + set_entity_offset(argument_ent, offset); + offset += get_type_size_bytes(tp); + + set_type_size_bytes(frame_tp, offset); + set_entity_link(ent, argument_ent); + } + return argument_ent; +} /** * Walker: Replaces Sels of frame type and * value param type entities by FrameAddress. @@ -1530,35 +1569,9 @@ static void lower_frame_sels_walker(ir_node *irn, void *data) int pos = 0; if (get_entity_owner(ent) == ctx->value_tp) { - ir_entity *argument_ent = get_entity_link(ent); - /* replace by its copy from the argument type */ pos = get_struct_member_index(ctx->value_tp, ent); - - if (argument_ent == NULL) { - /* we have NO argument entity yet: This is bad, as we will - * need one for backing store. - * Create one here. - */ - ir_type *frame_tp = ctx->frame_tp; - unsigned offset = get_type_size_bytes(frame_tp); - ir_type *tp = get_entity_type(ent); - unsigned align = get_type_alignment_bytes(tp); - - offset += align - 1; - offset &= ~(align - 1); - - argument_ent = copy_entity_own(ent, frame_tp); - - /* must be automatic to set a fixed layout */ - set_entity_allocation(argument_ent, allocation_automatic); - set_entity_offset(argument_ent, offset); - offset += get_type_size_bytes(tp); - - set_type_size_bytes(frame_tp, offset); - set_entity_link(ent, argument_ent); - } - ent = argument_ent; + ent = get_argument_entity(ent, ctx); } nw = be_new_FrameAddr(ctx->sp_class, current_ir_graph, bl, ctx->frame, ent); @@ -1728,6 +1741,68 @@ static void fix_start_block(ir_graph *irg) panic("Initial exec has no follow block in %+F", irg); } +static void lower_outer_frame_sels(ir_node *irn, void *env) { + lower_frame_sels_env_t *ctx = env; + ir_node *ptr, *bl, *nw; + ir_entity *ent; + int pos = 0; + + if (! is_Sel(irn)) + return; + ptr = get_Sel_ptr(irn); + if (! is_arg_Proj(ptr)) + return; + if (get_Proj_proj(ptr) != ctx->static_link_pos) + return; + ent = get_Sel_entity(irn); + + if (get_entity_owner(ent) == ctx->value_tp) { + /* replace by its copy from the argument type */ + pos = get_struct_member_index(ctx->value_tp, ent); + ent = get_argument_entity(ent, ctx); + } + bl = get_nodes_block(irn); + nw = be_new_FrameAddr(ctx->link_class, current_ir_graph, bl, ptr, ent); + exchange(irn, nw); + + /* check, if it's a param sel and if have not seen this entity before */ + if (get_entity_owner(ent) == ctx->value_tp && get_entity_link(ent) == NULL) { + ent_pos_pair pair; + + pair.ent = ent; + pair.pos = pos; + pair.next = NULL; + ARR_APP1(ent_pos_pair, ctx->value_param_list, pair); + /* just a mark */ + set_entity_link(ent, ctx->value_param_list); + } +} + +/** + * Fix access to outer local variables. + */ +static void fix_outer_variable_access(be_abi_irg_t *env, lower_frame_sels_env_t *ctx) +{ + int i; + ir_graph *irg; + + for (i = get_class_n_members(ctx->frame_tp) - 1; i >= 0; --i) { + ir_entity *ent = get_class_member(ctx->frame_tp, i); + + if (! is_method_entity(ent)) + continue; + + /* + * FIXME: find the number of the static link parameter + * for now we assume 0 here + */ + ctx->static_link_pos = 0; + + irg = get_entity_irg(ent); + irg_walk_graph(irg, NULL, lower_outer_frame_sels, ctx); + } +} + /** * Modify the irg itself and the frame type. */ @@ -1735,7 +1810,7 @@ static void modify_irg(be_abi_irg_t *env) { be_abi_call_t *call = env->call; const arch_env_t *arch_env= env->birg->main_env->arch_env; - const arch_register_t *sp = arch_env_sp(arch_env); + const arch_register_t *sp = arch_env->sp; ir_graph *irg = env->birg->irg; ir_node *start_bl; ir_node *end; @@ -1788,6 +1863,7 @@ static void modify_irg(be_abi_irg_t *env) ctx.value_param_list = NEW_ARR_F(ent_pos_pair, 0); ctx.frame = get_irg_frame(irg); ctx.sp_class = env->arch_env->sp->reg_class; + ctx.link_class = env->arch_env->link_class; ctx.frame_tp = get_irg_frame_type(irg); /* we will possible add new entities to the frame: set the layout to undefined */ @@ -1805,6 +1881,11 @@ static void modify_irg(be_abi_irg_t *env) args = obstack_alloc(&env->obst, n_params * sizeof(args[0])); memset(args, 0, n_params * sizeof(args[0])); + /* + * for inner function we must now fix access to outer frame entities. + */ + fix_outer_variable_access(env, &ctx); + /* Check if a value parameter is transmitted as a register. * This might happen if the address of an parameter is taken which is * transmitted in registers. @@ -1816,6 +1897,7 @@ static void modify_irg(be_abi_irg_t *env) * a backing store into the first block. */ fix_address_of_parameter_access(env, ctx.value_param_list); + DEL_ARR_F(ctx.value_param_list); irp_free_resources(irp, IR_RESOURCE_ENTITY_LINK); @@ -2438,7 +2520,7 @@ static int process_stack_bias(be_abi_irg_t *env, ir_node *bl, int real_bias) node. */ ir_entity *ent = arch_get_frame_entity(irn); - if (ent) { + if (ent != NULL) { int bias = omit_fp ? real_bias : 0; int offset = get_stack_entity_offset(&env->frame, ent, bias); arch_set_frame_offset(irn, offset); diff --git a/ir/be/bearch_t.h b/ir/be/bearch_t.h index e3cc892b7..e7c0320b7 100644 --- a/ir/be/bearch_t.h +++ b/ir/be/bearch_t.h @@ -538,19 +538,16 @@ struct arch_isa_if_t { */ struct arch_env_t { const arch_isa_if_t *impl; - const arch_register_t *sp; /** The stack pointer register. */ - const arch_register_t *bp; /** The base pointer register. */ - int stack_dir; /** -1 for decreasing, 1 for increasing. */ - int stack_alignment; /** power of 2 stack alignment */ - const be_main_env_t *main_env; /** the be main environment */ - int spill_cost; /** cost for a be_Spill node */ - int reload_cost; /** cost for a be_Reload node */ + const arch_register_t *sp; /** The stack pointer register. */ + const arch_register_t *bp; /** The base pointer register. */ + const arch_register_class_t *link_class; /** The static link pointer register class. */ + int stack_dir; /** -1 for decreasing, 1 for increasing. */ + int stack_alignment; /** power of 2 stack alignment */ + const be_main_env_t *main_env; /** the be main environment */ + int spill_cost; /** cost for a be_Spill node */ + int reload_cost; /** cost for a be_Reload node */ }; -#define arch_env_stack_dir(env) ((env)->stack_dir) -#define arch_env_sp(env) ((env)->sp) -#define arch_env_bp(env) ((env)->bp) - static inline unsigned arch_irn_get_n_outs(const ir_node *node) { backend_info_t *info = be_get_info(node); diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index 7ae42eead..d2f4c77af 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -1610,6 +1610,7 @@ static ia32_isa_t ia32_isa_template = { &ia32_isa_if, /* isa interface implementation */ &ia32_gp_regs[REG_ESP], /* stack pointer register */ &ia32_gp_regs[REG_EBP], /* base pointer register */ + &ia32_reg_classes[CLASS_ia32_gp], /* static link pointer register class */ -1, /* stack direction */ 2, /* power of two stack alignment, 2^2 == 4 */ NULL, /* main environment */ diff --git a/ir/be/mips/bearch_mips.c b/ir/be/mips/bearch_mips.c index d48958535..0604a324f 100644 --- a/ir/be/mips/bearch_mips.c +++ b/ir/be/mips/bearch_mips.c @@ -366,6 +366,7 @@ static mips_isa_t mips_isa_template = { &mips_isa_if, &mips_gp_regs[REG_SP], &mips_gp_regs[REG_FP], + &mips_reg_classes[CLASS_mips_gp], -1, /* stack direction */ 2, /* power of two stack alignment for calls, 2^2 == 4 */ NULL, /* main environment */ diff --git a/ir/be/ppc32/bearch_ppc32.c b/ir/be/ppc32/bearch_ppc32.c index 2b42d0a5c..3d7b95660 100644 --- a/ir/be/ppc32/bearch_ppc32.c +++ b/ir/be/ppc32/bearch_ppc32.c @@ -545,6 +545,7 @@ static ppc32_isa_t ppc32_isa_template = { &ppc32_isa_if, /* isa interface */ &ppc32_gp_regs[REG_R1], /* stack pointer */ &ppc32_gp_regs[REG_R31], /* base pointer */ + &ppc32_reg_classes[CLASS_ppc32_gp], /* static link pointer class */ -1, /* stack is decreasing */ 2, /* power of two stack alignment for calls, 2^2 == 4 */ NULL, /* main environment */ -- 2.20.1