X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2FTEMPLATE%2FTEMPLATE_transform.c;h=7a8b7e02e26f077407a68de4c721c27eacdb4aaa;hb=81191be9419f49c1338f460dd7cd180197aa46d5;hp=34a7f5ef3de863ba5ecc0c771537107b16e0e42d;hpb=1b1a0f1d75893ea203c8c0911e7d787a623d640d;p=libfirm diff --git a/ir/be/TEMPLATE/TEMPLATE_transform.c b/ir/be/TEMPLATE/TEMPLATE_transform.c index 34a7f5ef3..7a8b7e02e 100644 --- a/ir/be/TEMPLATE/TEMPLATE_transform.c +++ b/ir/be/TEMPLATE/TEMPLATE_transform.c @@ -20,7 +20,6 @@ /** * @file * @brief code selection (transform FIRM into TEMPLATE FIRM) - * @version $Id$ */ #include "config.h" @@ -29,387 +28,310 @@ #include "irmode_t.h" #include "irgmod.h" #include "iredges.h" -#include "irvrfy.h" #include "ircons.h" #include "iropt_t.h" #include "debug.h" +#include "error.h" -#include "../benode_t.h" +#include "benode.h" +#include "betranshlp.h" #include "bearch_TEMPLATE_t.h" #include "TEMPLATE_nodes_attr.h" #include "TEMPLATE_transform.h" #include "TEMPLATE_new_nodes.h" -#include "TEMPLATE_map_regs.h" #include "gen_TEMPLATE_regalloc_if.h" -extern ir_op *get_op_Mulh(void); +DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;) +typedef ir_node* (*new_binop_func)(dbg_info *dbgi, ir_node *block, + ir_node *left, ir_node *right); +static ir_mode *gp_regs_mode; -/**************************************************************************************************** - * _ _ __ _ _ - * | | | | / _| | | (_) - * _ __ ___ __| | ___ | |_ _ __ __ _ _ __ ___| |_ ___ _ __ _ __ ___ __ _| |_ _ ___ _ __ - * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __| _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \ - * | | | | (_) | (_| | __/ | |_| | | (_| | | | \__ \ || (_) | | | | | | | | (_| | |_| | (_) | | | | - * |_| |_|\___/ \__,_|\___| \__|_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_| - * - ****************************************************************************************************/ +static ir_node *transform_binop(ir_node *node, new_binop_func new_func) +{ + ir_node *block = get_nodes_block(node); + ir_node *new_block = be_transform_node(block); + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *left = get_binop_left(node); + ir_node *new_left = be_transform_node(left); + ir_node *right = get_binop_right(node); + ir_node *new_right = be_transform_node(right); -/** - * Creates an TEMPLATE Add. - * - * @param env The transformation environment - * @param op1 first operator - * @param op2 second operator - * @return the created TEMPLATE Add node - */ -static ir_node *gen_Add(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_bd_TEMPLATE_Add(env->dbg, env->block, op1, op2, env->mode); + return new_func(dbgi, new_block, new_left, new_right); } +static ir_node *gen_And(ir_node *node) +{ + return transform_binop(node, new_bd_TEMPLATE_And); +} - -/** - * Creates an TEMPLATE Mul. - * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created TEMPLATE Mul node - */ -static ir_node *gen_Mul(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) { - if (mode_is_float(env->mode)) { - return new_bd_TEMPLATE_fMul(env->dbg, env->block, op1, op2, env->mode); - } - else { - return new_bd_TEMPLATE_Mul(env->dbg, env->block, op1, op2, env->mode); - } +static ir_node *gen_Or(ir_node *node) +{ + return transform_binop(node, new_bd_TEMPLATE_Or); } +static ir_node *gen_Eor(ir_node *node) +{ + return transform_binop(node, new_bd_TEMPLATE_Xor); +} +static ir_node *gen_Div(ir_node *node) +{ + ir_mode *mode = get_Div_resmode(node); + assert(mode_is_float(mode)); + return transform_binop(node, new_bd_TEMPLATE_fDiv); +} -/** - * Creates an TEMPLATE And. - * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created TEMPLATE And node - */ -static ir_node *gen_And(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_bd_TEMPLATE_And(env->dbg, env->block, op1, op2, env->mode); +static ir_node *gen_Shl(ir_node *node) +{ + ir_mode *mode = get_irn_mode(node); + if (get_mode_modulo_shift(mode) != 32) + panic("modulo shift!=32 not supported"); + return transform_binop(node, new_bd_TEMPLATE_Shl); } +static ir_node *gen_Shr(ir_node *node) +{ + ir_mode *mode = get_irn_mode(node); + if (get_mode_modulo_shift(mode) != 32) + panic("modulo shift!=32 not supported"); + return transform_binop(node, new_bd_TEMPLATE_Shr); +} +static ir_node *gen_Add(ir_node *node) +{ + ir_mode *mode = get_irn_mode(node); -/** - * Creates an TEMPLATE Or. - * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created TEMPLATE Or node - */ -static ir_node *gen_Or(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_bd_TEMPLATE_Or(env->dbg, env->block, op1, op2, env->mode); + if (mode_is_float(mode)) { + return transform_binop(node, new_bd_TEMPLATE_fAdd); + } + return transform_binop(node, new_bd_TEMPLATE_Add); } +static ir_node *gen_Sub(ir_node *node) +{ + ir_mode *mode = get_irn_mode(node); - -/** - * Creates an TEMPLATE Eor. - * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created TEMPLATE Eor node - */ -static ir_node *gen_Eor(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_bd_TEMPLATE_Eor(env->dbg, env->block, op1, op2, env->mode); + if (mode_is_float(mode)) { + return transform_binop(node, new_bd_TEMPLATE_fSub); + } + return transform_binop(node, new_bd_TEMPLATE_Sub); } +static ir_node *gen_Mul(ir_node *node) +{ + ir_mode *mode = get_irn_mode(node); - -/** - * Creates an TEMPLATE Sub. - * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created TEMPLATE Sub node - */ -static ir_node *gen_Sub(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) { - if (mode_is_float(env->mode)) { - return new_bd_TEMPLATE_fSub(env->dbg, env->block, op1, op2, env->mode); - } - else { - return new_bd_TEMPLATE_Sub(env->dbg, env->block, op1, op2, env->mode); + if (mode_is_float(mode)) { + return transform_binop(node, new_bd_TEMPLATE_fMul); } + return transform_binop(node, new_bd_TEMPLATE_Mul); } +typedef ir_node* (*new_unop_func)(dbg_info *dbgi, ir_node *block, ir_node *op); -/** - * Creates an TEMPLATE floating Div. - * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created TEMPLATE fDiv node - */ -static ir_node *gen_Quot(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_bd_TEMPLATE_fDiv(env->dbg, env->block, op1, op2, env->mode); +static ir_node *transform_unop(ir_node *node, new_unop_func new_func) +{ + ir_node *block = get_nodes_block(node); + ir_node *new_block = be_transform_node(block); + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *op = get_unop_op(node); + ir_node *new_op = be_transform_node(op); + + return new_func(dbgi, new_block, new_op); } +static ir_node *gen_Minus(ir_node *node) +{ + ir_mode *mode = get_irn_mode(node); + if (mode_is_float(mode)) { + return transform_unop(node, new_bd_TEMPLATE_fMinus); + } + return transform_unop(node, new_bd_TEMPLATE_Minus); +} -/** - * Creates an TEMPLATE Shl. - * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created TEMPLATE Shl node - */ -static ir_node *gen_Shl(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_bd_TEMPLATE_Shl(env->dbg, env->block, op1, op2, env->mode); +static ir_node *gen_Not(ir_node *node) +{ + return transform_unop(node, new_bd_TEMPLATE_Not); } +static ir_node *gen_Const(ir_node *node) +{ + ir_node *block = get_nodes_block(node); + ir_node *new_block = be_transform_node(block); + dbg_info *dbgi = get_irn_dbg_info(node); + ir_tarval *value = get_Const_tarval(node); + ir_node *result; + result = new_bd_TEMPLATE_Const(dbgi, new_block, value); -/** - * Creates an TEMPLATE Shr. - * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created TEMPLATE Shr node - */ -static ir_node *gen_Shr(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_bd_TEMPLATE_Shr(env->dbg, env->block, op1, op2, env->mode); + return result; } - - -/** - * Transforms a Minus node. - * - * @param mod the debug module - * @param block the block the new node should belong to - * @param node the ir Minus node - * @param op operator - * @param mode node mode - * @return the created TEMPLATE Minus node - */ -static ir_node *gen_Minus(TEMPLATE_transform_env_t *env, ir_node *op) { - if (mode_is_float(env->mode)) { - return new_bd_TEMPLATE_fMinus(env->dbg, env->block, op, env->mode); +static ir_node *gen_Load(ir_node *node) +{ + ir_node *block = get_nodes_block(node); + ir_node *new_block = be_transform_node(block); + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *ptr = get_Load_ptr(node); + ir_node *new_ptr = be_transform_node(ptr); + ir_node *mem = get_Load_mem(node); + ir_node *new_mem = be_transform_node(mem); + ir_mode *mode = get_irn_mode(node); + + if (mode_is_float(mode)) { + return new_bd_TEMPLATE_fLoad(dbgi, new_block, new_ptr, new_mem, mode); } - return new_bd_TEMPLATE_Minus(env->dbg, env->block, op, env->mode); + return new_bd_TEMPLATE_Load(dbgi, new_block, new_ptr, new_mem, mode); } - - -/** - * Transforms a Not node. - * - * @param mod the debug module - * @param block the block the new node should belong to - * @param node the ir Not node - * @param op operator - * @param mode node mode - * @return the created TEMPLATE Not node - */ -static ir_node *gen_Not(TEMPLATE_transform_env_t *env, ir_node *op) { - return new_bd_TEMPLATE_Not(env->dbg, env->block, op, env->mode); +static ir_node *gen_Store(ir_node *node) +{ + ir_node *block = get_nodes_block(node); + ir_node *new_block = be_transform_node(block); + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *ptr = get_Store_ptr(node); + ir_node *new_ptr = be_transform_node(ptr); + ir_node *val = get_Store_value(node); + ir_node *new_val = be_transform_node(val); + ir_node *mem = get_Store_mem(node); + ir_node *new_mem = be_transform_node(mem); + ir_mode *mode = get_irn_mode(node); + + if (mode_is_float(mode)) { + return new_bd_TEMPLATE_fStore(dbgi, new_block, new_ptr, new_val, new_mem, mode); + } + return new_bd_TEMPLATE_Store(dbgi, new_block, new_ptr, new_mem, new_val, mode); } +static ir_node *gen_Jmp(ir_node *node) +{ + ir_node *block = get_nodes_block(node); + ir_node *new_block = be_transform_node(block); + dbg_info *dbgi = get_irn_dbg_info(node); + return new_bd_TEMPLATE_Jmp(dbgi, new_block); +} -/** - * Transforms a Load. - * - * @param mod the debug module - * @param block the block the new node should belong to - * @param node the ir Load node - * @param mode node mode - * @return the created TEMPLATE Load node - */ -static ir_node *gen_Load(TEMPLATE_transform_env_t *env) { - ir_node *node = env->irn; +static ir_node *gen_Start(ir_node *node) +{ + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = get_nodes_block(node); + ir_node *new_block = be_transform_node(block); - if (mode_is_float(env->mode)) { - return new_bd_TEMPLATE_fLoad(env->dbg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode); - } - return new_bd_TEMPLATE_Load(env->dbg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode); + return new_bd_TEMPLATE_Start(dbgi, new_block); } - +static ir_node *gen_Return(ir_node *node) +{ + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = get_nodes_block(node); + ir_node *new_block = be_transform_node(block); + ir_node *mem = get_Return_mem(node); + ir_node *new_mem = be_transform_node(mem); + ir_graph *irg = get_irn_irg(node); + ir_node *sp = get_irg_frame(irg); + + return new_bd_TEMPLATE_Return(dbgi, new_block, sp, new_mem); +} /** - * Transforms a Store. - * - * @param mod the debug module - * @param block the block the new node should belong to - * @param node the ir Store node - * @param mode node mode - * @return the created TEMPLATE Store node + * returns true if mode should be stored in a general purpose register */ -static ir_node *gen_Store(TEMPLATE_transform_env_t *env) { - ir_node *node = env->irn; +static inline bool mode_needs_gp_reg(ir_mode *mode) +{ + return mode_is_int(mode) || mode_is_reference(mode); +} - if (mode_is_float(env->mode)) { - return new_bd_TEMPLATE_fStore(env->dbg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode); +static ir_node *gen_Phi(ir_node *node) +{ + ir_mode *mode = get_irn_mode(node); + const arch_register_req_t *req; + if (mode_needs_gp_reg(mode)) { + mode = mode_Iu; + req = TEMPLATE_reg_classes[CLASS_TEMPLATE_gp].class_req; + } else { + req = arch_no_register_req; } - return new_bd_TEMPLATE_Store(env->dbg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode); -} + return be_transform_phi(node, req); +} +static ir_node *gen_Proj_Start(ir_node *node) +{ + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = get_nodes_block(node); + ir_node *new_block = be_transform_node(block); + ir_node *start = get_Proj_pred(node); + ir_node *new_start = be_transform_node(start); + long pn = get_Proj_proj(node); + + switch ((pn_Start) pn) { + case pn_Start_X_initial_exec: + return new_bd_TEMPLATE_Jmp(dbgi, new_block); + case pn_Start_M: + return new_rd_Proj(dbgi, new_start, mode_M, pn_TEMPLATE_Start_M); + case pn_Start_T_args: + return new_r_Bad(get_irn_irg(block), mode_T); + case pn_Start_P_frame_base: + return new_rd_Proj(dbgi, new_start, gp_regs_mode, pn_TEMPLATE_Start_stack); + } + panic("unexpected Start proj %ld\n", pn); +} -/********************************************************* - * _ _ _ - * (_) | | (_) - * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __ - * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__| - * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ | - * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_| - * - *********************************************************/ +static ir_node *gen_Proj(ir_node *node) +{ + ir_node *pred = get_Proj_pred(node); + switch (get_irn_opcode(pred)) { + case iro_Start: return gen_Proj_Start(node); + default: + panic("code selection can't handle Proj after %+F\n", pred); + } +} +static void TEMPLATE_register_transformers(void) +{ + be_start_transform_setup(); + + be_set_transform_function(op_Add, gen_Add); + be_set_transform_function(op_And, gen_And); + be_set_transform_function(op_Const, gen_Const); + be_set_transform_function(op_Div, gen_Div); + be_set_transform_function(op_Eor, gen_Eor); + be_set_transform_function(op_Jmp, gen_Jmp); + be_set_transform_function(op_Load, gen_Load); + be_set_transform_function(op_Minus, gen_Minus); + be_set_transform_function(op_Mul, gen_Mul); + be_set_transform_function(op_Not, gen_Not); + be_set_transform_function(op_Or, gen_Or); + be_set_transform_function(op_Proj, gen_Proj); + be_set_transform_function(op_Phi, gen_Phi); + be_set_transform_function(op_Return, gen_Return); + be_set_transform_function(op_Shl, gen_Shl); + be_set_transform_function(op_Shr, gen_Shr); + be_set_transform_function(op_Start, gen_Start); + be_set_transform_function(op_Store, gen_Store); + be_set_transform_function(op_Sub, gen_Sub); +} /** - * Transforms the given firm node (and maybe some other related nodes) - * into one or more assembler nodes. - * - * @param node the firm node - * @param env the debug module + * Transform generic IR-nodes into TEMPLATE machine instructions */ -void TEMPLATE_transform_node(ir_node *node, void *env) { -#ifdef DEBUG_libfirm - TEMPLATE_code_gen_t *cgenv = (TEMPLATE_code_gen_t *)env; -#endif - ir_opcode code = get_irn_opcode(node); - ir_node *asm_node = NULL; - TEMPLATE_transform_env_t tenv; - (void) env; - - if (is_Block(node)) - return; - - tenv.block = get_nodes_block(node); - tenv.dbg = get_irn_dbg_info(node); - tenv.irg = current_ir_graph; - tenv.irn = node; -#ifdef DEBUG_libfirm - tenv.mod = cgenv->mod; -#endif - tenv.mode = get_irn_mode(node); - -#define UNOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break -#define BINOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_left(node), get_##a##_right(node)); break -#define GEN(a) case iro_##a: asm_node = gen_##a(&tenv); break -#define IGN(a) case iro_##a: break -#define BAD(a) case iro_##a: goto bad - - DBG((tenv.mod, LEVEL_1, "check %+F ... ", node)); - - switch (code) { - BINOP(Add); - BINOP(Mul); - BINOP(And); - BINOP(Or); - BINOP(Eor); - - BINOP(Sub); - BINOP(Shl); - BINOP(Shr); - BINOP(Quot); - - - UNOP(Minus); - UNOP(Not); - - GEN(Load); - GEN(Store); - - /* TODO: implement these nodes */ - IGN(Shrs); - IGN(Div); - IGN(Mod); - IGN(DivMod); - IGN(Const); - IGN(SymConst); - IGN(Conv); - IGN(Abs); - IGN(Cond); - IGN(Mux); - IGN(Mulh); - IGN(CopyB); - IGN(Unknown); - IGN(Cmp); - - /* You probably don't need to handle the following nodes */ - - IGN(Call); - IGN(Proj); - IGN(Alloc); - - IGN(Block); - IGN(Start); - IGN(End); - IGN(NoMem); - IGN(Phi); - IGN(IJmp); - IGN(Jmp); - IGN(Break); - IGN(Sync); - - BAD(Raise); - BAD(Sel); - BAD(InstOf); - BAD(Cast); - BAD(Free); - BAD(Tuple); - BAD(Id); - BAD(Bad); - BAD(Confirm); - BAD(Filter); - BAD(CallBegin); - BAD(EndReg); - BAD(EndExcept); - - default: - break; -bad: - fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node)); - assert(0); - } +void TEMPLATE_transform_graph(ir_graph *irg) +{ + gp_regs_mode = TEMPLATE_reg_classes[CLASS_TEMPLATE_gp].mode; - if (asm_node) { - exchange(node, asm_node); - DB((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node)); - } - else { - DB((tenv.mod, LEVEL_1, "ignored\n")); - } + TEMPLATE_register_transformers(); + be_transform_graph(irg, NULL); +} + +void TEMPLATE_init_transform(void) +{ + FIRM_DBG_REGISTER(dbg, "firm.be.TEMPLATE.transform"); }