From: Christian Würdig Date: Tue, 24 Jan 2006 14:55:35 +0000 (+0000) Subject: fixed assignement of stack register X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=de69494d834f44158c928849e767209f5c056de2;p=libfirm fixed assignement of stack register added callbacks for spill- and reload-lowering --- diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index a40891558..412e331f0 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -7,6 +7,7 @@ #include "irprog.h" #include "irprintf.h" #include "iredges_t.h" +#include "ircons.h" #include "bitset.h" #include "debug.h" @@ -73,7 +74,7 @@ static int is_Start_Proj(const ir_node *n) { static int is_P_frame_base_Proj(const ir_node *n) { if (is_Proj(n) && - is_Start(n) && + is_Start(get_Proj_pred(n)) && get_Proj_proj(n) == pn_Start_P_frame_base) { return 1; @@ -334,34 +335,65 @@ 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]); + if (cg->has_alloca) { + arch_set_irn_register(cg->arch_env, irn, &ia32_general_purpose_regs[REG_EBP]); + } + else { + 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. + * Dummy functions for hooks we don't need but which must be filled. */ -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); +static void ia32_before_sched(void *self) { } +static void ia32_before_ra(void *self) { +} /** - * Dummy functions for hooks we don't need but which must be filled. + * Creates a Store for a Spill */ -static void ia32_before_ra(void *self) { +static ir_node *ia32_lower_spill(void *self, ir_node *spill) { + ia32_code_gen_t *cg = self; + unsigned offs = be_get_spill_offset(spill); + dbg_info *dbg = get_irn_dbg_info(spill); + ir_node *block = get_nodes_block(spill); + ir_node *ptr = get_irg_frame(cg->irg); + ir_node *val = be_get_Spill_context(spill); + ir_node *mem = new_rd_NoMem(cg->irg); + ir_mode *mode = get_irn_mode(spill); + ir_node *res; + + res = new_rd_ia32_Store(dbg, cg->irg, block, ptr, val, mem, mode); + set_ia32_am_offs(res, new_tarval_from_long(offs, mode_Iu)); + + return res; } - +/** + * Create a Load for a Spill + */ +static ir_node *ia32_lower_reload(void *self, ir_node *reload) { + ia32_code_gen_t *cg = self; + dbg_info *dbg = get_irn_dbg_info(reload); + ir_node *block = get_nodes_block(reload); + ir_node *ptr = get_irg_frame(cg->irg); + ir_mode *mode = get_irn_mode(reload); + ir_node *store = get_irn_n(reload, 0); + tarval *tv = get_ia32_am_offs(store); + ir_node *res; + + res = new_rd_ia32_Load(dbg, cg->irg, block, ptr, store, mode); + set_ia32_am_offs(res, tv); + + return res; +} /** * Emits the code, closes the output file and frees @@ -377,6 +409,10 @@ static void ia32_codegen(void *self) { cg->emit_decls = 0; } + /* set the stack register */ + if (! is_pseudo_ir_graph(irg)) + irg_walk_blkwise_graph(irg, NULL, ia32_set_P_frame_base_Proj_reg, cg); + // ia32_finish_irg(irg); ia32_gen_routine(out, irg, cg->arch_env); @@ -392,8 +428,10 @@ 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_some_stuff_need_to_be_done_after_deadnode_elimination, /* before scheduling hook */ + ia32_before_sched, /* before scheduling hook */ ia32_before_ra, /* before register allocation hook */ + ia32_lower_spill, + ia32_lower_reload, ia32_codegen /* emit && done */ };