plug more leaks
[libfirm] / ir / common / irtools.c
index 0ada115..5accaf5 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.
  *
@@ -21,7 +21,6 @@
  * @file
  * @brief     Some often needed tool-functions
  * @author    Michael Beck
- * @version   $Id$
  */
 #include "config.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);
 }
 
-/* the famous clear_node_and_phi_links() implementation. */
-void firm_clear_node_and_phi_links(ir_node *n, void *env) {
+void firm_clear_node_and_phi_links(ir_node *n, void *env)
+{
        (void) env;
        set_irn_link(n, NULL);
        if (is_Block(n))
@@ -50,24 +50,31 @@ void firm_clear_node_and_phi_links(ir_node *n, void *env) {
                set_Phi_next(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_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);
@@ -111,136 +118,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)) {
+       /* 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));
        }
 }
 
-/*
- * 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;
-
-       if (is_no_Block(n))
-               block = get_nodes_block(n);
-
-       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);
-
+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.  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);
+       /* copy the attributes */
+       copy_node_attr(irg, node, res);
 
-       if (is_Block(n)) {
-               set_Block_MacroBlock(res, get_Block_MacroBlock(n));
+       /* 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;
 }
 
-/*
- * Dump a pset containing Firm objects.
- */
-void firm_pset_dump(pset *set) {
-       void *obj;
-
-       foreach_pset(set, obj) {
-               ir_fprintf(stderr, "%+F\n", obj);
-       }
+ir_node *exact_copy(const ir_node *node)
+{
+       return irn_copy_into_irg(node, get_irn_irg(node));
 }
 
-/**
- * Wrapper for running void function(ir_graph *irg) as an ir_graph pass.
- */
-static int void_graph_wrapper(ir_graph *irg, void *context) {
-       void (*function)(ir_graph *irg) = context;
-       function(irg);
-       return 0;
-}  /* void_graph_wrapper */
-
-/* Creates an ir_graph pass for running void function(ir_graph *irg). */
-ir_graph_pass_t *def_graph_pass(
-       const char *name, void (*function)(ir_graph *irg))
+static ir_node *get_new_node(const ir_node *old_node)
 {
-       struct ir_graph_pass_t *pass = XMALLOCZ(ir_graph_pass_t);
-
-       pass->kind       = k_ir_graph_pass;
-       pass->run_on_irg = void_graph_wrapper;
-       pass->context    = function;
-       pass->name       = name;
-
-       INIT_LIST_HEAD(&pass->list);
-
-       return pass;
-}  /* def_graph_pass */
+       return (ir_node*) get_irn_link(old_node);
+}
 
-/**
- * Wrapper for running void function(ir_graph *irg) as an ir_graph pass.
- */
-static int int_graph_wrapper(ir_graph *irg, void *context) {
-       int (*function)(ir_graph *irg) = context;
-       return function(irg);
-}  /* int_graph_wrapper */
-
-/* Creates an ir_graph pass for running void function(ir_graph *irg). */
-ir_graph_pass_t *def_graph_pass_ret(
-       const char *name, int verify, int dump,
-       int (*function)(ir_graph *irg))
+void irn_rewire_inputs(ir_node *node)
 {
-       struct ir_graph_pass_t *pass = XMALLOCZ(ir_graph_pass_t);
-
-       pass->kind       = k_ir_graph_pass;
-       pass->run_on_irg = int_graph_wrapper;
-       pass->context    = function;
-       pass->name       = name;
+       ir_node *new_node;
+       int      arity;
+       int      i;
 
-       INIT_LIST_HEAD(&pass->list);
+       new_node = get_new_node(node);
 
-       return pass;
-}  /* def_graph_pass_ret */
+       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);
+       }
 
-/**
- * Wrapper for running void function(void) as an ir_prog pass.
- */
-static int void_prog_wrapper(ir_prog *irp, void *context) {
-       void (*function)(void) = context;
-
-       (void)irp;
-       function();
-       return 0;
-}  /* void_graph_wrapper */
-
-/* Creates an ir_prog pass for running void function(void). */
-ir_prog_pass_t *def_prog_pass(
-       const char *name,
-       void (*function)(void))
-{
-       struct ir_prog_pass_t *pass = XMALLOCZ(ir_prog_pass_t);
+       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);
+       }
 
-       pass->kind          = k_ir_prog_pass;
-       pass->run_on_irprog = void_prog_wrapper;
-       pass->context       = function;
-       pass->name          = name;
+       /* Now the new node is complete. We can add it to the hash table for CSE. */
+       add_identities(new_node);
+}
 
-       INIT_LIST_HEAD(&pass->list);
+void firm_pset_dump(pset *set)
+{
+       void *obj;
 
-       return pass;
-}  /* def_prog_pass */
+       foreach_pset(set, void*, obj) {
+               ir_fprintf(stderr, "%+F\n", obj);
+       }
+}