give Bad nodes a mode
[libfirm] / ir / common / irtools.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief     Some often needed tool-functions
23  * @author    Michael Beck
24  * @version   $Id$
25  */
26 #include "config.h"
27
28 #include "pset.h"
29
30 #include <stdlib.h>
31 #include "irnode_t.h"
32 #include "irbackedge_t.h"
33 #include "irtools.h"
34 #include "irprintf.h"
35 #include "irpass_t.h"
36 #include "iropt_t.h"
37
38 void firm_clear_link(ir_node *n, void *env)
39 {
40         (void) env;
41         set_irn_link(n, NULL);
42 }
43
44 void firm_clear_node_and_phi_links(ir_node *n, void *env)
45 {
46         (void) env;
47         set_irn_link(n, NULL);
48         if (is_Block(n))
49                 set_Block_phis(n, NULL);
50         else if (is_Phi(n))
51                 set_Phi_next(n, NULL);
52 }
53
54 void copy_irn_to_irg(ir_node *n, ir_graph *irg)
55 {
56         ir_op *op = get_irn_op(n);
57         ir_graph *old_irg;
58         ir_node *nn = NULL;
59
60         /* do not copy standard nodes */
61         if (op == op_NoMem)
62                 n = get_irg_no_mem(irg);
63         else if (op == op_Block) {
64                 old_irg = get_irn_irg(n);
65
66                 if (n == get_irg_start_block(old_irg))
67                         nn = get_irg_start_block(irg);
68                 else if (n == get_irg_end_block(old_irg))
69                         nn = get_irg_end_block(irg);
70         }
71         else if (op == op_Start)
72                 nn = get_irg_start(irg);
73         else if (op == op_End)
74                 nn = get_irg_end(irg);
75         else if (op == op_Proj) {
76                 old_irg = get_irn_irg(n);
77
78                 if (n == get_irg_initial_exec(old_irg))
79                         nn = get_irg_initial_exec(irg);
80                 else if (n == get_irg_frame(old_irg))
81                         nn = get_irg_frame(irg);
82                 else if (n == get_irg_initial_mem(old_irg))
83                         nn = get_irg_initial_mem(irg);
84                 else if (n == get_irg_args(old_irg))
85                         nn = get_irg_args(irg);
86         }
87
88         if (nn) {
89                 set_irn_link(n, nn);
90                 return;
91         }
92
93         nn = new_ir_node(get_irn_dbg_info(n),
94                          irg,
95                          NULL,            /* no block yet, will be set later */
96                          op,
97                          get_irn_mode(n),
98                          get_irn_arity(n),
99                          get_irn_in(n) + 1);
100
101
102         /* Copy the attributes.  These might point to additional data.  If this
103            was allocated on the old obstack the pointers now are dangling.  This
104            frees e.g. the memory of the graph_arr allocated in new_immBlock. */
105         copy_node_attr(irg, n, nn);
106         set_irn_link(n, nn);
107
108         /* fix the irg for nodes containing a reference to it */
109         if (ir_has_irg_ref(nn)) {
110                 nn->attr.block.irg.irg = irg;
111         }
112 }
113
114 ir_node *irn_copy_into_irg(const ir_node *node, ir_graph *irg)
115 {
116         ir_node  *block = NULL;
117         ir_op    *op    = get_irn_op(node);
118         int       arity = get_irn_arity(node);
119         dbg_info *dbgi  = get_irn_dbg_info(node);
120         ir_mode  *mode  = get_irn_mode(node);
121         ir_node  *res;
122         int       n_deps;
123         int       i;
124
125         if (op != op_Block)
126                 block = get_nodes_block(node);
127
128         if (op->opar == oparity_dynamic) {
129                 int i;
130                 res = new_ir_node(dbgi, irg, block, op, mode, -1, NULL);
131                 for (i = 0; i < arity; ++i) {
132                         ir_node *in = get_irn_n(node, i);
133                         add_irn_n(res, in);
134                 }
135         } else {
136                 ir_node **ins = get_irn_in(node)+1;
137                 res = new_ir_node(dbgi, irg, block, op, mode, arity, ins);
138         }
139
140         /* copy the attributes */
141         copy_node_attr(irg, node, res);
142
143         /* duplicate dependency edges */
144         n_deps = get_irn_deps(node);
145         for (i = 0; i < n_deps; ++i) {
146                 ir_node *dep = get_irn_dep(node, i);
147                 add_irn_dep(res, dep);
148         }
149
150         return res;
151 }
152
153 ir_node *exact_copy(const ir_node *node)
154 {
155         return irn_copy_into_irg(node, get_irn_irg(node));
156 }
157
158 static ir_node *get_new_node(const ir_node *old_node)
159 {
160         return (ir_node*) get_irn_link(old_node);
161 }
162
163 void irn_rewire_inputs(ir_node *node)
164 {
165         ir_node *new_node;
166         int      arity;
167         int      i;
168
169         new_node = get_new_node(node);
170
171         if (!is_Block(node)) {
172                 ir_node *block     = get_nodes_block(node);
173                 ir_node *new_block = get_new_node(block);
174                 set_nodes_block(new_node, new_block);
175         }
176
177         arity = get_irn_arity(new_node);
178         for (i = 0; i < arity; ++i) {
179                 ir_node *in     = get_irn_n(node, i);
180                 ir_node *new_in = get_new_node(in);
181                 set_irn_n(new_node, i, new_in);
182         }
183
184         /* Now the new node is complete. We can add it to the hash table for CSE. */
185         add_identities(new_node);
186 }
187
188 void firm_pset_dump(pset *set)
189 {
190         void *obj;
191
192         foreach_pset(set, void*, obj) {
193                 ir_fprintf(stderr, "%+F\n", obj);
194         }
195 }