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