X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fir%2Firop.c;h=5f98506e564a2c72be340c6324b7ac2765ddd66c;hb=f736dac2478850ba2dec24c64bb9b313177ad6ec;hp=e0387db61138056a68204ae64d484b84e03c956d;hpb=8bd62b87ff0d3fdd3b5edfb5af5e5d7b246bb213;p=libfirm diff --git a/ir/ir/irop.c b/ir/ir/irop.c index e0387db61..5f98506e5 100644 --- a/ir/ir/irop.c +++ b/ir/ir/irop.c @@ -1,153 +1,283 @@ -/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe -** All rights reserved. -** -** Authors: Christian Schaefer -** -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -# include "irop_t.h" -# include "irnode_t.h" -# include "misc.h" - -ir_op *op_Block; - -ir_op *op_Start; -ir_op *op_End; -ir_op *op_Jmp; -ir_op *op_Cond; -ir_op *op_Return; -ir_op *op_Raise; - -ir_op *op_Sel; - -ir_op *op_Const; -ir_op *op_SymConst; - -ir_op *op_Call; -ir_op *op_Add; -ir_op *op_Sub; -ir_op *op_Minus; -ir_op *op_Mul; -ir_op *op_Quot; -ir_op *op_DivMod; -ir_op *op_Div; -ir_op *op_Mod; -ir_op *op_Abs; -ir_op *op_And; -ir_op *op_Or; -ir_op *op_Eor; -ir_op *op_Not; -ir_op *op_Cmp; -ir_op *op_Shl; -ir_op *op_Shr; -ir_op *op_Shrs; -ir_op *op_Rot; -ir_op *op_Conv; - -ir_op *op_Phi; - -ir_op *op_Load; -ir_op *op_Store; -ir_op *op_Alloc; -ir_op *op_Free; -ir_op *op_Sync; - -ir_op *op_Tuple; -ir_op *op_Proj; -ir_op *op_Id; -ir_op *op_Bad; - - -ir_op * -new_ir_op (opcode code, ident *name, size_t attr_size, int labeled) -{ - ir_op *res; - - res = (ir_op *) xmalloc (sizeof (ir_op)); - res->code = code; - res->name = name; - res->attr_size = attr_size; - res->labeled = labeled; /* For vcg dumping. - Set labeled = 1 if the edges should be - enumarated in vcg output, otherwise set - labeled = 0. */ - return res; +/* + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. + * + * This file is part of libFirm. + * + * This file may be distributed and/or modified under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation and appearing in the file LICENSE.GPL included in the + * packaging of this file. + * + * Licensees holding valid libFirm Professional Edition licenses may use + * this file in accordance with the libFirm Commercial License. + * Agreement provided with the Software. + * + * 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 Representation of opcode of intermediate operation. + * @author Christian Schaefer, Goetz Lindenmaier, Michael Beck + * @version $Id$ + */ +#include "config.h" + +#include + +#include "irop_t.h" +#include "irnode_t.h" +#include "irhooks.h" +#include "irbackedge_t.h" + +#include "iropt_t.h" +#include "irvrfy_t.h" +#include "reassoc_t.h" + +#include "xmalloc.h" + +void be_init_op(void); + +/** the available next opcode */ +static unsigned next_iro = iro_MaxOpcode; + +/* + * Copies all attributes stored in the old node to the new node. + * Assumes both have the same opcode and sufficient size. + */ +void default_copy_attr(ir_graph *irg, const ir_node *old_node, + ir_node *new_node) +{ + unsigned size = firm_add_node_size; + (void) irg; + + assert(get_irn_op(old_node) == get_irn_op(new_node)); + memcpy(&new_node->attr, &old_node->attr, get_op_attr_size(get_irn_op(old_node))); + + if (size > 0) { + /* copy additional node data */ + memcpy(get_irn_data(new_node, void, size), get_irn_data(old_node, void, size), size); + } } +/** + * Copies all Call attributes stored in the old node to the new node. + */ +static void call_copy_attr(ir_graph *irg, const ir_node *old_node, + ir_node *new_node) +{ + default_copy_attr(irg, old_node, new_node); + remove_Call_callee_arr(new_node); +} -void -init_op(void) -{ - op_Block = new_ir_op (iro_Block, id_from_str ("Block", 5), sizeof (block_attr), 1); - - op_Start = new_ir_op (iro_Start, id_from_str ("Start", 5), sizeof (block_attr), 1); - op_End = new_ir_op (iro_End, id_from_str ("End", 3), sizeof (block_attr), 1); - op_Jmp = new_ir_op (iro_Jmp, id_from_str ("Jmp", 3), 0, 0); - op_Cond = new_ir_op (iro_Cond, id_from_str ("Cond", 4), sizeof(cond_attr), 1); - op_Return = new_ir_op (iro_Return, id_from_str ("Return", 6), 0, 1); - op_Raise = new_ir_op (iro_Raise, id_from_str ("Raise", 5), 0, 1); - - op_Const = new_ir_op (iro_Const, id_from_str ("Const", 5), sizeof (struct tarval *), 0); - op_SymConst = new_ir_op (iro_SymConst, id_from_str ("SymConst", 8), - sizeof (symconst_attr), 0); - - op_Sel = new_ir_op (iro_Sel, id_from_str ("Sel", 3), sizeof (sel_attr), 1); - - op_Call = new_ir_op (iro_Call, id_from_str ("Call", 4), sizeof (call_attr), 1); - op_Add = new_ir_op (iro_Add, id_from_str ("Add", 3), 0, 0); - op_Minus = new_ir_op (iro_Minus, id_from_str ("Minus", 5), 0, 0); - op_Sub = new_ir_op (iro_Sub, id_from_str ("Sub", 3), 0, 1); - op_Mul = new_ir_op (iro_Mul, id_from_str ("Mul", 3), 0, 0); - op_Quot = new_ir_op (iro_Quot, id_from_str ("Quot", 4), sizeof(struct irnode **), 1); - op_DivMod = new_ir_op (iro_DivMod, id_from_str ("DivMod", 6), sizeof(struct irnode **), 1); - op_Div = new_ir_op (iro_Div, id_from_str ("Div", 3), sizeof(struct irnode **), 1); - op_Mod = new_ir_op (iro_Mod, id_from_str ("Mod", 3), sizeof(struct irnode **), 1); - op_Abs = new_ir_op (iro_Abs, id_from_str ("Abs", 3), 0, 0); - op_And = new_ir_op (iro_And, id_from_str ("And", 3), 0, 0); - op_Or = new_ir_op (iro_Or, id_from_str ("Or", 2), 0, 0); - op_Eor = new_ir_op (iro_Eor, id_from_str ("Eor", 3), 0, 0); - op_Not = new_ir_op (iro_Not, id_from_str ("Not", 3), 0, 0); - op_Cmp = new_ir_op (iro_Cmp, id_from_str ("Cmp", 3), 0, 1); - op_Shl = new_ir_op (iro_Shl, id_from_str ("Shl", 3), 0, 1); - op_Shr = new_ir_op (iro_Shr, id_from_str ("Shr", 3), 0, 1); - op_Shrs = new_ir_op (iro_Shrs, id_from_str ("Shrs", 3), 0, 0); - op_Rot = new_ir_op (iro_Rot, id_from_str ("Rot", 3), 0, 0); - op_Conv = new_ir_op (iro_Conv, id_from_str ("Conv", 4), 0, 1); - - op_Phi = new_ir_op (iro_Phi, id_from_str ("Phi", 3), sizeof (int), 1); - - op_Load = new_ir_op (iro_Load, id_from_str ("Load", 4), sizeof(struct irnode **), 1); - op_Store = new_ir_op (iro_Store, id_from_str ("Store", 5), sizeof(struct irnode **), 1); - op_Alloc = new_ir_op (iro_Alloc, id_from_str ("Alloc", 5), sizeof (alloc_attr), 1); - op_Free = new_ir_op (iro_Free, id_from_str ("Free", 4), sizeof (type *), 1); - op_Sync = new_ir_op (iro_Sync, id_from_str ("Sync", 4), 0, 0); - - op_Proj = new_ir_op (iro_Proj, id_from_str ("Proj", 4), sizeof (long), 1); - op_Tuple = new_ir_op (iro_Tuple, id_from_str ("Tuple", 5), 0, 1); - op_Id = new_ir_op (iro_Id, id_from_str ("Id", 2), 0, 0); - op_Bad = new_ir_op (iro_Bad, id_from_str ("Bad", 3), 0, 0); +/** + * Copies all Block attributes stored in the old node to the new node. + */ +static void block_copy_attr(ir_graph *irg, const ir_node *old_node, + ir_node *new_node) +{ + default_copy_attr(irg, old_node, new_node); + new_node->attr.block.irg.irg = irg; + new_node->attr.block.phis = NULL; + new_node->attr.block.cg_backedge = NULL; + new_node->attr.block.backedge = new_backedge_arr(irg->obst, get_irn_arity(new_node)); + new_node->attr.block.block_visited = 0; + memset(&new_node->attr.block.dom, 0, sizeof(new_node->attr.block.dom)); + memset(&new_node->attr.block.pdom, 0, sizeof(new_node->attr.block.pdom)); + /* TODO: we should probably create a new entity. But we somehow have to + * patch the stuff at the same time */ + new_node->attr.block.entity = NULL; + new_node->attr.block.phis = NULL; + INIT_LIST_HEAD(&new_node->attr.block.succ_head); } -/* Returns the string for the opcode. */ -const char *get_op_name (ir_op *op) { - return id_to_str(op->name); +/** + * Copies all phi attributes stored in old node to the new node + */ +static void phi_copy_attr(ir_graph *irg, const ir_node *old_node, + ir_node *new_node) +{ + default_copy_attr(irg, old_node, new_node); + new_node->attr.phi.next = NULL; + new_node->attr.phi.u.backedge = new_backedge_arr(irg->obst, get_irn_arity(new_node)); } -opcode get_op_code (ir_op *op){ - return op->code; +/** + * Copies all filter attributes stored in old node to the new node + */ +static void filter_copy_attr(ir_graph *irg, const ir_node *old_node, + ir_node *new_node) +{ + default_copy_attr(irg, old_node, new_node); + new_node->attr.filter.backedge = new_backedge_arr(irg->obst, get_irn_arity(new_node)); } -ident *get_op_ident(ir_op *op){ - return op->name; +/** + * Copies all ASM attributes stored in old node to the new node + */ +static void ASM_copy_attr(ir_graph *irg, const ir_node *old_node, + ir_node *new_node) +{ + default_copy_attr(irg, old_node, new_node); + new_node->attr.assem.input_constraints = DUP_ARR_D(ir_asm_constraint, irg->obst, old_node->attr.assem.input_constraints); + new_node->attr.assem.output_constraints = DUP_ARR_D(ir_asm_constraint, irg->obst, old_node->attr.assem.output_constraints); + new_node->attr.assem.clobbers = DUP_ARR_D(ir_asm_constraint, irg->obst, old_node->attr.assem.clobbers); } -/* returns the attribute size of the operator. */ -int get_op_attr_size (ir_op *op) { - return op->attr_size; +/** + * Sets the default copy_attr operation for an ir_ops + * + * @param code the opcode for the default operation + * @param ops the operations initialized + * + * @return + * The operations. + */ +static ir_op_ops *firm_set_default_copy_attr(ir_opcode code, ir_op_ops *ops) +{ + switch (code) { + case iro_Call: + ops->copy_attr = call_copy_attr; + break; + case iro_Block: + ops->copy_attr = block_copy_attr; + break; + case iro_Phi: + ops->copy_attr = phi_copy_attr; + break; + case iro_Filter: + ops->copy_attr = filter_copy_attr; + break; + case iro_ASM: + ops->copy_attr = ASM_copy_attr; + break; + default: + /* not allowed to be NULL */ + if (! ops->copy_attr) + ops->copy_attr = default_copy_attr; + } + return ops; +} /* firm_set_default_copy_attr */ + +/* Creates a new ir operation. */ +ir_op *new_ir_op(unsigned code, const char *name, op_pin_state p, + unsigned flags, op_arity opar, int op_index, size_t attr_size, + const ir_op_ops *ops) +{ + ir_op *res = XMALLOCZ(ir_op); + + res->code = code; + res->name = new_id_from_chars(name, strlen(name)); + res->pin_state = p; + res->attr_size = attr_size; + res->flags = flags; + res->opar = opar; + res->op_index = op_index; + res->tag = 0; + + if (ops) + memcpy(&res->ops, ops, sizeof(res->ops)); + else /* no given ops, set all operations to NULL */ + memset(&res->ops, 0, sizeof(res->ops)); + + firm_set_default_operations(code, &res->ops); + firm_set_default_copy_attr(code, &res->ops); + firm_set_default_verifyer(code, &res->ops); + firm_set_default_reassoc(code, &res->ops); + + add_irp_opcode(res); + + hook_new_ir_op(res); + return res; +} /* new_ir_op */ + +void free_ir_op(ir_op *code) +{ + hook_free_ir_op(code); + + remove_irp_opcode(code); + free(code); +} /* free_ir_op */ + +/* Returns the string for the opcode. */ +const char *get_op_name (const ir_op *op) +{ + return get_id_str(op->name); +} /* get_op_name */ + +unsigned (get_op_code)(const ir_op *op) +{ + return _get_op_code(op); +} /* get_op_code */ + +ident *(get_op_ident)(const ir_op *op) +{ + return _get_op_ident(op); +} /* get_op_ident */ + +const char *get_op_pin_state_name(op_pin_state s) +{ + switch (s) { +#define XXX(s) case s: return #s + XXX(op_pin_state_floats); + XXX(op_pin_state_pinned); + XXX(op_pin_state_exc_pinned); + XXX(op_pin_state_mem_pinned); +#undef XXX + } + return ""; +} /* get_op_pin_state_name */ + +op_pin_state (get_op_pinned)(const ir_op *op) +{ + return _get_op_pinned(op); +} /* get_op_pinned */ + +/* Sets op_pin_state_pinned in the opcode. Setting it to floating has no effect + for Phi, Block and control flow nodes. */ +void set_op_pinned(ir_op *op, op_pin_state pinned) +{ + if (op == op_Block || op == op_Phi || is_op_cfopcode(op)) return; + op->pin_state = pinned; +} /* set_op_pinned */ + +/* retrieve the next free opcode */ +unsigned get_next_ir_opcode(void) +{ + return next_iro++; +} /* get_next_ir_opcode */ + +/* Returns the next free n IR opcode number, allows to register a bunch of user ops */ +unsigned get_next_ir_opcodes(unsigned num) +{ + unsigned base = next_iro; + next_iro += num; + return base; +} /* get_next_ir_opcodes */ + +/* Returns the generic function pointer from an ir operation. */ +op_func (get_generic_function_ptr)(const ir_op *op) +{ + return _get_generic_function_ptr(op); +} /* get_generic_function_ptr */ + +/* Store a generic function pointer into an ir operation. */ +void (set_generic_function_ptr)(ir_op *op, op_func func) +{ + _set_generic_function_ptr(op, func); +} /* set_generic_function_ptr */ + +/* Returns the ir_op_ops of an ir_op. */ +const ir_op_ops *(get_op_ops)(const ir_op *op) +{ + return _get_op_ops(op); +} /* get_op_ops */ + +irop_flags get_op_flags(const ir_op *op) +{ + return op->flags; } + +#include "gen_irop.c.inl"