From: Christian Würdig Date: Wed, 26 Oct 2005 13:55:23 +0000 (+0000) Subject: added gen of new ops X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=a25caa3c63cb30f9bac650056b8e301a2dc1b12a;p=libfirm added gen of new ops changed structure of main driver --- diff --git a/ir/be/ia32/transform.c b/ir/be/ia32/transform.c index e295693b2..20ca4cf57 100644 --- a/ir/be/ia32/transform.c +++ b/ir/be/ia32/transform.c @@ -1,117 +1,579 @@ -#include +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "irnode_t.h" +#include "irgraph_t.h" +#include "irmode_t.h" +#include "irgmod.h" +#include "dbginfo.h" +#include "irop_t.h" +#include "debug.h" #include "../firm2arch_nodes_attr.h" +#include "../bearch_firm.h" #include "transform.h" #include "new_nodes.h" -void transform_node(ir_node *node, void *env) { - ir_mode *mode = get_irn_mode(node); - opcode code = get_irn_opcode(node); - ir_node *op1 = NULL; - ir_node *op2 = NULL; - ir_node *asm_op = NULL; - ir_node *const_op = NULL; +/* determine if one operator is an Imm */ +ir_node *get_immediate_op(ir_node *op1, ir_node *op2) { + if (op1) + return is_Imm(op1) ? op1 : (is_Imm(op2) ? op2 : NULL); + else return is_Imm(op2) ? op2 : NULL; +} + +/* determine if one operator is not an Imm */ +ir_node *get_expr_op(ir_node *op1, ir_node *op2) { + return !is_Imm(op1) ? op1 : (!is_Imm(op2) ? op2 : NULL); +} + + + +/** + * Creates an ia32 Add with immediate. + * + * @param dbg firm dbg + * @param block the block the new node should belong to + * @param expr_op operator + * @param mode node mode + * @return the created ia23 Add_i node + */ +ir_node *gen_imm_Add(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) { + return new_rd_ia32_Add_i(dbg, current_ir_graph, block, expr_op, mode); +} + +/** + * Creates an ia32 Add. + * + * @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 ia32 Add node + */ +ir_node *gen_Add(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) { + return new_rd_ia32_Add(dbg, current_ir_graph, block, op1, op2, mode); +} + + + +/** + * Creates an ia32 Mul with immediate. + * + * @param dbg firm dbg + * @param block the block the new node should belong to + * @param expr_op operator + * @param mode node mode + * @return the created ia23 Mul_i node + */ +ir_node *gen_imm_Mul(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) { + return new_rd_ia32_Mul_i(dbg, current_ir_graph, block, expr_op, mode); +} + +/** + * Creates an ia32 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 ia32 Mul node + */ +ir_node *gen_Mul(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) { + return new_rd_ia32_Mul(dbg, current_ir_graph, block, op1, op2, mode); +} + + + +/** + * Creates an ia32 And with immediate. + * + * @param dbg firm dbg + * @param block the block the new node should belong to + * @param expr_op operator + * @param mode node mode + * @return the created ia23 And_i node + */ +ir_node *gen_imm_And(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) { + return new_rd_ia32_And_i(dbg, current_ir_graph, block, expr_op, mode); +} + +/** + * Creates an ia32 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 ia32 And node + */ +ir_node *gen_And(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) { + return new_rd_ia32_And(dbg, current_ir_graph, block, op1, op2, mode); +} + + + +/** + * Creates an ia32 Or with immediate. + * + * @param dbg firm dbg + * @param block the block the new node should belong to + * @param expr_op operator + * @param mode node mode + * @return the created ia23 Or_i node + */ +ir_node *gen_imm_Or(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) { + return new_rd_ia32_Or_i(dbg, current_ir_graph, block, expr_op, mode); +} + +/** + * Creates an ia32 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 ia32 Or node + */ +ir_node *gen_Or(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) { + return new_rd_ia32_Or(dbg, current_ir_graph, block, op1, op2, mode); +} + + + +/** + * Creates an ia32 Eor with immediate. + * + * @param dbg firm dbg + * @param block the block the new node should belong to + * @param expr_op operator + * @param mode node mode + * @return the created ia23 Eor_i node + */ +ir_node *gen_imm_Eor(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) { + return new_rd_ia32_Eor_i(dbg, current_ir_graph, block, expr_op, mode); +} + +/** + * Creates an ia32 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 ia32 Eor node + */ +ir_node *gen_Eor(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) { + return new_rd_ia32_Eor(dbg, current_ir_graph, block, op1, op2, mode); +} + + + +/** + * Creates an ia32 Cmp with immediate. + * + * @param dbg firm dbg + * @param block the block the new node should belong to + * @param expr_op operator + * @param mode node mode + * @return the created ia23 Cmp_i node + */ +ir_node *gen_imm_Cmp(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) { + return new_rd_ia32_Cmp_i(dbg, current_ir_graph, block, expr_op, mode); +} + +/** + * Creates an ia32 Cmp. + * + * @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 ia32 Cmp node + */ +ir_node *gen_Cmp(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) { + return new_rd_ia32_Cmp(dbg, current_ir_graph, block, op1, op2, mode); +} + + + +/** + * Creates an ia32 Sub with immediate. + * + * @param dbg firm dbg + * @param block the block the new node should belong to + * @param expr_op operator + * @param mode node mode + * @return the created ia23 Sub_i node + */ +ir_node *gen_imm_Sub(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) { + return new_rd_ia32_Sub_i(dbg, current_ir_graph, block, expr_op, mode); +} + +/** + * Creates an ia32 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 ia32 Sub node + */ +ir_node *gen_Sub(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) { + return new_rd_ia32_Sub(dbg, current_ir_graph, block, op1, op2, mode); +} + + + +/** + * Creates an ia32 Mod with immediate. + * + * @param dbg firm dbg + * @param block the block the new node should belong to + * @param expr_op operator + * @param mode node mode + * @return the created ia23 Mod_i node + */ +ir_node *gen_imm_Mod(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) { + return new_rd_ia32_Mod_i(dbg, current_ir_graph, block, expr_op, mode); +} + +/** + * Creates an ia32 Mod. + * + * @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 ia32 Mod node + */ +ir_node *gen_Mod(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) { + return new_rd_ia32_Mod(dbg, current_ir_graph, block, op1, op2, mode); +} + + + +/** + * Creates an ia32 Shl with immediate. + * + * @param dbg firm dbg + * @param block the block the new node should belong to + * @param expr_op operator + * @param mode node mode + * @return the created ia23 Shl_i node + */ +ir_node *gen_imm_Shl(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) { + return new_rd_ia32_Shl_i(dbg, current_ir_graph, block, expr_op, mode); +} + +/** + * Creates an ia32 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 ia32 Shl node + */ +ir_node *gen_Shl(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) { + return new_rd_ia32_Shl(dbg, current_ir_graph, block, op1, op2, mode); +} + + + +/** + * Creates an ia32 Shr with immediate. + * + * @param dbg firm dbg + * @param block the block the new node should belong to + * @param expr_op operator + * @param mode node mode + * @return the created ia23 Shr_i node + */ +ir_node *gen_imm_Shr(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) { + return new_rd_ia32_Shr_i(dbg, current_ir_graph, block, expr_op, mode); +} + +/** + * Creates an ia32 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 ia32 Shr node + */ +ir_node *gen_Shr(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) { + return new_rd_ia32_Shr(dbg, current_ir_graph, block, op1, op2, mode); +} + + + +/** + * Creates an ia32 Shrs with immediate. + * + * @param dbg firm dbg + * @param block the block the new node should belong to + * @param expr_op operator + * @param mode node mode + * @return the created ia23 Shrs_i node + */ +ir_node *gen_imm_Shrs(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) { + return new_rd_ia32_Shrs_i(dbg, current_ir_graph, block, expr_op, mode); +} + +/** + * Creates an ia32 Shrs. + * + * @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 ia32 Shrs node + */ +ir_node *gen_Shrs(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) { + return new_rd_ia32_Shrs(dbg, current_ir_graph, block, op1, op2, mode); +} + + + +/** + * Creates an ia32 Rot with immediate. + * + * @param dbg firm dbg + * @param block the block the new node should belong to + * @param expr_op operator + * @param mode node mode + * @return the created ia23 Rot_i node + */ +ir_node *gen_imm_Rot(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) { + return new_rd_ia32_Rot_i(dbg, current_ir_graph, block, expr_op, mode); +} + +/** + * Creates an ia32 Rot. + * + * @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 ia32 Rot node + */ +ir_node *gen_Rot(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) { + return new_rd_ia32_Rot(dbg, current_ir_graph, block, op1, op2, mode); +} + + + +/** + * Transforms a Conv node. + * + * @param mod the debug module + * @param block the block the new node should belong to + * @param node the ir Conv node + * @param op operator + * @param mode node mode + * @return the created ia32 Conv node + */ +ir_node *gen_Conv(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op, ir_mode *mode) { + return new_rd_ia32_Conv(get_irn_dbg_info(node), current_ir_graph, block, op, mode); +} + + + +/** + * Transforms commutative operations (op_Add, op_Mul, op_And, op_Or, op_Eor, op_Cmp) + * and non-commutative operations with com == 0 (op_Sub, op_Mod, op_Shl, op_Shr, op_Shrs, op_Rot) + * + * @param mod the debug module + * @param block the block node belongs to + * @param node the node to transform + * @param op1 first operator + * @param op2 second operator + * @param mode node mode + * @param com flag if op is commutative + * @return the created assembler node + */ +ir_node *gen_arith_Op(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op1, ir_node *op2, ir_mode *mode, int com) { + dbg_info *dbg = get_irn_dbg_info(node); + ir_node *imm_op = NULL; ir_node *expr_op = NULL; - opcode code_op1, code_op2; + ir_node *asm_node = NULL; - /* TODO: maybe one can transform - "Const -- Sub -- Exp" into "Exp -- Minus -- Add -- Const" - to save a register - but I'm not sure about side effects */ +#define GENOP(a) case iro_##a: asm_node = gen_##a(dbg, block, op1, op2, mode); break +#define GENOPI(a) case iro_##a: asm_node = gen_imm_##a(dbg, block, expr_op, mode); break -#define GEN(a) case iro_##a: asm_op = new_ia32_##a(op1, op2, mode); break -#define GENI(a) case iro_##a: asm_op = new_ia32_##a##_i(expr_op, mode); break + if (com) + imm_op = get_immediate_op(op1, op2); + else + imm_op = get_immediate_op(NULL, op2); - switch (code) { - /* commutative arith ops */ - case iro_Add: - case iro_Mul: - case iro_And: - case iro_Or: - case iro_Eor: - op1 = get_irn_n(node, 0); - op2 = get_irn_n(node, 1); - code_op1 = get_irn_opcode(op1); - code_op2 = get_irn_opcode(op2); - - /* determine if one operator is a Const */ - const_op = code_op1 == iro_Const ? op1 : (code_op2 == iro_Const ? op2 : NULL); - expr_op = code_op1 != iro_Const ? op1 : (code_op2 != iro_Const ? op2 : NULL); - - goto gen_asm_node; - - /* not commutative arith ops: only construct the immediate nodes - when the right operand is a Const */ - case iro_Sub: - case iro_DivMod: - case iro_Mod: - case iro_Shl: - case iro_Shr: - case iro_Shrs: - case iro_Rot: - op1 = get_irn_n(node, 0); - op2 = get_irn_n(node, 1); - code_op1 = get_irn_opcode(op1); - code_op2 = get_irn_opcode(op2); - - /* determine if the right operator is a Const */ - const_op = code_op2 == iro_Const ? op2 : NULL; - expr_op = op1; - -gen_asm_node: - assert(code_op1 != iro_Const && code_op2 != iro_Const && "Op(Const, Const) not expected!"); - if ((code_op1 == iro_Const) && (code_op2 == iro_Const)) { - printf("Ignoring %s(Const, Const)\n", get_irn_opname(node)); - return; - } + expr_op = get_expr_op(op1, op2); - if (const_op) { /* one of the operators is a Const */ - switch (code) { - GENI(Add); - GENI(Mul); - GENI(And); - GENI(Or); - GENI(Eor); - GENI(Sub); -// GENI(DivMod); - GENI(Mod); - GENI(Shl); - GENI(Shr); - GENI(Shrs); - GENI(Rot); - default: - /* ignore */ - break; - } - /* make the Const an attribute */ - asmop_attr *attr = (asmop_attr *)get_irn_generic_attr(const_op); - attr->tv = get_Const_tarval(const_op); - } - else { /* both operators need to be computed */ - switch (code) { - GEN(Add); - GEN(Mul); - GEN(And); - GEN(Or); - GEN(Eor); - GEN(Sub); -// GEN(DivMod); - GEN(Mod); - GEN(Shl); - GEN(Shr); - GEN(Shrs); - GEN(Rot); - default: - /* ignore */ - break; - } + /* TODO: Op(Imm, Imm) support */ + if (is_Imm(op1) && is_Imm(op2)) { + DBG((mod, LEVEL_1, "found unexpected %s(Imm, Imm), creating binop ... ", get_irn_opname(node))); + imm_op = NULL; + } + + DBG((mod, LEVEL_1, "(op1: %s -- op2: %s) ... ", get_irn_opname(op1), get_irn_opname(op2))); + + if (imm_op) { + imm_attr_t *attr_imm = (imm_attr_t *)get_irn_generic_attr(imm_op); + + DBG((mod, LEVEL_1, "%s with imm ... ", get_irn_opname(node))); + + /* make sure that Imm is a Const and no SymConst */ + if (attr_imm->tp == imm_Const) { + switch(get_irn_opcode(node)) { + GENOPI(Add); + GENOPI(Mul); + GENOPI(And); + GENOPI(Or); + GENOPI(Eor); + GENOPI(Cmp); + + GENOPI(Sub); + GENOPI(Mod); + GENOPI(Shl); + GENOPI(Shr); + GENOPI(Shrs); + GENOPI(Rot); + default: + assert("binop_i: THIS SHOULD NOT HAPPEN"); } - /* exchange the old firm node with the new assembler node */ - exchange(node, asm_op); - break; - default: - fprintf(stderr, "Ignoring node: %s\n", get_irn_opname(node)); - break; + /* make the Const an attribute */ + asmop_attr *attr = (asmop_attr *)get_irn_generic_attr(asm_node); + attr->tv = attr_imm->data.tv; + } /* TODO: SymConst support */ + else + goto do_binop; + } + else { +do_binop: + DBG((mod, LEVEL_1, "%s as binop ... ", get_irn_opname(node))); + + switch(get_irn_opcode(node)) { + GENOP(Add); + GENOP(Mul); + GENOP(And); + GENOP(Or); + GENOP(Eor); + GENOP(Cmp); + + GENOP(Sub); + GENOP(Mod); + GENOP(Shl); + GENOP(Shr); + GENOP(Shrs); + GENOP(Rot); + default: + assert("binop: THIS SHOULD NOT HAPPEN"); + } + } + + return asm_node; +} + + + +/** + * 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 ia32 Load node + */ +ir_node *gen_Load(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) { + return new_rd_ia32_Load(get_irn_dbg_info(node), current_ir_graph, block, get_Load_mem(node), get_Load_ptr(node), mode); +} + + + +/** + * 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 ia32 Store node + */ +ir_node *gen_Store(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) { + return new_rd_ia32_Store(get_irn_dbg_info(node), current_ir_graph, block, get_Store_mem(node), get_Store_ptr(node), get_Store_value(node), mode); +} + + + +/** + * 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 + */ +void transform_node(ir_node *node, void *env) { + firm_dbg_module_t *mod = (firm_dbg_module_t *)env; + opcode code = get_irn_opcode(node); + ir_node *asm_node = NULL; + ir_node *block; + ir_mode *mode; + + if (is_Block(node)) + return; + + block = get_nodes_block(node); + mode = get_irn_mode(node); + +#define BINOP_COM(a) case iro_##a: asm_node = gen_arith_Op(mod, block, node, get_irn_n(node, 0), get_irn_n(node, 1), mode, 1); break +#define BINOP_NCOM(a) case iro_##a: asm_node = gen_arith_Op(mod, block, node, get_irn_n(node, 0), get_irn_n(node, 1), mode, 0); break +#define UNOP(a) case iro_##a: asm_node = gen_##a(mod, block, node, get_irn_n(node, 0), mode); break +#define GEN(a) case iro_##a: asm_node = gen_##a(mod, block, node, mode); break +#define IGN(a) case iro_##a: break + + DBG((mod, LEVEL_1, "transforming node %s (%ld) ... ", get_irn_opname(node), get_irn_node_nr(node))); + + switch (code) { + BINOP_COM(Add); + BINOP_COM(Mul); + BINOP_COM(And); + BINOP_COM(Or); + BINOP_COM(Eor); + BINOP_COM(Cmp); + + BINOP_NCOM(Sub); + BINOP_NCOM(Mod); + BINOP_NCOM(Shl); + BINOP_NCOM(Shr); + BINOP_NCOM(Shrs); + BINOP_NCOM(Rot); +// BINOP_ARITH_NCOM(DivMod); + + UNOP(Conv); + GEN(Load); + GEN(Store); + } + + if (asm_node) { + exchange(node, asm_node); + DBG((mod, LEVEL_1, "created node %u\n", get_irn_node_nr(asm_node))); + } + else { + DBG((mod, LEVEL_1, "ignored\n")); } }