be: Replace generate_emitter.pl by generate_emitter_new.pl.
[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  */
25 #include "config.h"
26
27 #include "pset.h"
28
29 #include <stdlib.h>
30 #include "irnode_t.h"
31 #include "irbackedge_t.h"
32 #include "irtools.h"
33 #include "irprintf.h"
34 #include "irpass_t.h"
35 #include "iropt_t.h"
36
37 void firm_clear_link(ir_node *n, void *env)
38 {
39         (void) env;
40         set_irn_link(n, NULL);
41 }
42
43 void firm_clear_node_and_phi_links(ir_node *n, void *env)
44 {
45         (void) env;
46         set_irn_link(n, NULL);
47         if (is_Block(n))
48                 set_Block_phis(n, NULL);
49         else if (is_Phi(n))
50                 set_Phi_next(n, NULL);
51 }
52
53 void firm_clear_block_phis(ir_node *node, void *env)
54 {
55         (void) env;
56         if (is_Block(node)) {
57                 set_Block_phis(node, NULL);
58         } else if (is_Phi(node)) {
59                 set_Phi_next(node, NULL);
60         }
61 }
62
63 void firm_collect_block_phis(ir_node *node, void *env)
64 {
65         (void) env;
66         if (is_Phi(node))
67                 add_Block_phi(get_nodes_block(node), node);
68 }
69
70 void copy_irn_to_irg(ir_node *n, ir_graph *irg)
71 {
72         ir_graph *old_irg;
73         ir_node *nn = NULL;
74
75         /* do not copy standard nodes */
76         switch (get_irn_opcode(n)) {
77         case iro_NoMem:
78                 n = get_irg_no_mem(irg);
79                 break;
80
81         case iro_Block:
82                 old_irg = get_irn_irg(n);
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                 break;
88
89         case iro_Start:
90                 nn = get_irg_start(irg);
91                 break;
92
93         case iro_End:
94                 nn = get_irg_end(irg);
95                 break;
96
97         case iro_Proj:
98                 old_irg = get_irn_irg(n);
99                 if (n == get_irg_initial_exec(old_irg))
100                         nn = get_irg_initial_exec(irg);
101                 else if (n == get_irg_frame(old_irg))
102                         nn = get_irg_frame(irg);
103                 else if (n == get_irg_initial_mem(old_irg))
104                         nn = get_irg_initial_mem(irg);
105                 else if (n == get_irg_args(old_irg))
106                         nn = get_irg_args(irg);
107                 break;
108         }
109
110         if (nn) {
111                 set_irn_link(n, nn);
112                 return;
113         }
114
115         nn = new_ir_node(get_irn_dbg_info(n),
116                          irg,
117                          NULL,            /* no block yet, will be set later */
118                          get_irn_op(n),
119                          get_irn_mode(n),
120                          get_irn_arity(n),
121                          get_irn_in(n) + 1);
122
123
124         /* Copy the attributes.  These might point to additional data.  If this
125            was allocated on the old obstack the pointers now are dangling.  This
126            frees e.g. the memory of the graph_arr allocated in new_immBlock. */
127         copy_node_attr(irg, n, nn);
128         set_irn_link(n, nn);
129
130         /* fix the irg for nodes containing a reference to it */
131         if (ir_has_irg_ref(nn)) {
132                 nn->attr.block.irg.irg = irg;
133         }
134 }
135
136 ir_node *irn_copy_into_irg(const ir_node *node, ir_graph *irg)
137 {
138         ir_node  *block = NULL;
139         ir_op    *op    = get_irn_op(node);
140         int       arity = get_irn_arity(node);
141         dbg_info *dbgi  = get_irn_dbg_info(node);
142         ir_mode  *mode  = get_irn_mode(node);
143         ir_node  *res;
144         int       n_deps;
145         int       i;
146
147         if (op != op_Block)
148                 block = get_nodes_block(node);
149
150         if (op->opar == oparity_dynamic) {
151                 int i;
152                 res = new_ir_node(dbgi, irg, block, op, mode, -1, NULL);
153                 for (i = 0; i < arity; ++i) {
154                         ir_node *in = get_irn_n(node, i);
155                         add_irn_n(res, in);
156                 }
157         } else {
158                 ir_node **ins = get_irn_in(node)+1;
159                 res = new_ir_node(dbgi, irg, block, op, mode, arity, ins);
160         }
161
162         /* copy the attributes */
163         copy_node_attr(irg, node, res);
164
165         /* duplicate dependency edges */
166         n_deps = get_irn_deps(node);
167         for (i = 0; i < n_deps; ++i) {
168                 ir_node *dep = get_irn_dep(node, i);
169                 add_irn_dep(res, dep);
170         }
171
172         return res;
173 }
174
175 ir_node *exact_copy(const ir_node *node)
176 {
177         return irn_copy_into_irg(node, get_irn_irg(node));
178 }
179
180 static ir_node *get_new_node(const ir_node *old_node)
181 {
182         return (ir_node*) get_irn_link(old_node);
183 }
184
185 void irn_rewire_inputs(ir_node *node)
186 {
187         ir_node *new_node;
188         int      arity;
189         int      n_deps;
190         int      i;
191
192         new_node = get_new_node(node);
193
194         if (!is_Block(node)) {
195                 ir_node *block     = get_nodes_block(node);
196                 ir_node *new_block = get_new_node(block);
197                 set_nodes_block(new_node, new_block);
198         }
199
200         arity = get_irn_arity(new_node);
201         for (i = 0; i < arity; ++i) {
202                 ir_node *in     = get_irn_n(node, i);
203                 ir_node *new_in = get_new_node(in);
204                 set_irn_n(new_node, i, new_in);
205         }
206
207         n_deps = get_irn_deps(new_node);
208         for (i = 0; i < n_deps; ++i) {
209                 ir_node *dep     = get_irn_dep(node, i);
210                 ir_node *new_dep = get_new_node(dep);
211                 set_irn_dep(new_node, i, new_dep);
212         }
213
214         /* Now the new node is complete. We can add it to the hash table for CSE. */
215         add_identities(new_node);
216 }
217
218 void firm_pset_dump(pset *set)
219 {
220         foreach_pset(set, void, obj) {
221                 ir_fprintf(stderr, "%+F\n", obj);
222         }
223 }