From: Michael Beck Date: Fri, 8 Sep 2006 22:43:39 +0000 (+0000) Subject: Added support for be_SubSP nodes X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=5f07fa3a5c620a82be0a5b0b06fbf325f5f32c9f;p=libfirm Added support for be_SubSP nodes --- diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 8612528a5..221129707 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -1789,8 +1789,11 @@ static void emit_ia32_Const(const ir_node *n, ia32_emit_env_t *env) { FILE *F = env->out; char cmd_buf[256], cmnt_buf[256]; const lc_arg_env_t *arg_env = ia32_get_arg_env(); + ir_mode *mode = get_irn_mode(n); + tarval *tv = get_ia32_Immop_tarval(n); - if (get_ia32_Immop_tarval(n) == get_tarval_null(get_irn_mode(n))) { + /* beware: in some rare cases mode is mode_b which has no tarval_null() */ + if (tv == get_tarval_b_false() || tv == get_tarval_null(mode)) { const char *instr = "xor"; if (env->isa->opt_arch == arch_pentium_4) { /* P4 prefers sub r, r, others xor r, r */ @@ -1836,6 +1839,30 @@ static void emit_ia32_AddSP(const ir_node *irn, ia32_emit_env_t *emit_env) { IA32_DO_EMIT(irn); } +/** + * Emits code to increase stack pointer. + */ +static void emit_ia32_SubSP(const ir_node *irn, ia32_emit_env_t *emit_env) { + FILE *F = emit_env->out; + char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN]; + + if (is_ia32_ImmConst(irn)) { + lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "add %1D, %C", irn, irn); + } + else if (is_ia32_ImmSymConst(irn)) { + if (get_ia32_op_type(irn) == ia32_Normal) + lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "add %1D, OFFSET_FLAT:%C", irn, irn); + else /* source address mode */ + lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "add %1D, [%s%s]", irn, get_id_str(get_ia32_am_sc(irn)), get_ia32_am_offs(irn)); + } + else { + lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "add %1D, %2S", irn, irn); + } + snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* free space on stack */"); + + IA32_DO_EMIT(irn); +} + /** * Emits code to load the TLS base */ @@ -1921,6 +1948,7 @@ static void ia32_register_emitters(void) { IA32_EMIT(Conv_I2I8Bit); IA32_EMIT(Const); IA32_EMIT(AddSP); + IA32_EMIT(SubSP); IA32_EMIT(LdTls); IA32_EMIT(xCmp); IA32_EMIT(xCmpSet); diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 0d32820d6..d9e20db87 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -770,6 +770,13 @@ else { "outs" => [ "stack", "M" ], }, +"SubSP" => { + "irn_flags" => "I", + "comment" => "free space on stack", + "reg_req" => { "in" => [ "esp", "gp" ], "out" => [ "esp", "none" ] }, + "outs" => [ "stack", "M" ], +}, + "LdTls" => { "irn_flags" => "R", "comment" => "get the TLS base address", diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index 4540b6f9d..33a5b7255 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -2470,6 +2470,54 @@ static ir_node *gen_be_AddSP(ia32_transform_env_t *env) { return new_op; } +/** + * Transform a be_SubSP into an ia32_SubSP. Eat up const sizes. + */ +static ir_node *gen_be_SubSP(ia32_transform_env_t *env) { + ir_node *new_op; + const ir_edge_t *edge; + ir_node *sz = get_irn_n(env->irn, be_pos_SubSP_size); + ir_node *sp = get_irn_n(env->irn, be_pos_SubSP_old_sp); + + new_op = new_rd_ia32_SubSP(env->dbg, env->irg, env->block, sp, sz); + + if (is_ia32_Const(sz)) { + set_ia32_Immop_attr(new_op, sz); + set_irn_n(new_op, 1, ia32_new_NoReg_gp(env->cg)); + } + else if (is_ia32_Load(sz) && get_ia32_am_flavour(sz) == ia32_O) { + set_ia32_immop_type(new_op, ia32_ImmSymConst); + set_ia32_op_type(new_op, ia32_AddrModeS); + set_ia32_am_sc(new_op, get_ia32_am_sc(sz)); + add_ia32_am_offs(new_op, get_ia32_am_offs(sz)); + set_irn_n(new_op, 1, ia32_new_NoReg_gp(env->cg)); + } + + /* fix proj nums */ + foreach_out_edge(env->irn, edge) { + ir_node *proj = get_edge_src_irn(edge); + + assert(is_Proj(proj)); + + if (get_Proj_proj(proj) == pn_be_SubSP_res) { + /* the node is not yet exchanged: we need to set the register manually */ + ia32_attr_t *attr = get_ia32_attr(new_op); + attr->slots[pn_ia32_SubSP_stack] = &ia32_gp_regs[REG_ESP]; + set_Proj_proj(proj, pn_ia32_SubSP_stack); + } + else if (get_Proj_proj(proj) == pn_be_SubSP_M) { + set_Proj_proj(proj, pn_ia32_SubSP_M); + } + else { + assert(0); + } + } + + SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn)); + + return new_op; +} + /** * This function just sets the register for the Unknown node * as this is not done during register allocation because Unknown @@ -2970,6 +3018,7 @@ void ia32_register_transformers(void) { GEN(be_FrameStore); GEN(be_StackParam); GEN(be_AddSP); + GEN(be_SubSP); /* set the register for all Unknown nodes */ GEN(Unknown);