From: Michael Beck Date: Thu, 18 Dec 2008 18:19:51 +0000 (+0000) Subject: - implemented __builtin_return_address(0) X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=d266f5722bbfd01292a2bc3a2ddf188af8a2c702;p=libfirm - implemented __builtin_return_address(0) [r24793] --- diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index 44f08c62f..035d96f08 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -101,6 +101,14 @@ static set *cur_reg_set = NULL; ir_mode *mode_fpcw = NULL; ia32_code_gen_t *ia32_current_cg = NULL; +/** The current omit-fp state */ +static unsigned ia32_curr_fp_ommitted = 0; +static ir_type *omit_fp_between_type = NULL; +static ir_type *between_type = NULL; +static ir_entity *old_bp_ent = NULL; +static ir_entity *ret_addr_ent = NULL; +static ir_entity *omit_fp_ret_addr_ent = NULL; + /** * The environment for the intrinsic mapping. */ @@ -337,6 +345,7 @@ static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap ia32_code_gen_t *cg = ia32_current_cg; const arch_env_t *arch_env = env->aenv; + ia32_curr_fp_ommitted = env->flags.try_omit_fp; if (! env->flags.try_omit_fp) { ir_graph *irg = env->irg; ir_node *bl = get_irg_start_block(irg); @@ -464,23 +473,11 @@ static void ia32_abi_done(void *self) { } /** - * Produces the type which sits between the stack args and the locals on the stack. - * it will contain the return address and space to store the old base pointer. - * @return The Firm type modeling the ABI between type. + * Build the between type and entities if not already build. */ -static ir_type *ia32_abi_get_between_type(void *self) -{ +static void ia32_build_between_type(void) { #define IDENT(s) new_id_from_chars(s, sizeof(s)-1) - static ir_type *omit_fp_between_type = NULL; - static ir_type *between_type = NULL; - - ia32_abi_env_t *env = self; - if (! between_type) { - ir_entity *old_bp_ent; - ir_entity *ret_addr_ent; - ir_entity *omit_fp_ret_addr_ent; - ir_type *old_bp_type = new_type_primitive(IDENT("bp"), mode_Iu); ir_type *ret_addr_type = new_type_primitive(IDENT("return_addr"), mode_Iu); @@ -500,9 +497,28 @@ static ir_type *ia32_abi_get_between_type(void *self) set_type_size_bytes(omit_fp_between_type, get_type_size_bytes(ret_addr_type)); set_type_state(omit_fp_between_type, layout_fixed); } +#undef IDENT +} + +/** + * Produces the type which sits between the stack args and the locals on the stack. + * it will contain the return address and space to store the old base pointer. + * @return The Firm type modeling the ABI between type. + */ +static ir_type *ia32_abi_get_between_type(void *self) +{ + ia32_abi_env_t *env = self; + ia32_build_between_type(); return env->flags.try_omit_fp ? omit_fp_between_type : between_type; -#undef IDENT +} + +/** + * Return the stack entity that contains the return address. + */ +ir_entity *ia32_get_return_address_entity(void) { + ia32_build_between_type(); + return ia32_curr_fp_ommitted ? omit_fp_ret_addr_ent : ret_addr_ent; } /** diff --git a/ir/be/ia32/bearch_ia32_t.h b/ir/be/ia32/bearch_ia32_t.h index 110f2394a..a85ca4bb2 100644 --- a/ir/be/ia32/bearch_ia32_t.h +++ b/ir/be/ia32/bearch_ia32_t.h @@ -176,4 +176,9 @@ ir_entity *ia32_create_intrinsic_fkt(ir_type *method, const ir_op *op, const ir_mode *imode, const ir_mode *omode, void *context); +/** + * Return the stack entity that contains the return address. + */ +ir_entity *ia32_get_return_address_entity(void); + #endif diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index 8f2615e41..024813730 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -90,8 +90,6 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;) static ir_node *initial_fpcw = NULL; -extern ir_op *get_op_Mulh(void); - typedef ir_node *construct_binop_func(dbg_info *db, ir_node *block, ir_node *base, ir_node *index, ir_node *mem, ir_node *op1, ir_node *op2); @@ -4520,6 +4518,82 @@ static ir_node *gen_be_Call(ir_node *node) return call; } +/** + * Transform Builtin return_address + */ +static ir_node *gen_return_address(ir_node *node) { + ir_node *param = get_Builtin_param(node, 0); + ir_node *frame = get_Builtin_param(node, 1); + dbg_info *dbgi = get_irn_dbg_info(node); + tarval *tv = get_Const_tarval(param); + long value = get_tarval_long(tv); + + ir_node *block = be_transform_node(get_nodes_block(node)); + + if (value == 0) { + /* the return address of the current function */ + ir_node *new_op = be_transform_node(frame); + ir_node *noreg = ia32_new_NoReg_gp(env_cg); + ir_node *new_node; + + new_node = new_bd_ia32_Load(dbgi, block, new_op, noreg, get_irg_no_mem(current_ir_graph)); + + set_irn_pinned(new_node, get_irn_pinned(node)); + set_ia32_op_type(new_node, ia32_AddrModeS); + set_ia32_ls_mode(new_node, mode_Iu); + + set_ia32_am_offs_int(new_node, 0); + set_ia32_use_frame(new_node); + set_ia32_frame_ent(new_node, ia32_get_return_address_entity()); + + if (get_irn_pinned(node) == op_pin_state_floats) { + assert(pn_ia32_xLoad_res == pn_ia32_vfld_res + && pn_ia32_vfld_res == pn_ia32_Load_res + && pn_ia32_Load_res == pn_ia32_res); + arch_irn_add_flags(new_node, arch_irn_flags_rematerializable); + } + + SET_IA32_ORIG_NODE(new_node, node); + return new_rd_Proj(dbgi, current_ir_graph, block, new_node, mode_Iu, pn_ia32_Load_res); + } + panic("builtin_return_address(%ld) not supported in IA32", value); +} + +/** + * Transform Builtin node. + */ +static ir_node *gen_Builtin(ir_node *node) { + ir_builtin_kind kind = get_Builtin_kind(node); + + switch (kind) { + case ir_bk_return_address: + return gen_return_address(node); + case ir_bk_frame_addess: + case ir_bk_prefetch: + break; + } + panic("Builtin %s not implemented in IA32", get_builtin_kind_name(kind)); +} + +/** + * Transform Proj(Builtin) node. + */ +static ir_node *gen_Proj_Builtin(ir_node *proj) { + ir_node *node = get_Proj_pred(proj); + ir_node *new_node = be_transform_node(node); + ir_builtin_kind kind = get_Builtin_kind(node); + + switch (kind) { + case ir_bk_return_address: + case ir_bk_frame_addess: + assert(get_Proj_proj(proj) == pn_Builtin_1_result); + return new_node; + case ir_bk_prefetch: + break; + } + panic("Builtin %s not implemented in IA32", get_builtin_kind_name(kind)); +} + static ir_node *gen_be_IncSP(ir_node *node) { ir_node *res = be_duplicate_node(node); @@ -4725,6 +4799,8 @@ static ir_node *gen_Proj(ir_node *node) return gen_Proj_Load(node); case iro_ASM: return gen_Proj_ASM(node); + case iro_Builtin: + return gen_Proj_Builtin(node); case iro_Div: case iro_Mod: case iro_DivMod: @@ -4868,7 +4944,7 @@ static void register_transformers(void) BAD(EndExcept); /* handle builtins */ - BAD(Builtin); + GEN(Builtin); /* handle generic backend nodes */ GEN(be_FrameAddr);