we must clear block+phi-node links
[libfirm] / ir / common / irtools.c
1 /*
2  * Copyright (C) 1995-2011 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 firm_clear_block_phis(ir_node *node, void *env)
55 {
56         (void) env;
57         if (is_Block(node)) {
58                 set_Block_phis(node, NULL);
59         } else if (is_Phi(node)) {
60                 set_Phi_next(node, NULL);
61         }
62 }
63
64 void firm_collect_block_phis(ir_node *node, void *env)
65 {
66         (void) env;
67         if (is_Phi(node))
68                 add_Block_phi(get_nodes_block(node), node);
69 }
70
71 void copy_irn_to_irg(ir_node *n, ir_graph *irg)
72 {
73         ir_op *op = get_irn_op(n);
74         ir_graph *old_irg;
75         ir_node *nn = NULL;
76
77         /* do not copy standard nodes */
78         if (op == op_NoMem)
79                 n = get_irg_no_mem(irg);
80         else if (op == op_Block) {
81                 old_irg = get_irn_irg(n);
82
83                 if (n == get_irg_start_block(old_irg))
84                         nn = get_irg_start_block(irg);
85                 else if (n == get_irg_end_block(old_irg))
86                         nn = get_irg_end_block(irg);
87         }
88         else if (op == op_Start)
89                 nn = get_irg_start(irg);
90         else if (op == op_End)
91                 nn = get_irg_end(irg);
92         else if (op == op_Proj) {
93                 old_irg = get_irn_irg(n);
94
95                 if (n == get_irg_initial_exec(old_irg))
96                         nn = get_irg_initial_exec(irg);
97                 else if (n == get_irg_frame(old_irg))
98                         nn = get_irg_frame(irg);
99                 else if (n == get_irg_initial_mem(old_irg))
100                         nn = get_irg_initial_mem(irg);
101                 else if (n == get_irg_args(old_irg))
102                         nn = get_irg_args(irg);
103         }
104
105         if (nn) {
106                 set_irn_link(n, nn);
107                 return;
108         }
109
110         nn = new_ir_node(get_irn_dbg_info(n),
111                          irg,
112                          NULL,            /* no block yet, will be set later */
113                          op,
114                          get_irn_mode(n),
115                          get_irn_arity(n),
116                          get_irn_in(n) + 1);
117
118
119         /* Copy the attributes.  These might point to additional data.  If this
120            was allocated on the old obstack the pointers now are dangling.  This
121            frees e.g. the memory of the graph_arr allocated in new_immBlock. */
122         copy_node_attr(irg, n, nn);
123         set_irn_link(n, nn);
124
125         /* fix the irg for nodes containing a reference to it */
126         if (ir_has_irg_ref(nn)) {
127                 nn->attr.block.irg.irg = irg;
128         }
129 }
130
131 ir_node *irn_copy_into_irg(const ir_node *node, ir_graph *irg)
132 {
133         ir_node  *block = NULL;
134         ir_op    *op    = get_irn_op(node);
135         int       arity = get_irn_arity(node);
136         dbg_info *dbgi  = get_irn_dbg_info(node);
137         ir_mode  *mode  = get_irn_mode(node);
138         ir_node  *res;
139         int       n_deps;
140         int       i;
141
142         if (op != op_Block)
143                 block = get_nodes_block(node);
144
145         if (op->opar == oparity_dynamic) {
146                 int i;
147                 res = new_ir_node(dbgi, irg, block, op, mode, -1, NULL);
148                 for (i = 0; i < arity; ++i) {
149                         ir_node *in = get_irn_n(node, i);
150                         add_irn_n(res, in);
151                 }
152         } else {
153                 ir_node **ins = get_irn_in(node)+1;
154                 res = new_ir_node(dbgi, irg, block, op, mode, arity, ins);
155         }
156
157         /* copy the attributes */
158         copy_node_attr(irg, node, res);
159
160         /* duplicate dependency edges */
161         n_deps = get_irn_deps(node);
162         for (i = 0; i < n_deps; ++i) {
163                 ir_node *dep = get_irn_dep(node, i);
164                 add_irn_dep(res, dep);
165         }
166
167         return res;
168 }
169
170 ir_node *exact_copy(const ir_node *node)
171 {
172         return irn_copy_into_irg(node, get_irn_irg(node));
173 }
174
175 static ir_node *get_new_node(const ir_node *old_node)
176 {
177         return (ir_node*) get_irn_link(old_node);
178 }
179
180 void irn_rewire_inputs(ir_node *node)
181 {
182         ir_node *new_node;
183         int      arity;
184         int      i;
185
186         new_node = get_new_node(node);
187
188         if (!is_Block(node)) {
189                 ir_node *block     = get_nodes_block(node);
190                 ir_node *new_block = get_new_node(block);
191                 set_nodes_block(new_node, new_block);
192         }
193
194         arity = get_irn_arity(new_node);
195         for (i = 0; i < arity; ++i) {
196                 ir_node *in     = get_irn_n(node, i);
197                 ir_node *new_in = get_new_node(in);
198                 set_irn_n(new_node, i, new_in);
199         }
200
201         /* Now the new node is complete. We can add it to the hash table for CSE. */
202         add_identities(new_node);
203 }
204
205 void firm_pset_dump(pset *set)
206 {
207         void *obj;
208
209         foreach_pset(set, void*, obj) {
210                 ir_fprintf(stderr, "%+F\n", obj);
211         }
212 }