From: Christian Würdig Date: Fri, 20 Jan 2006 17:55:44 +0000 (+0000) Subject: assign esp to special stack node (frame_base Proj) X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=0d22619b6ca7337e2b0fdda4a3b06e410759cc32;p=libfirm assign esp to special stack node (frame_base Proj) check for alloca and use ebp as stack register if found --- diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index 5be53ce44..a3af2ef49 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -58,6 +58,17 @@ static int is_Call_Proj(const ir_node *n) { return 0; } +static int is_P_frame_base_Proj(const ir_node *n) { + if (is_Proj(n) && + get_irn_opcode(get_Proj_pred(n)) == iro_Start && + get_Proj_proj(n) == pn_Start_P_frame_base) + { + return 1; + } + + return 0; +} + static int is_used_by_Keep(const ir_node *n) { return be_is_Keep(get_edge_src_irn(get_irn_out_edge_first(n))); } @@ -138,8 +149,6 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const arch_irn_ops_t *sel case pn_Start_X_initial_exec: case pn_Start_P_value_arg_base: case pn_Start_P_globals: - memcpy(req, &(ia32_default_req_none.req), sizeof(*req)); - break; case pn_Start_P_frame_base: memcpy(req, &(ia32_default_req_none.req), sizeof(*req)); break; @@ -163,10 +172,10 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const arch_irn_ops_t *sel static void ia32_set_irn_reg(const arch_irn_ops_t *self, ir_node *irn, const arch_register_t *reg) { int pos = 0; - if (is_Call_Proj(irn) && is_used_by_Keep(irn)) { + if ((is_Call_Proj(irn) && is_used_by_Keep(irn)) || is_P_frame_base_Proj(irn)) { /* don't skip the proj, we want to take the else below */ } - if (is_Proj(irn)) { + else if (is_Proj(irn)) { pos = ia32_translate_proj_pos(irn); irn = my_skip_proj(irn); } @@ -186,7 +195,7 @@ static const arch_register_t *ia32_get_irn_reg(const arch_irn_ops_t *self, const int pos = 0; const arch_register_t *reg = NULL; - if (is_Call_Proj(irn) && is_used_by_Keep(irn)) { + if ((is_Call_Proj(irn) && is_used_by_Keep(irn)) || is_P_frame_base_Proj(irn)) { /* don't skip the proj, we want to take the else below */ } else if (is_Proj(irn)) { @@ -251,25 +260,72 @@ static const arch_irn_ops_t ia32_irn_ops = { * |___/ **************************************************/ +static void check_for_alloca(ir_node *irn, void *env) { + int *has_alloca = env; + + if (get_irn_opcode(irn) == iro_Alloc) { + if (get_Alloc_where(irn) == stack_alloc) { + *has_alloca = 1; + } + } +} + /** * Transforms the standard firm graph into * an ia32 firm graph */ static void ia32_prepare_graph(void *self) { - ia32_code_gen_t *cg = self; + ia32_code_gen_t *cg = self; + int has_alloca = 0; + + if (! is_pseudo_ir_graph(cg->irg)) { + /* If there is a alloca in the irg, we use %ebp for stack addressing */ + /* instead of %esp, as alloca destroys %esp. */ + + /* check for alloca node */ + irg_walk_blkwise_graph(cg->irg, check_for_alloca, NULL, &has_alloca); + + if (has_alloca) { + ia32_general_purpose_regs[REG_EBP].type = arch_register_type_ignore; + } - if (! is_pseudo_ir_graph(cg->irg)) irg_walk_blkwise_graph(cg->irg, NULL, ia32_transform_node, cg); + } } /** - * Dummy functions for hooks we don't need but which must be filled. + * Set the register for P_frame_base Proj to %esp. */ -static void ia32_before_sched(void *self) { +static void ia32_set_P_frame_base_Proj_reg(ir_node *irn, void *env) { + ia32_code_gen_t *cg = env; + + if (is_P_frame_base_Proj(irn)) { + arch_set_irn_register(cg->arch_env, irn, &ia32_general_purpose_regs[REG_ESP]); + } } +/** + * This function is the hook before_sched but more important: it is + * called after the dead node elimination. The dead node elimination changes + * the memory location of the nodes, which will change the hash key of + * the Proj_P_frame_base(Start) and this will fuck up the firm_node -> register + * hash map. So we need to insert the register for this node after the dead node + * elimination. + */ +static void ia32_some_stuff_need_to_be_done_after_deadnode_elimination(void *self) { + ia32_code_gen_t *cg = self; + + if (! is_pseudo_ir_graph(cg->irg)) + irg_walk_blkwise_graph(cg->irg, NULL, ia32_set_P_frame_base_Proj_reg, cg); +} + + + +/** + * Dummy functions for hooks we don't need but which must be filled. + */ static void ia32_before_ra(void *self) { } @@ -304,7 +360,7 @@ static void *ia32_cg_init(FILE *F, ir_graph *irg, const arch_env_t *arch_env); static const arch_code_generator_if_t ia32_code_gen_if = { ia32_cg_init, ia32_prepare_graph, - ia32_before_sched, /* before scheduling hook */ + ia32_some_stuff_need_to_be_done_after_deadnode_elimination, /* before scheduling hook */ ia32_before_ra, /* before register allocation hook */ ia32_codegen /* emit && done */ }; diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 7a009d1fe..381694236 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -141,12 +141,6 @@ int get_ia32_reg_nr(ir_node *irn, int pos, int in_out) { ir_node *op; if (in_out == 1) { - /* special case Proj P_fame_base */ - op = get_irn_n(irn, pos); - if (is_Proj(op) && get_Proj_proj(op) == pn_Start_P_frame_base) { - return 10; - } - reg = get_in_reg(irn, pos); } else { @@ -164,11 +158,6 @@ const char *get_ia32_reg_name(ir_node *irn, int pos, int in_out) { ir_node *op; if (in_out == 1) { - /* special case Proj P_fame_base */ - op = get_irn_n(irn, pos); - if (is_Proj(op) && get_Proj_proj(op) == pn_Start_P_frame_base) { - return "x(esp)"; - } reg = get_in_reg(irn, pos); } else { diff --git a/ir/be/ia32/ia32_map_regs.c b/ir/be/ia32/ia32_map_regs.c index e8acbc08d..c804755b2 100644 --- a/ir/be/ia32/ia32_map_regs.c +++ b/ir/be/ia32/ia32_map_regs.c @@ -23,7 +23,7 @@ int ia32_cmp_irn_reg_assoc(const void *a, const void *b, size_t len) { const struct ia32_irn_reg_assoc *x = a; const struct ia32_irn_reg_assoc *y = b; - return !(x->irn == y->irn); + return x->irn != y->irn; } static struct ia32_irn_reg_assoc *get_irn_reg_assoc(const ir_node *irn, set *reg_set) { diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 6701cd414..2c2f96770 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -76,17 +76,19 @@ $arch = "ia32"; # 2 - caller save (register must be saved by the caller of a function) # 3 - callee save (register must be saved by the called function) # 4 - ignore (do not assign this register) -# NOTE: Make sure to list the registers returning the call-result at first and -# in the correct order, otherwise it will break the magic! +# NOTE: Make sure to list the registers returning the call-result before all other +# caller save registers and in the correct order, otherwise it will break +# the magic! %reg_classes = ( "general_purpose" => [ { "name" => "eax", "type" => 2 }, { "name" => "edx", "type" => 2 }, { "name" => "ebx", "type" => 3 }, { "name" => "ecx", "type" => 2 }, - { "name" => "edi", "type" => 2 }, { "name" => "esi", "type" => 3 }, - { "name" => "ebp", "type" => 3 } + { "name" => "edi", "type" => 3 }, + { "name" => "ebp", "type" => 3 }, + { "name" => "esp", "type" => 4 } # we don't want esp to be assigned ], "floating_point" => [ { "name" => "xmm0", "type" => 2 }, diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index 74f43136a..005ee4876 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -1480,9 +1480,9 @@ static ir_node *gen_Proj_Start(transform_env_t *env, ir_node *proj, ir_node *sta free(projargs); break; + case pn_Start_P_frame_base: case pn_Start_X_initial_exec: case pn_Start_M: - case pn_Start_P_frame_base: case pn_Start_P_globals: case pn_Start_P_value_arg_base: break; @@ -1604,11 +1604,11 @@ void ia32_transform_node(ir_node *node, void *env) { IGN(Break); IGN(Cmp); + BAD(Alloc); BAD(Raise); BAD(Sel); BAD(InstOf); BAD(Cast); - BAD(Alloc); BAD(Free); BAD(Sync); BAD(Tuple);