X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbeabi.c;h=e10097a1e6ff709a9f9f42e8ded586e5026bb251;hb=a8e4a954b36da58bce5413b569532ef54b87abcd;hp=d692cd9ecf1616648530c5df68c3b866a5b20643;hpb=4d5c3365a58cba59993045a9e08e686d8ae079a7;p=libfirm diff --git a/ir/be/beabi.c b/ir/be/beabi.c index d692cd9ec..e10097a1e 100644 --- a/ir/be/beabi.c +++ b/ir/be/beabi.c @@ -1,12 +1,5 @@ -/** - * @file becopyheur4.c - * @brief ABI lowering - * @author Sebastian Hack - * @date 7.3.2005 - * @version $Id$ - * @license - * - * Copyrigth (C) 1995-2007 University of Karlsruhe. All right reserved. +/* + * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. * * This file is part of libFirm. * @@ -22,7 +15,13 @@ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. - * + */ + +/** + * @file + * @brief Backend ABI implementation. + * @author Sebastian Hack, Michael Beck + * @version $Id$ */ #ifdef HAVE_CONFIG_H # include "config.h" @@ -31,7 +30,6 @@ #include "obst.h" #include "offset.h" -#include "type.h" #include "irgopt.h" #include "irgraph_t.h" @@ -47,6 +45,7 @@ #include "pdeq.h" #include "irtools.h" #include "raw_bitset.h" +#include "error.h" #include "be.h" #include "beabi.h" @@ -65,9 +64,9 @@ typedef struct _be_abi_call_arg_t { int pos; const arch_register_t *reg; ir_entity *stack_ent; - unsigned alignment; - unsigned space_before; - unsigned space_after; + unsigned alignment; /**< stack alignment */ + unsigned space_before; /**< allocate space before */ + unsigned space_after; /**< allocate space after */ } be_abi_call_arg_t; struct _be_abi_call_t { @@ -89,15 +88,15 @@ struct _be_abi_irg_t { ir_type *method_type; /**< The type of the method of the IRG. */ ir_node *init_sp; /**< The node representing the stack pointer - at the start of the function. */ + at the start of the function. */ ir_node *start_barrier; /**< The barrier of the start block */ ir_node *reg_params; /**< The reg params node. */ pmap *regs; /**< A map of all callee-save and ignore regs to - their Projs to the RegParams node. */ + their Projs to the RegParams node. */ - int start_block_bias; /**< The stack bias at the end of the start block. */ + int start_block_bias; /**< The stack bias at the end of the start block. */ void *cb; /**< ABI Callback self pointer. */ @@ -795,6 +794,31 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp, i return curr_sp; } +/** + * Adjust the size of a node representing a stack alloc or free for the minimum stack alignment. + * + * @param alignment the minimum stack alignment + * @param size the node containing the non-aligned size + * @param irg the irg where new nodes are allocated on + * @param irg the block where new nodes are allocated on + * @param dbg debug info for new nodes + * + * @return a node representing the aligned size + */ +static ir_node *adjust_alloc_size(unsigned stack_alignment, ir_node *size, ir_graph *irg, ir_node *block, dbg_info *dbg) { + if (stack_alignment > 1) { + ir_mode *mode = get_irn_mode(size); + tarval *tv = new_tarval_from_long(stack_alignment-1, mode); + ir_node *mask = new_r_Const(irg, block, mode, tv); + + size = new_rd_Add(dbg, irg, block, size, mask, mode); + + tv = new_tarval_from_long(-(long)stack_alignment, mode); + mask = new_r_Const(irg, block, mode, tv); + size = new_rd_And(dbg, irg, block, size, mask, mode); + } + return size; +} /** * Adjust an alloca. * The alloca is transformed into a back end alloca node and connected to the stack nodes. @@ -806,13 +830,11 @@ static ir_node *adjust_alloc(be_abi_irg_t *env, ir_node *alloc, ir_node *curr_sp ir_node *alloc_mem; ir_node *alloc_res; ir_type *type; + dbg_info *dbg; const ir_edge_t *edge; - ir_node *new_alloc; - ir_node *size; - ir_node *addr; - ir_node *copy; - ir_node *ins[2]; + ir_node *new_alloc, *size, *addr, *copy, *ins[2]; + unsigned stack_alignment; if (get_Alloc_where(alloc) != stack_alloc) { assert(0); @@ -849,11 +871,13 @@ static ir_node *adjust_alloc(be_abi_irg_t *env, ir_node *alloc, ir_node *curr_sp return curr_sp; } + dbg = get_irn_dbg_info(alloc); + /* we might need to multiply the size with the element size */ if(type != get_unknown_type() && get_type_size_bytes(type) != 1) { tarval *tv = new_tarval_from_long(get_type_size_bytes(type), mode_Iu); - ir_node *cnst = new_rd_Const(NULL, irg, block, mode_Iu, tv); - ir_node *mul = new_rd_Mul(NULL, irg, block, get_Alloc_size(alloc), + ir_node *cnst = new_rd_Const(dbg, irg, block, mode_Iu, tv); + ir_node *mul = new_rd_Mul(dbg, irg, block, get_Alloc_size(alloc), cnst, mode_Iu); size = mul; } else { @@ -863,7 +887,13 @@ static ir_node *adjust_alloc(be_abi_irg_t *env, ir_node *alloc, ir_node *curr_sp /* The stack pointer will be modified in an unknown manner. We cannot omit it. */ env->call->flags.bits.try_omit_fp = 0; + + /* FIXME: size must be here round up for the stack alignment, but + this must be transmitted from the backend. */ + stack_alignment = 4; + size = adjust_alloc_size(stack_alignment, size, irg, block, dbg); new_alloc = be_new_AddSP(env->isa->sp, irg, block, curr_sp, size); + set_irn_dbg_info(new_alloc, dbg); if(alloc_mem != NULL) { ir_node *addsp_mem; @@ -871,8 +901,8 @@ static ir_node *adjust_alloc(be_abi_irg_t *env, ir_node *alloc, ir_node *curr_sp addsp_mem = new_r_Proj(irg, block, new_alloc, mode_M, pn_be_AddSP_M); - // We need to sync the output mem of the AddSP with the input mem - // edge into the alloc node + /* We need to sync the output mem of the AddSP with the input mem + edge into the alloc node. */ ins[0] = get_Alloc_mem(alloc); ins[1] = addsp_mem; sync = new_r_Sync(irg, block, 2, ins); @@ -914,6 +944,8 @@ static ir_node *adjust_free(be_abi_irg_t *env, ir_node *free, ir_node *curr_sp) ir_type *type; ir_node *in[2]; ir_mode *sp_mode; + unsigned stack_alignment; + dbg_info *dbg; if (get_Free_where(free) != stack_alloc) { assert(0); @@ -924,22 +956,29 @@ static ir_node *adjust_free(be_abi_irg_t *env, ir_node *free, ir_node *curr_sp) irg = get_irn_irg(block); type = get_Free_type(free); sp_mode = env->isa->sp->reg_class->mode; + dbg = get_irn_dbg_info(free); /* we might need to multiply the size with the element size */ if(type != get_unknown_type() && get_type_size_bytes(type) != 1) { tarval *tv = new_tarval_from_long(get_type_size_bytes(type), mode_Iu); - ir_node *cnst = new_rd_Const(NULL, irg, block, mode_Iu, tv); - ir_node *mul = new_rd_Mul(NULL, irg, block, get_Free_size(free), + ir_node *cnst = new_rd_Const(dbg, irg, block, mode_Iu, tv); + ir_node *mul = new_rd_Mul(dbg, irg, block, get_Free_size(free), cnst, mode_Iu); size = mul; } else { size = get_Free_size(free); } + /* FIXME: size must be here round up for the stack alignment, but + this must be transmitted from the backend. */ + stack_alignment = 4; + size = adjust_alloc_size(stack_alignment, size, irg, block, dbg); + /* The stack pointer will be modified in an unknown manner. We cannot omit it. */ env->call->flags.bits.try_omit_fp = 0; subsp = be_new_SubSP(env->isa->sp, irg, block, curr_sp, size); + set_irn_dbg_info(subsp, dbg); mem = new_r_Proj(irg, block, subsp, mode_M, pn_be_SubSP_M); res = new_r_Proj(irg, block, subsp, sp_mode, pn_be_SubSP_res); @@ -1003,7 +1042,7 @@ static int dependent_on(ir_node *n1, ir_node *n2) return heights_reachable_in_block(ir_heights, n1, n2); } -static int cmp_call_dependecy(const void *c1, const void *c2) +static int cmp_call_dependency(const void *c1, const void *c2) { ir_node *n1 = *(ir_node **) c1; ir_node *n2 = *(ir_node **) c2; @@ -1072,7 +1111,7 @@ static void process_calls_in_block(ir_node *bl, void *data) nodes = obstack_finish(&env->obst); /* order the call nodes according to data dependency */ - qsort(nodes, n, sizeof(nodes[0]), cmp_call_dependecy); + qsort(nodes, n, sizeof(nodes[0]), cmp_call_dependency); for(i = n - 1; i >= 0; --i) { ir_node *irn = nodes[i]; @@ -1089,6 +1128,7 @@ static void process_calls_in_block(ir_node *bl, void *data) curr_sp = adjust_free(env, irn, curr_sp); break; default: + panic("invalid call"); break; } } @@ -1096,9 +1136,12 @@ static void process_calls_in_block(ir_node *bl, void *data) obstack_free(&env->obst, nodes); /* Keep the last stack state in the block by tying it to Keep node */ - nodes[0] = curr_sp; - keep = be_new_Keep(env->isa->sp->reg_class, get_irn_irg(bl), bl, 1, nodes); - pmap_insert(env->keep_map, bl, keep); + if(curr_sp != env->init_sp) { + nodes[0] = curr_sp; + keep = be_new_Keep(env->isa->sp->reg_class, get_irn_irg(bl), + bl, 1, nodes); + pmap_insert(env->keep_map, bl, keep); + } } set_irn_link(bl, curr_sp); @@ -1429,11 +1472,9 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl, i */ stack = be_abi_reg_map_get(env->regs, isa->sp); if (keep) { - ir_node *bad = new_r_Bad(env->birg->irg); stack = get_irn_n(keep, 0); - set_nodes_block(keep, bad); - set_irn_n(keep, 0, bad); - // exchange(keep, new_r_Bad(env->birg->irg)); + be_kill_node(keep); + remove_End_keepalive(get_irg_end(env->birg->irg), keep); } /* Insert results for Return into the register map. */ @@ -1875,13 +1916,14 @@ static void modify_irg(be_abi_irg_t *env) if(arg_proj != NULL) { be_abi_call_arg_t *arg; ir_type *param_type; - int nr = get_Proj_proj(arg_proj); + int nr = get_Proj_proj(arg_proj); + ir_mode *mode; nr = MIN(nr, n_params); arg = get_call_arg(call, 0, nr); param_type = get_method_param_type(method_type, nr); - if(arg->in_reg) { + if (arg->in_reg) { repl = pmap_get(env->regs, (void *) arg->reg); } @@ -1894,14 +1936,21 @@ static void modify_irg(be_abi_irg_t *env) } /* The stack parameter is not primitive (it is a struct or array), - we thus will create a node representing the parameter's address - on the stack. */ + we thus will create a node representing the parameter's address + on the stack. */ else { repl = be_new_FrameAddr(sp->reg_class, irg, reg_params_bl, frame_pointer, arg->stack_ent); } } assert(repl != NULL); + + /* Beware: the mode of the register parameters is always the mode of the register class + which may be wrong. Add Conv's then. */ + mode = get_irn_mode(args[i]); + if (mode != get_irn_mode(repl)) { + repl = new_r_Conv(irg, get_irn_n(repl, -1), repl, mode); + } exchange(args[i], repl); } }