consolidate utility macros in util.h
[libfirm] / ir / common / irtools.c
index 1e3e9ef..7ff3994 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
+ * Copyright (C) 1995-2011 University of Karlsruhe.  All right reserved.
  *
  * This file is part of libFirm.
  *
 #include "irbackedge_t.h"
 #include "irtools.h"
 #include "irprintf.h"
+#include "irpass_t.h"
+#include "iropt_t.h"
 
-/* the famous clear_link implementation. */
-void firm_clear_link(ir_node *n, void *env) {
+void firm_clear_link(ir_node *n, void *env)
+{
        (void) env;
        set_irn_link(n, NULL);
 }
 
-/*
- * Copies a node to a new irg. The Ins of the new node point to
- * the predecessors on the old irg.  n->link points to the new node.
- *
- * Does NOT copy standard nodes like Start, End etc that are fixed
- * in an irg. Instead, the corresponding nodes of the new irg are returned.
- * Note further, that the new nodes have no block.
- */
-void
-copy_irn_to_irg(ir_node *n, ir_graph *irg) {
+void firm_clear_node_and_phi_links(ir_node *n, void *env)
+{
+       (void) env;
+       set_irn_link(n, NULL);
+       if (is_Block(n))
+               set_Block_phis(n, NULL);
+       else if (is_Phi(n))
+               set_Phi_next(n, NULL);
+}
+
+void firm_clear_block_phis(ir_node *node, void *env)
+{
+       (void) env;
+       if (is_Block(node)) {
+               set_Block_phis(node, NULL);
+       } else if (is_Phi(node)) {
+               set_Phi_next(node, NULL);
+       }
+}
+
+void firm_collect_block_phis(ir_node *node, void *env)
+{
+       (void) env;
+       if (is_Phi(node))
+               add_Block_phi(get_nodes_block(node), node);
+}
+
+void copy_irn_to_irg(ir_node *n, ir_graph *irg)
+{
        ir_op *op = get_irn_op(n);
        ir_graph *old_irg;
        ir_node *nn = NULL;
 
        /* do not copy standard nodes */
-       if (op == op_Bad)
-               nn = get_irg_bad(irg);
-       else if (op == op_NoMem)
+       if (op == op_NoMem)
                n = get_irg_no_mem(irg);
        else if (op == op_Block) {
                old_irg = get_irn_irg(n);
@@ -100,58 +119,94 @@ copy_irn_to_irg(ir_node *n, ir_graph *irg) {
        /* Copy the attributes.  These might point to additional data.  If this
           was allocated on the old obstack the pointers now are dangling.  This
           frees e.g. the memory of the graph_arr allocated in new_immBlock. */
-       copy_node_attr(n, nn);
-       new_backedge_info(nn);
+       copy_node_attr(irg, n, nn);
        set_irn_link(n, nn);
 
-       /* fix the irg for blocks */
-       if (is_Block(nn)) {
-               nn->attr.block.irg = irg;
+       /* fix the irg for nodes containing a reference to it */
+       if (ir_has_irg_ref(nn)) {
+               nn->attr.block.irg.irg = irg;
+       }
+}
 
-               /* we cannot allow blocks WITHOUT macroblock input */
-               set_Block_MacroBlock(nn, get_Block_MacroBlock(n));
+ir_node *irn_copy_into_irg(const ir_node *node, ir_graph *irg)
+{
+       ir_node  *block = NULL;
+       ir_op    *op    = get_irn_op(node);
+       int       arity = get_irn_arity(node);
+       dbg_info *dbgi  = get_irn_dbg_info(node);
+       ir_mode  *mode  = get_irn_mode(node);
+       ir_node  *res;
+       int       n_deps;
+       int       i;
+
+       if (op != op_Block)
+               block = get_nodes_block(node);
+
+       if (op->opar == oparity_dynamic) {
+               int i;
+               res = new_ir_node(dbgi, irg, block, op, mode, -1, NULL);
+               for (i = 0; i < arity; ++i) {
+                       ir_node *in = get_irn_n(node, i);
+                       add_irn_n(res, in);
+               }
+       } else {
+               ir_node **ins = get_irn_in(node)+1;
+               res = new_ir_node(dbgi, irg, block, op, mode, arity, ins);
        }
+
+       /* copy the attributes */
+       copy_node_attr(irg, node, res);
+
+       /* duplicate dependency edges */
+       n_deps = get_irn_deps(node);
+       for (i = 0; i < n_deps; ++i) {
+               ir_node *dep = get_irn_dep(node, i);
+               add_irn_dep(res, dep);
+       }
+
+       return res;
 }
 
-/*
- * Creates an exact copy of a node.
- * The copy resides in the same graph in the same block.
- */
-ir_node *exact_copy(const ir_node *n) {
-       ir_graph *irg = get_irn_irg(n);
-       ir_node *res, *block = NULL;
+ir_node *exact_copy(const ir_node *node)
+{
+       return irn_copy_into_irg(node, get_irn_irg(node));
+}
 
-       if (is_no_Block(n))
-               block = get_nodes_block(n);
+static ir_node *get_new_node(const ir_node *old_node)
+{
+       return (ir_node*) get_irn_link(old_node);
+}
 
-       res = new_ir_node(get_irn_dbg_info(n),
-               irg,
-               block,
-               get_irn_op(n),
-               get_irn_mode(n),
-               get_irn_arity(n),
-               get_irn_in(n) + 1);
+void irn_rewire_inputs(ir_node *node)
+{
+       ir_node *new_node;
+       int      arity;
+       int      i;
 
+       new_node = get_new_node(node);
 
-       /* Copy the attributes.  These might point to additional data.  If this
-          was allocated on the old obstack the pointers now are dangling.  This
-          frees e.g. the memory of the graph_arr allocated in new_immBlock. */
-       copy_node_attr(n, res);
-       new_backedge_info(res);
+       if (!is_Block(node)) {
+               ir_node *block     = get_nodes_block(node);
+               ir_node *new_block = get_new_node(block);
+               set_nodes_block(new_node, new_block);
+       }
 
-       if (is_Block(n)) {
-               set_Block_MacroBlock(res, get_Block_MacroBlock(n));
+       arity = get_irn_arity(new_node);
+       for (i = 0; i < arity; ++i) {
+               ir_node *in     = get_irn_n(node, i);
+               ir_node *new_in = get_new_node(in);
+               set_irn_n(new_node, i, new_in);
        }
-       return res;
+
+       /* Now the new node is complete. We can add it to the hash table for CSE. */
+       add_identities(new_node);
 }
 
-/*
- * Dump a pset containing Firm objects.
- */
-void firm_pset_dump(pset *set) {
+void firm_pset_dump(pset *set)
+{
        void *obj;
 
-       foreach_pset(set, obj) {
+       foreach_pset(set, void*, obj) {
                ir_fprintf(stderr, "%+F\n", obj);
        }
 }